Вопрос или проблема
У нас есть кластер из 6 экземпляров Elasticsearch (версия 8.13), управляемый с помощью Docker Swarm в Google Cloud. У нас есть несколько индексов с 2 репликами каждый. Нам нужно было обновить наш кластер (увеличить объем памяти), поэтому план состоял в том, чтобы выключить один экземпляр, увеличить объем памяти, перезапустить его и повторить это для каждого другого экземпляра.
Конфигурация клиента выглядит следующим образом:
hosts:
- scheme: http
host: "es8_node"
port: 9200
timeout: 10
sniff_on_start: True
sniff_on_node_failure: True
sniff_timeout: 15
Когда первый экземпляр вернулся к работе, здоровье кластера быстро восстановилось до 100%, и все шардов были назначены, но время ответа по некоторым запросам все еще оставалось очень высоким.
Даже через час некоторые запросы по-прежнему имели очень высокое время отклика, но мне удалось найти эту запись в логах Python-сервиса:
Узел <Urllib3HttpNode(http://10.0.3.53:9200)> потерпел неудачу 271 раз подряд, выставив 30-секундный тайм-аут.
Оказалось, что экземпляр, который я перезапустил, получил новый IP-адрес, и даже после стольких сбоев он не был удален из списка узлов. Почему? Эти повторные попытки и восстановление этого узла вызывали высокое время ответа.
Разве sniff_on_node_failure
не должен был решить эту проблему? В списке узлов, который я получаю из Elasticsearch (_cat/nodes
), этот узел больше не указан. Почему он не был удален?
Ответ или решение
Ваш вопрос об исчезающем узле в клиенте Python для Elasticsearch и его конфигурации вызывает несколько важных моментов, которые необходимо рассмотреть.
Причина проблемы
Когда вы восстановили первый узел и он по какой-то причине получил новый IP-адрес, возможно, вы столкнулись с несколькими проблемами. Несмотря на то, что узел не отображается в результате команды _cat/nodes
, клиент Python все еще считает его активным в течение определенного времени из-за механизма, который управляет статусом узлов.
Код ошибки, который вы видите в логах — Node <Urllib3HttpNode(http://10.0.3.53:9200)> has failed for 271 times in a row, putting on 30 second timeout
— говорит о том, что клиент не может подключиться к узлу, который по каким-то причинам стал недоступен. Здесь важно понимать, что клиент Python имеет встроенные таймауты и механизм повторных попыток, которые позволяют ему продолжать попытки подключения к несуществующему или недоступному узлу.
Почему sniff_on_node_failure
не срабатывает?
Опция sniff_on_node_failure
предназначена для повторного сканирования узлов, чтобы обновить их список при первом неудачном подключении. Однако в вашем случае, если клиент не получает ответ от узла по IP-адресу в течение определенного времени, он может не инициировать повторный "снифф" узлов. Невозможность подключения может приводить к тому, что произошли тайм-ауты, и функция sniff_on_node_failure
не будет вызвана.
Решения
-
Увеличьте тайм-ауты на клиенте: Вы можете попробовать увеличить значения параметров
timeout
иsniff_timeout
, чтобы дать клиенту больше времени для проверки доступности узла. -
Используйте статические IP-адреса: Если возможно, рассмотрите возможность присвоения статических IP-адресов вашим контейнерам Elasticsearch, чтобы избежать проблем, связанных с изменением IP-адресов при перезапуске.
-
Ручная профилактика: Если узел все еще фигурирует в логах клиента даже после того, как вы убедились, что он отсутствует в кластере, можно вручную сбросить список узлов в клиенте, вызвав команду сброса для разрешения проблемы с подключением:
from elasticsearch import Elasticsearch es = Elasticsearch( hosts=[{"host": "es8_node", "port": 9200}], timeout=10, sniff_on_start=True, sniff_on_node_failure=True, sniff_timeout=15 ) es.transport.sniff() # Сбросьте информацию о узлах вручную
-
Мониторинг и алерты: Настройте мониторинг и алерты для узлов Elasticsearch с использованием инструментов вроде Kibana или Prometheus, чтобы более быстро реагировать на подобные инциденты.
Заключение
Исходя из вышесказанного, ваша проблема связана с механизмом управления узлами в клиенте Python. Увеличение тайм-аутов, использование статических IP-адресов и ручная профилактика через метод sniff()
могут помочь вам избежать подобного поведения в будущем.