При записи или поиске данных в кластере Elasticsearch вы можете получить следующую ошибку HTTP 429 или es_rejected_execution_exception
Следующие параметры могут способствовать возникновению ошибки HTTP 429 или es_rejected_execution_exception:
- Типы дата нод и ограничения на поиск или запись
- Высокие значения для метрик
- Активные потоки и потоки очереди
Ошибки HTTP 429 могут возникать из-за запросов поиска и записи в кластер. Отказы также могут исходить от одного узла или нескольких узлов кластера.
Разные версии Elasticsearch используют разные пулы потоков для обработки вызовов API _index. Elasticsearch версий 1.5 и 2.3 использует пул потоков index. Elasticsearch версий 5.x, 6.0 и 6.2 использует пул потоков bulk. Elasticsearch версий 6.3 и более поздних использует пул потоков записи.
Дата ноды и ограничения на поиск или запись
Дата нода имеет фиксированное количество виртуальных центральных процессоров (vCPU). Подставьте количество vCPU в формулу, чтобы получить количество одновременных операций поиска или записи, которые может выполнить узел, прежде чем он попадет в очередь. Если активный поток становится переполненным, он перетекает в очередь и в конечном итоге отклоняется.
Кроме того, существует ограничение на количество поисков на узле или записей на узле, которые можно выполнить. Это ограничение основано на определении пула потоков и номере версии Elasticsearch.
Например, если пяти узлов в кластере Elasticsearch (версия 7.4), узел будет иметь 8 vCPU.
Используйте следующую формулу для расчета максимального количества активных потоков для поисковых запросов:
1 | int ((# количество доступных ядер * 3) / 2) + 1 |
Используйте следующую формулу для расчета максимального количества активных потоков для запросов на запись:
1 | int (# количество доступных ядер) |
Пример расчета операций поиска
(8 VCPUs * 3) / 2 + 1 = 13 операций поиска
Пример расчета операций записи
8 VCPUs = 8 операцуий записи
Для кластера Elasticsearch с пятью узлами вы можете выполнить максимум 65 поисковых операций:
5 нод * 13 = 65 операций
При этом операции записи, может быть 40
5 нод * 8 = 40 операций
Высокие значения для конкретных показателей
Для устранения ошибки 429 проверьте следующие показатели Elasticsearch для вашего кластера:
- IndexingRate: Количество операций индексирования в минуту. Один вызов API _bulk, добавляющий два документа и обновляющий два, считается четырьмя операциями, которые могут быть распределены между одним или несколькими узлами. Если этот индекс имеет одну или несколько реплик, другие узлы в кластере также регистрируют в общей сложности четыре операции индексирования. Удаление документов не учитывается в метрике IndexingRate.
- SearchRate: Общее количество поисковых запросов в минуту для всех шардов на узле данных. Один вызов API _search может вернуть результаты из многих различных хранилищ. Если на одном узле находится пять различных шардов, то узел сообщает "5" для этой метрики, даже если клиент сделал только один запрос.
- CoordinatingWriteRejected: Общее количество отказов, произошедших на координирующем узле. Эти отказы вызваны давлением индексирования, которое накопилось с момента запуска службы.
- PrimaryWriteRejected: Общее количество отказов, произошедших на первичных осколках. Эти отказы вызваны давлением индексирования, которое накопилось с момента последнего запуска службы.
- ReplicaWriteRejected: Общее количество отказов, произошедших на репликах из-за давления индексирования. Эти отказы вызваны давлением индексирования, которое накопилось с момента последнего запуска службы.
- ThreadpoolWriteQueue: Количество задач в очереди в пуле потоков записи. Эта метрика информирует вас о том, отклоняется ли запрос из-за высокой загрузки процессора или высокого параллелизма индексирования.
- ThreadpoolWriteRejected: Количество отклоненных задач в пуле потоков записи.
Примечание: В версии 7.9 размер очереди записи по умолчанию был увеличен с 200 до 10 000. В результате эта метрика больше не является единственным показателем отказов. Используйте метрики CoordinatingWriteRejected, PrimaryWriteRejected и ReplicaWriteRejected для мониторинга отказов в версиях 7.9 и более поздних. - ThreadpoolSearchQueue: Количество задач в очереди в пуле потоков поиска. Если размер очереди постоянно высок, подумайте о масштабировании кластера. Максимальный размер очереди поиска составляет 1 000.
- ThreadpoolSearchRejected: Количество отклоненных задач в пуле поисковых потоков. Если это число постоянно растет, подумайте о масштабировании кластера.
Активные потоки и потоки очереди
При нехватке процессоров или высоком параллелизме запросов очередь может быстро заполниться, что приведет к ошибке HTTP 429. Для мониторинга потоков очереди проверьте метрики ThreadpoolSearchQueue и ThreadpoolWriteQueue.
Чтобы проверить потоки Active и Queue на наличие отказов в поиске, используйте следующую команду:
1 | GET /_cat/thread_pool/search?v&h=id,name,active,queue,rejected,completed |
Чтобы проверить потоки Active и Queue на наличие отказов в записи, замените "search" на "write". Значения rejected и completed в выводе являются кумулятивными счетчиками узлов, которые сбрасываются при запуске новых узлов.
Основная очередь на каждом узле может вмещать от 50 до 200 запросов, в зависимости от того, какую версию Elasticsearch вы используете. Когда очередь переполняется, новые запросы отклоняются.
Ошибки при записи и поиске
Отказы в поиске
Ошибка отказа в поиске указывает на то, что активные потоки заняты, а очереди заполнены до максимального количества заданий. В результате ваш запрос на поиск может быть отклонен. Вы можете настроить журналы службы Elasticsearch так, чтобы эти сообщения об ошибках появлялись в медленных журналах поиска.
Чтобы избежать лишних накладных расходов, установите порог медленного журнала на большую величину. Например, если большинство ваших запросов занимает 11 секунд, а порог равен "10", то службе Elasticsearch потребуется больше времени для записи журнала. Вы можете избежать этих накладных расходов, установив порог медленного журнала на 20 секунд. Тогда только небольшой процент медленных запросов (которые занимают более 11 секунд) будет записываться в журнал.
Отказы в записи
Сообщение об ошибке 429 как отказ в записи указывает на ошибку в очереди. Ошибка es_rejected_execution_exception[bulk] указывает на то, что очередь переполнена и любые новые запросы отклоняются. Ошибка bulk queue возникает, когда количество запросов к кластеру превышает размер bulk queue (threadpool.bulk.queue_size). Объемная очередь на каждом узле может вмещать от 50 до 200 запросов, в зависимости от версии Elasticsearch, которую вы используете.
Вы можете настроить журналы службы Elasticsearch так, чтобы эти сообщения об ошибках появлялись в медленных журналах индекса.
Чтобы избежать лишних накладных расходов, установите порог медленных журналов на большую величину. Например, если большинство ваших запросов занимает 11 секунд, а порог равен "10", Elasticsearch будет тратить дополнительное время на запись журнала. Вы можете избежать этих накладных расходов, установив порог медленного журнала на 20 секунд. Тогда только небольшой процент медленных запросов (которые занимают более 11 секунд) будет записываться в журнал.
Лучшие практики
Вот несколько лучших практик, которые смягчают последствия отказов от записи:
- Когда документы индексируются быстрее, очередь на запись с меньшей вероятностью достигнет своей емкости.
- Настройте размер запроса в соответствии с рабочей нагрузкой и желаемой производительностью.
- Добавьте логику экспоненциального повтора в логику приложения. Логика экспоненциального повторения обеспечивает автоматическое повторение неудачных запросов.
Если ваш кластер постоянно испытывает большое количество одновременных запросов, то логика экспоненциального повторения не поможет устранить ошибку 429.
- Если вы получаете данные из Logstash, настройте количество потоков и размер запроса. Лучше всего установить размер запроса в пределах 3-5 МБ.
- Вертикальное масштабирование. Служба Elasticsearch в значительной степени полагается на кэш файловой системы для ускорения результатов поиска. Количество потоков в пуле потоков на каждом узле для поисковых запросов равно следующему: int((# количество доступных ядер * 3) / 2) + 1. Добавите vCPU, чтобы получить больше потоков для обработки запросов.
- Включите журналы медленного поиска для данного индекса или для всех индексов с разумным пороговым значением. Проверьте, какие запросы выполняются дольше, и внедрите стратегии повышения производительности поиска для ваших запросов.