Как установить тайм-аут для открытого соединения пула?

Вопрос или проблема

Я использую knex для подключения к базе данных и продолжаю сталкиваться с ошибкой, когда достигнуто максимальное количество соединений в пуле, говорится: Knex: Timeout acquiring a connection. The pool is probably full. Are you missing a .transacting(trx) call?

Моя конфигурация knex выглядит следующим образом;

const knex = require("knex")({
        client: "pg",
        connection: {
            connectionString: process.env.connection_string,
        },
        pool: {
            min: 0,
            max: 300,
            idleTimeoutMillis: 30000,
            createTimeoutMillis: 30000,
            acquireTimeoutMillis: 30000
            },
        }
    );

knex: "^3.1.0"
pg: "^8.13.0"

Версия Node: 18.18.2
nvm: 0.38.0
npm: 9.8.1

Что я заметил, так это то, что некоторые из моих соединений пула не закрываются автоматически. Есть ли способ установить тайм-аут для соединений пула, если выполнение занимает больше времени, чем я указал, тогда остановить его и закрыть соединение пула. В конфигурации я установил idleTimeoutMillis на 30000мс (30 секунд). Но я не думаю, что это работает так, как я хочу. В данный момент у меня около 100 открытых соединений пула, которые открыты почти 2 часа. Я измеряю количество использованных соединений пула с помощью knex.client.pool.numUsed(). У вас есть какие-нибудь идеи?

Я вижу некоторые обходные пути, такие как;

  • Понижение версии node. Я не хочу этого делать!
  • Добавление параметра propagateCreateError в конфигурацию, что не рекомендуется командой knex!

Ответ или решение

Как установить таймаут для открытых пулов подключений в Knex.js

При работе с библиотекой Knex.js для взаимодействия с базами данных, особенно при использовании пула соединений, важно правильно настраивать параметры конфигурации, чтобы избежать ошибок, связанных с исчерпанием пула соединений. Ваша проблема заключается в ошибке: "Knex: Timeout acquiring a connection. The pool is probably full. Are you missing a .transacting(trx) call?", что указывает на возможные проблемы с управлением соединениями.

Настройка параметров пула соединений

На основании предоставленной конфигурации, вы уже указали несколько ключевых параметров пула:

pool: {
    min: 0,
    max: 300,
    idleTimeoutMillis: 30000,
    createTimeoutMillis: 30000,
    acquireTimeoutMillis: 30000
}

Параметры конфигурации:

  1. min: Минимальное количество подключений в пуле (в вашем случае 0).
  2. max: Максимальное количество подключений в пуле (в вашем случае 300).
  3. idleTimeoutMillis: Время в миллисекундах, после которого неиспользуемые соединения будут закрыты (30 секунд).
  4. createTimeoutMillis: Время в миллисекундах, выделяемое на создание нового соединения (30 секунд).
  5. acquireTimeoutMillis: Время в миллисекундах, после которого запрос на получение соединения будет завершен с ошибкой (30 секунд).

Проблема с не закрытыми соединениями

Ваш наблюдение о 100 открытых подключениях, которые остаются открытыми на протяжении 2 часов, указывает на возможные недостатки в логике вашего приложения или неправильную обработку транзакций и асинхронных операций. Вот что вы можете сделать:

Рекомендации:

  1. Проверка использования транзакций:
    Убедитесь, что вы используете метод .transacting(trx) при работе с транзакциями. Это очень важно, поскольку он позволит обеспечить правильное управление соединениями.

    Пример использования транзакции:

    await knex.transaction(async (trx) => {
       await trx('table_name').insert(data);
    });
  2. Увеличение параметров тайм-аута:
    Если ваша логика требует больше времени для обработки запросов, рассмотрите возможность увеличения acquireTimeoutMillis, чтобы избежать ошибок захвата соединений.

  3. Мониторинг используемых соединений:
    Используйте knex.client.pool.numUsed() для мониторинга числа активно используемых соединений. Это позволит вам видеть, насколько эффективно используются ваши соединения и помогает выявить возможные утечки.

  4. Закрытие соединений вручную:
    В случаях, когда соединения не закрываются автоматически, вы можете добавить логику для закрытия соединений вручную после выполнения операций. Это может быть реализовано через knex.destroy() в конце выполнения запросов:

    process.on('exit', async () => {
       await knex.destroy();
    });
  5. Использование Microsoft Edge Case Handlers:
    Рассмотрите возможность добавления обработчиков исключений для управления непредвиденными ситуациями, чтобы убедиться, что соединения закрываются в любых случаях.

  6. Настройка propagateCreateError:
    Хотя команде Knex не рекомендуется использовать этот параметр, в некоторых случаях он может помочь выявить, в чем проблема. Обдумайте, готов ли вы следовать этому пути.

Заключение

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

Оцените материал
Добавить комментарий

Капча загружается...