Узел MySQL Пул соединений - дождитесь запуска базы данных - PullRequest
3 голосов
/ 15 января 2020

Как проверить, готова ли база данных MySQL для некоторых запросов из узла MySQL Пул соединений?

У меня есть среда Docker, состоящая из трех контейнеров:

  • контейнер 1: веб-сервер
  • контейнер 2: api
  • контейнер 3: база данных

Контейнер базы данных работает с базой данных MySQL. Контейнер API соединяется с этой базой данных. Все три контейнера запускаются одновременно. Контейнер веб-сервера работает через 0,5 с. Контейнер API работает через 2 с. Сервер базы данных работает через 20 с.

В настоящее время API пытается получить доступ к таблицам базы данных, прежде чем база данных будет запущена и запущена. Это приводит к ошибкам типа Отказано в соединении . Следующий сегмент кода всегда заканчивается сообщением «Ошибка запроса базы данных!» когда база данных MySQL еще не запущена:

const sql: string = 'SELECT * FROM sometable;';
MySQL.createPool({
    connectionLimit: 10,
    acquireTimeout: 30000,
    waitForConnections: true,
    database: 'mydatabase',
    host: 'localhost',
    multipleStatements: true,
    password: 'mypassword',
    user: 'root',
}).query(sql, (err, result) => {
    if (result) {
        console.log('Successfully queried database.');
    } else {
        console.log('Error querying database!');
    }
});

Используемые версии:

OS: Ubuntu 19.10
Node: v13.6.0
MySQL (Node API): "@types/mysql": "2.15.8" and "mysql": "2.17.1"
MySQL (Docker Database): mysql:5.7.28
TypeScript: 3.7.4

Я хотел бы проверить (и подождать) готовность базы данных из API, возможно, используя пул соединений, который я использую для запросов. Это возможно?

Ответы [ 3 ]

1 голос
/ 16 января 2020

Повторите попытку соединения с setTimeout():

(ответ в Javascript вместо машинописного текста)

'use strict';

const dbpool = require('mysql').createPool({
    connectionLimit: 10,
    acquireTimeout: 30000,
    waitForConnections: true,
    database: 'mydatabase',
    host: 'localhost',
    multipleStatements: true,
    password: 'mypassword',
    user: 'root',
});

const sql = 'SELECT * FROM sometable;';

const attemptConnection = () =>
  dbpool.getConnection((err, connection) => {
  if (err) {
    console.log('error connecting. retrying in 1 sec');
    setTimeout(attemptConnection, 1000);
  } else {
    connection.query(sql, (errQuery, results) => {
      connection.release();
      if (errQuery) {
        console.log('Error querying database!');
      } else {
        console.log('Successfully queried database.');
      }
    });
  }
});

attemptConnection();

Вот мой тестовый прогон:

$ sudo service mysql stop; node test.js & sudo service mysql start
[1] 24737
error connecting. retrying in 1 sec
error connecting. retrying in 1 sec
$ Successfully queried database.

FYI, программа никогда не заканчивается, потому что ей нужно dbpool.end();

0 голосов
/ 15 марта 2020

Здесь у вас есть вариант, но вам не нужно mysql объединение. Я использую это на моем сервере, и он работает:

const mysql = require('mysql')
var db // global, to use later to db.query
var dbInfo = {
  host     : 'example.org',
  database : 'some_database',
  user     : 'bob',
  password : 'secret'
}

function connectToDb(callback) {
  const attemptConnection = () => {
    console.log('Attempting to connect to db')
    dbInfo.connectTimeout = 2000 // same as setTimeout to avoid server overload 
    db = mysql.createConnection(dbInfo)
    db.connect(function (err) {
      if (err) {
        console.log('Error connecting to database, try again in 1 sec...')
        db.destroy() // end immediately failed connection before creating new one
        setTimeout(attemptConnection, 2000)
      } else {
        callback()
      }
    })
  }
  attemptConnection()
}

// now you simply call it with normal callback
connectToDb( () => {
  console.log('Connection successfully')
  // do some queries
  db.query(..)
})
0 голосов
/ 16 января 2020

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

Попробуйте использовать модуль wait-for- mysql.

waitForMy = require 'wait-for-mysql'
config =
  username: user
  password: pass
  quiet: true
  query: 'SELECT 1'

waitForMy.wait(config)
...