Как пул соединений MySQL различает соединения в NodeJS (используя mysqljs)?

#mysql #node.js #express #google-cloud-sql

#mysql #node.js #выразить #google-cloud-sql

Вопрос:

Я прочитал всю документацию по объединению в mysqljs, и мне все еще не хватает некоторого контекста. Мой счет за CloudSQL только что вернулся и напомнил мне, что мой старый метод имеет серьезные недостатки. Я ищу некоторый контекст о том, как обрабатывать объединение MySQL в NodeJS для CRM, который выполняет множество SQL-запросов.

Мой старый метод подключения:

 //* SELECT BY ID
app.post(`/api/v1/select/id`, (req, res) => {
  let did = req.body.did;
  let host = req.body.host;
  let user = req.body.user;
  let password = req.body.password;
  let schema = req.body.schema;
  let columns = accountColumns();
  let connection = mysql.createConnection({
    host: host,
    user: user,
    password: password,
    database: schema,
    port: 3306,
  });
  if (connection.state === "disconnected") {
    connection.connect();
  }
  let selectStatement = `SELECT * FROM mydb.schema WHERE id = ${did};`;
  connection.query(selectStatement, (err, results) => {
    if (err) { throw err }
    else {
    res.send(results);
    }
  });
});

//* SELECT BY STATUS
app.post('/api/v1/status', (req, res) => {
  let status= req.body.status;
  let host = req.body.host;
  let user = req.body.user;
  let password = req.body.password;
  let schema = req.body.schema;
  let connection = mysql.createConnection({
    host: host,
    user: user,
    password: password,
    database: schema,
    port: 3306,
  });
  if (connection.state === "disconnected") {
    connection.connect();
  }
  let selectStatement= `SELECT * FROM mydb.schema WHERE status = ${status};`;
  connection.query(selectStatement, (err, results) => {
    if (err) { throw err }
      console.log(err);
    } else {
      res.json({ results });
    } 
  });
});
  

Проблема:

  • Я только что получил счет за облачный SQL GCP стоимостью 200 долларов за 3 недели минимального тестирования
  • Соединения открываются и закрываются каждый раз при попадании в конечную точку (что может быть сотни раз на пользователя в час
  • Это работало в небольших масштабах и с VPS, но это не является устойчивым с GCP Cloud SQL

Новый подход:

Реализуйте объединение, чтобы не было таких абсурдных накладных расходов, связанных с постоянным подключением.

 //* CREATE CONNECTION
let getConnection = (host, user, password, database) => {
let pool = mysql.createPool({
    connectionLimit:10,
    host: host,
    user: user,
    password: password,
    database: database
})
  return pool
}

// Testing the initial connection
app.get('/test/:host/:user/:password/:database', (req, res) => {
  let pool = getConnection(req.params.host, req.params.user, req.params.password, req.params.database)
  pool.getConnection((err, db) => {
    if (err) { throw err }
    else {
      db.query('SELECT * FROM mydb.schema LIMIT 10;', (queryErr, records) => {
        if (queryErr) { throw queryErr }
        else {
          res.send(records)
        }
        db.release() //? do I release it if I know it will continue to be used?
      })
    }
  })
})

// This endpoint will be hit hundreds of times per session. Trying to see if the original connection will carry over without having to reconnect with the config data again
//? Would I need a try catch block here?
app.get('/test2/:host/:user/:password/:database', (req, res) => {
  let pool = getConnection(req.params.host, req.params.user, req.params.password, req.params.database)
  pool.getConnection((err, db) => {
    if (err) { throw err }
    else {
      db.query('SELECT * FROM mydb.schema LIMIT 10;', (queryErr, records) => {
        if (queryErr) { throw queryErr }
        else {
          res.send(records)
        }
        db.release() //? do I release it if I know it will continue to be used?
      })
    }
  })
})
  
  • Есть ли риск, что пользователь A получит данные из базы данных пользователя B, если я полагаюсь на объединение?
  • Как пул распознает запрашиваемое соединение?
  • Если в настоящее время нет открытого пула, будет ли он по умолчанию создан? Нужно ли мне создавать блок try / catch, чтобы убедиться, что это произойдет?
  • Правильный ли этот синтаксис?
  • Если конечная точка ‘test2’ попадает в сотни раз, является ли это разумным способом справиться с этим?

Ответ №1:

Пул соединений — это кэш подключений к базе данных, которые являются общими и используются повторно для повышения задержки соединения и производительности. Когда вашему приложению требуется подключение к базе данных, оно временно заимствует его из своего пула. Когда ваше приложение завершит подключение, оно вернет соединение обратно в пул, где оно может быть повторно использовано в следующий раз, когда вашему приложению потребуется подключение к базе данных. Я бы рекомендовал вам взглянуть на эту документацию для получения более подробной информации.

Cloud SQL автоматически не обеспечивает и не настраивает балансировку нагрузки для вашего экземпляра базы данных. Вам нужно будет настроить пул соединений для распределения запросов на чтение / запись для баз данных между несколькими точками подключения.

Если вы хотите отправить несколько запросов к конечной точке, рекомендуется реализовать стратегию экспоненциального отката, поскольку это предотвращает отправку вашим приложением большого количества запросов на подключение, когда оно не может подключиться к вашей базе данных. Однако, в вашем случае, для node.js модуль mysql автоматически использует экспоненциальные задержки между неудачными попытками подключения.

Что касается риска доступа к данным от разных пользователей вашей базы данных. Я бы посоветовал вам взглянуть на эту документацию, поскольку она описывает, как Cloud SQL работает с пользователями MySQL.