Как предотвратить распространение устаревших/ложных объектов подключений RabbitMQ в плагине управления без обновления сервера?

Как предотвратить распространение устаревших/ложных объектов подключений RabbitMQ в плагине управления без обновления сервера?

Контекст:

Мы используем кластер RabbitMQ 2.8.4 HA для обмена сообщениями в центре обработки данных среднего размера (сотни-тысячи серверов). Функции обмена сообщениями имеют решающее значение для нашего приложения.

Мы используем API клиента C для операций AMQP/RabbitMQ и API HTTP для плагина управления RabbitMQ для периодического мониторинга состояния очереди и отправки оповещений на основе размера/пропускной способности и т. д.

Единственными портами/подключениями, разрешенными от клиентов к серверам обмена сообщениями, являются порты AMQP и HTTP для API управления.

Руководство решило, что в ближайшем будущем простой кластера обмена сообщениями (который приводит к простою определенных запрашивающих частей приложения) неприемлем. Через несколько месяцев это станет возможным, но до тех пор проблемы, связанные с продажами, не позволят нам проводить обслуживание системы обмена сообщениями. Это отстой, но мы (люди инфраструктуры/devops) не можем совершать эти звонки.

Проблема:

Некоторое время мы были жертвами проблемы, обсуждаемой вэтот ТАК вопрос. После шторма подключений или длительного периода, в течение которого новые клиенты подключаются и очень часто используют систему AMQP, API управления RabbitMQ показывает сотни тысяч подключений, которые он перечисляет как «работающие», но которые больше не существуют. netstat, lsofи другие диагностические данные доказывают, что сокеты, соответствующие этим подключениям, не открыты на клиентах; API управления просто не может удалить записи по какой-то причине. rabbitmqctl list_connectionsиногда показывает, что некоторые из несуществующих подключений все еще открыты, но он всегда показывает намного меньше, чем API управления, и его обнаружение «устаревания» кажется лучше, чем у API, и в конечном итоге он удаляет ложные подключения из своего списка.

Когда мы пытаемся удалить одно из этих "ложных" подключений через веб-интерфейс, страница не реагирует на нажатие "удалить", и подключение остается в списке. Когда мы пытаемся удалить его, отправив DELETE в JSON API, мы получаем ошибку сервера 500, указывающую на то, что подключение недействительно, поэтому его нельзя удалить (точно так же, как описано в связанном вопросе SO выше).

После длительного накопления этих несуществующих объектов связи происходят три плохие вещи, в произвольном порядке:

  • Сервер RabbitMQ имеет огромные скачки памяти (которые возникают из ниоткуда; они не соответствуют медленному увеличению скорости соединения в API управления, хотя потребление памяти медленно растет со временем). Это часто приводит к сбою.
  • API управления перестает отвечать на запросы (истекают тайм-ауты на клиентах API).
  • Сам сервер RabbitMQ начинает время от времени отклонять соединения от клиентов AMQP, которые ничего не делают с HTTP/API управления.

В случаях, когда эта проблема начинает нарушать работу нашего приложения, нам приходится делать одно из двух: * Перезапустить весь кластер обмена сообщениями, что плохо, потому что это приводит к кратковременному простою, и плохо, потому что сообщения могут быть потеряны во время этого процесса. * Перезапустить и очистить базу данных API управления, что плохо, потому что мы не можем использовать API управления, и еще хуже, потому что это часто нарушает работу API управления таким образом, что он не запустится должным образом, пока мы не перезапустим весь кластер, как в первом пункте.

Большинство людей, столкнувшихся с подобными проблемами, решают их, обновляясь до RabbitMQ 3.*. У нас нет ни времени, ни разрешения, ни разрешения на простой для такого проекта. Даже в условиях периодических отключений на несколько минут при перезапуске кластера из-за этой проблемы мы не были авторизованы на обновление. Это чисто политическое ограничение, но прискорбная реальность.

Вопрос:

Учитывая, что мы не сможем обновить RabbitMQ в ближайшем будущем и нам необходимо продолжать использовать API управления, как мы можем решить проблему постоянных устаревших соединений, которые вызывают сбои кластера обмена сообщениями?

У нас есть возможность разрабатывать новый/другой клиентский код и запускать задания на самих серверах обмена сообщениями, но у нас нет возможности использовать его rabbitmqctlлокально или через sshкакую-либо из клиентских машин.

Что мы пробовали:

  • Мы пробовали переключать клиентские библиотеки AMQP в надежде, что лучший клиент очистит за собой и не оставит устаревших соединений, но безрезультатно. Проблема сохраняется.
  • Мы пробовали играть с настройками tcp_keepaliveи exit_on_closeTCP на самих серверах RabbitMQ. Никакая комбинация этих значений не решает проблему.
  • Мы создали скрипт, который перебирает все соединения, возвращаемые из списка соединений JSON API, и отправляет DELETE для каждого, которое было открыто дольше, чем требовалось бы, если бы оно использовалось. Все такие запросы встречают ошибки сервера 500, как описано в вопросе SO, ссылка на который приведена выше.

решение1

Периодически приходится все перезапускать.

Другой вариант — бэкпортировать исправление из 3.x в вашу текущую версию, но если вам не разрешено обновляться, вам, вероятно, не разрешат сделать и это. И это почти наверняка будет гораздо больше работы, чем обновление, особенно если код RabbitMQ был значительно переработан.

Пока вы не сможете изменитьполитикаситуации, это ваши варианты.

Связанный контент