Долгий ответ heartbeats от клиента Node.js при публикации сообщений

Столкнулся с проблемой провалов heartbeats от клиента Node.js (npm-пакет amqplib) при публикации >150к уникальных сообщений в 20 символов каждое.

Отправляю сообщения в цикле следующим кодом:

// Публикация сообщения
function publish(ch, exchange, routing_key, content, callback_publish) {
    let result = false;
    const message = content.toString();
    try {
        // Попытка публикации сообщения
        ch.publish(exchange, routing_key, content, {persistent: true},
                (err, ok) => {
                    if (err) {
                        console.log('[AMQP] Ошибка при публикации сообщения:', err);
                    } else {
                        result = true;
                    }
                    callback_publish(result, message);
                });
    } catch (e) {
        console.log('[AMQP] Исключение при публикации сообщения:', e.message);
        callback_publish(result, message);
    }
}

// ch = ...
// exchange = ...
// routing_key = ...

// Получение сообщений на отправку
const msgs = messages.get_publisher_messages_to_send()

let j = 1;

// Отправка сообщений
for (let i = 0; i < count_messages; i++) {

    const msg = msgs[i];
    const content = Buffer.from(msg);

    console.log('[AMQP] Отправка сообщения:', msg, '(', i + 1,')');

    publish(ch, exchange, routing_key, content, (res, msg) => {
        console.log('[AMQP] Результат отправки', res, 'для сообщения:', msg, '(', j, ')');
        j++;
    });

}

Пример непрерывной публикации 100к сообщений:

Непрерывная публикация 100к сообщений

На графике видим небольшие провалы, которые убираются в heartbeats = 60s.

Но как только объем сообщений увеличивается, например, до 500к сообщений, длина "ступеньки" тоже увеличивается и значения heartbeats = 60s становится недостаточно. В логах RabbitMQ возникает сообщение вида:

2020-05-22 10:34:36.975 [error] <0.24252.1> closing AMQP connection <0.24252.1> (192.168.56.25:58446 -> 192.168.56.17:5672): missed heartbeats from client, timeout: 60s

Мы видим, что если RabbitMQ отправляет некое сердцебиение в клиентское приложение, если оно не отвечает, RabbitMQ отсоединяет его.

Поискав информацию в официальной документации и на просторах интернета можно встретить два решения:

  1. Установить значение heartbeats = 0, тем самым отключив сердцебиение
  2. Увеличить значение heartbeats на более высокое значение, например, heartbeats = 1800s

Первый вариант мне не понравился тем, что отключив heartbeats клиентское приложение не узнает своевременно о недоступности RabbitMQ и это создаст значительный риск для безопасности данных, особенно для публикаторов.

Второй вариант, тоже не совсем понятен. Увеличить на сколько? Если мы увеличим, heartbeats, скажем, до 1800s это сработает, например, для передачи 500к сообщений в 20 символов. А если будет более большой объем данных?

Привожу пример публикации 500к сообщений за раз при heartbeats = 1800s:

Непрерывная публикация 500к сообщений

Мы видим, что интервалы простоя значительно увеличились.

Увеличим объем передаваемых сообщений ещё до 1000к:

Непрерывная публикация 1000к сообщений (last hour

Непрерывная публикация 1000к сообщений (last eight hours)

Видим, что простои увеличились ещё больше.

Есть ли другие решения для того, чтобы клиентское приложение Node.js успевало "снюхиваться" (клиент и сервер отвечают друг другу по двунаправленному протоколу RPC убираясь в интервал 60 секунд) с RabbitMQ?


Ответы (0 шт):