Потоки в Manticore Search

В этой статье мы поговорим о текущих рабочих потоках, реализованных в Manticore Search, и о том, как настроить параметры этих потоков.

В Manticore Search в настоящее время существуют два режима многопроцессорной обработки, контролируемые директивой workers . По умолчанию текущий режим MPM - это thread_pool, с альтернативным режимом threads.

Потоки

В режиме многопроцессорной обработки ‘ threads ’ для каждого входящего сетевого соединения создается новый выделенный поток. Поток активен до тех пор, пока клиент не отключится - то есть, пока соединение активно. В это время поток будет выполнять входящие запросы от соединения.

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

Создание сотен или тысяч потоков в секунду может повлиять на производительность системы в зависимости от доступных ядер ЦП. Наличие значительно большего числа потоков, чем доступных ядер, приводит к тому, что эти потоки начинают конкурировать за ресурсы - одно из которых - ядра ЦП, второе может быть хранилищем данных.

Например, если у нас система с 16 ядрами, но мы позволяем создать 160 потоков поиска, это означает 10 потоков на одно ядро ЦП. Потоки не будут выполняться одновременно, но будут ожидать в очереди, пока ядро ЦП выделит для них такты. Со стороны хранилища у нас может быть 160 потенциальных запросчиков для чтения данных из него. Если хранилище не может продолжать обслуживать потоки без задержек (латентности), задержки могут повлиять на распределение по ядрам ЦП, так как поток может получить зеленый свет для выполнения своих расчетов на ядре ЦП, но должен ожидать данные.
max_children позволяет установить ограничение на количество потоков, которые могут быть активными одновременно. Когда лимит достигается, движок начнет отклонять входящие соединения с ошибкой ‘maxed out’. При установке max_children необходимо помнить, что поток завершается, когда клиент закрывает соединение. Если соединение бездействует, поток останется активным и будет засчитываться в max_children. max_children можно увеличить до предела, который зависит от возможностей сервера обрабатывать количество активных запросов. Это включает в себя вычислительные возможности (ЦП) и операции ввода-вывода (хранилище). Частой ошибкой является увеличение max_children до очень высоких значений. Существует предел, в зависимости от возможностей системы, когда создание слишком большого количества потоков приводит только к замедлению запросов. Если нет ничего другого в плане оптимизации индексов и запросов, целесообразно рассмотреть возможность создания нового сервера поиска для распределения нагрузки.

Thread_pool

В предыдущем разделе мы говорили о том, что потоки имеют свою цену и что соединения могут поддерживать потоки активными, даже если они не используются.

Другой стратегией управления потоками является не создание потока для каждого соединения, а использование пула потоков для обработки работы. В этом случае рабочие потоки не связаны с входящими соединениями, так как соединениями управляет другой класс потоков. Когда демона запускается, он создает определенное количество потоков. Входящие сетевые соединения обрабатываются так называемыми сетевыми потоками, основная задача которых заключается в получении запросов от соединений и перенаправлении их в потоки пула.

Если пул слишком занят (все рабочие обрабатывают запросы), новые запросы отправляются в ожидающую очередь. Сервер будет ‘max out’, если ожидающая очередь заполняется. По умолчанию ограничения не установлено, однако занос запросов в очередь слишком надолго ничего не дает, кроме как получения запросов, на которые уходит много времени. Хорошая идея - установить ограничение на очередь, чтобы сигнализировать о том, что сервер получает больше запросов, чем может обработать. Это можно установить с помощью директивы queue_max_length . В отличие от max_children в модели потоков, где ограничение начинается после определенного числа открытых соединений, в случае thread_pool демон начнет ‘max out’, когда активных запросов станет больше, чем max_children (количество потоков в пуле) + queue_max_length.

В случае thread_pool директива max_children определяет количество потоков в пуле, которые создаются при запуске демона. По умолчанию используется значение 1.5x от количества ядер ЦП. Установка max_children на высокие значения не увеличит производительность или вместимость сервера. Поскольку эти потоки обрабатывают только процессы, они должны иметь доступ к ЦП как можно быстрее.

Установка высоких значений только приведет, как и в предыдущем разделе, к конкуренции за ЦП и более медленной производительности, а также к более медленному запуску демона. В отличие от режима потоков, в котором max_children можно установить в несколько раз выше количества ядер ЦП и значения даже в несколько сотен могут иметь смысл, в случае thread_pool не имеет смысла превышать 2-3x от количества ядер.
По умолчанию для обработки сетевых подключений используется один специализированный поток. Задача потока обычно проста, так как он действует как прокси для thread_pool и в целом может поддерживать хорошее количество трафика. Количество сетевых потоков можно увеличить с помощью net_workers директивы. Увеличение сетевых потоков показывает прирост для установок с экстремальными значениями запросов в секунду.

Сетевой поток также имеет несколько параметров для точной настройки. Сетевой поток может быть не всегда занят, так как могут быть времена (в подсекундных терминах), когда он не получает запросы. Поток перейдет в состояние сна и потеряет свою приоритетность к CPU. Время, потраченное на пробуждение или возвращение на свое место к CPU, небольшое, но для высокой производительности каждую миллисекунду имеет значение.

Чтобы справиться с этим, можно активировать занятое ожидание с помощью директивы net_wait_tm . Если значение net_wait_tm положительное, поток будет “тикать” CPU каждые 10*net_wait_tm (где значение net_wait_tm представляет собой миллисекунды). Если net_wait_tm равно нулю, занятое ожидание будет работать постоянно - следует отметить, что это приведет к дополнительной нагрузке на CPU, даже если сетевой поток не получает много трафика. Чтобы отключить занятое ожидание, следует использовать отрицательное значение -1. По умолчанию net_wait_tm имеет значение 1, что означает, что занятое ожидание тикает каждые 10мс.

Сетевой поток также может быть ограничен. Опция net_throttle_accept накладывает ограничение на количество клиентов, которых сетевой поток может принять одновременно, а net_throttle_action объясняет, сколько запросов обрабатывать за итерацию. По умолчанию ограничения не применяются. Ограничение сетевого потока имеет смысл в условиях высокой нагрузки.

Одним из аспектов, который часто неправильно понимается, является связь между max_children и dist_threads . dist_threads отвечает за многопоточность некоторых операций, таких как локальный распределенный индекс, сниппеты с load_files или команду CALL PQ . Однако это вспомогательные потоки, и они не учитываются в директиве max_children , которая учитывает только основные потоки запросов.

Установить Manticore Search

Установить Manticore Search