Как можно предотвратить распространение устаревших / ложных объектов соединения RabbitMQ в плагине управления без обновления сервера?
Контекст:
Мы используем кластер RabbitMQ 2.8.4 HA для обмена сообщениями в центрах обработки данных среднего размера (от сотен до тысяч серверов). Функции обмена сообщениями имеют решающее значение для нашего приложения.
Мы используем клиентский API C для операций AMQP/RabbitMQ и HTTP API для плагина управления RabbitMQ для периодического мониторинга состояния очереди и отправки предупреждений в зависимости от размера / пропускной способности / и т. Д.
Единственные порты / соединения, разрешенные от клиентов к серверам обмена сообщениями, находятся на портах AMQP и на HTTP для API управления.
В ближайшем будущем руководство решило, что простои кластера обмена сообщениями (что приводит к простоям для определенных запрашивающих частей приложения) недопустимы. Через несколько месяцев это станет возможным, но до тех пор, пока проблемы, связанные с продажами, не позволят нам обслуживать систему обмена сообщениями. Это отстой, но мы (инфраструктура / люди из devops) не можем делать эти звонки.
Проблема:
Некоторое время мы становились жертвами проблемы, обсуждаемой в этом вопросе SO. После шторма соединения или длительного периода, в течение которого новые клиенты очень часто подключаются и используют систему 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_close
Настройки TCP на самих серверах RabbitMQ. Никакая комбинация этих значений не решает проблему. - Мы создали скрипт, который перебирает все соединения, возвращаемые из списка соединений JSON API, и отправляет DELETE для каждого, которое было открыто дольше, чем это должно было бы быть при использовании. Все такие запросы встречаются с 500 ошибками сервера, как описано в вопросе SO, связанном выше.
1 ответ
Вы продолжаете перезапускать все периодически.
Другой вариант - перенести исправление из версии 3.x в вашу текущую версию, но если вам не разрешено обновляться, вам, вероятно, тоже не удастся это сделать. И это почти наверняка будет гораздо больше работы, чем обновление, особенно если код RabbitMQ был значительно реорганизован.
Пока вы не можете изменить политику ситуации, это ваши варианты.