В NGINX версии 1.9.1 появилась новая возможность, позволяющая использовать сокетную опцию
(В NGINX Plus эта функциональность появится в выпуске 7, который выйдет позже в этом году.)
У опции
Как показано на рисунке, без

С опцией

Это позволяет на многоядерных системах уменьшить блокировку, когда множество рабочих процессов одновременно принимают соединения. Однако, это также означает, что когда один из рабочих процессов заблокировался на какой-нибудь долгой операции, то это скажется не только на соединениях, которые им уже обрабатывает, но также и на тех, что еще ожидают в очереди.
Для включения
Указание
Тестируем производительность с
Измерения производились с помощью wrk, используя 4 рабочих процесса NGINX на 36 ядерном AWS инстансе. Чтобы свести к минимуму сетевые издержки клиент и сервер работали через loopback-интерфейс, а NGINX был сконфигурирован для отдачи строки

Также были проведены замеры, когда клиент и сервер были запущены на разных машинах и запрашивался html-файл. Как видно из таблицы, с
В данных тестах частота запросов была крайне высокой, при этом они не требовали какой-либо сложной обработки. Различные наблюдения подтверждают, что наибольший эффект от применения опции
Спасибо Sepherosa Ziehau и Yingqi Lu, каждый из которых предложил собственное решение для работы
SO_REUSEPORT
, которая доступна в современных версиях операционных систем, таких как DragonFly BSD и Linux (ядра 3.9 и новее). Данная опция разрешает открывать сразу несколько слушающих сокетов на одном и том же адресе и порту. При этом, ядро будет распределять входящие соединения между ними.(В NGINX Plus эта функциональность появится в выпуске 7, который выйдет позже в этом году.)
У опции
SO_REUSEPORT
есть множество потенциальных вариантов применения для решения различных задач. Так, некоторые приложения могут использовать её для обновления исполняемого кода на лету (NGINX всегда имел такую возможность с незапамятных времен, используя иной механизм). В NGINX включение данной опции увеличивает производительность в отдельных случаях за счет уменьшения блокировок на локах.Как показано на рисунке, без
SO_REUSEPORT
один слушающий сокет разделен между множеством рабочих процессов и каждый из них пытается принимать от него новые соединения:
С опцией
SO_REUSEPORT
у нас есть множество слушающих сокетов, по одному на каждый рабочий процесс. Ядро операционной системы распределяет в какой из них попадет новое соединение (а тем самым какой из рабочих процессов его в итоге получит):
Это позволяет на многоядерных системах уменьшить блокировку, когда множество рабочих процессов одновременно принимают соединения. Однако, это также означает, что когда один из рабочих процессов заблокировался на какой-нибудь долгой операции, то это скажется не только на соединениях, которые им уже обрабатывает, но также и на тех, что еще ожидают в очереди.
Конфигурация
Для включения
SO_REUSEPORT
в модулях http
или stream
достаточно указать параметр reuseport
директивы listen
, как показано в примере:http {
server {
listen 80 reuseport;
server_name example.org;
...
}
}
stream {
server {
listen 12345 reuseport;
...
}
}
Указание
reuseport
при этом автоматически отключает accept_mutex
для данного сокета, поскольку в данном режиме мьютекс не нужен.Тестируем производительность с reuseport
Измерения производились с помощью wrk, используя 4 рабочих процесса NGINX на 36 ядерном AWS инстансе. Чтобы свести к минимуму сетевые издержки клиент и сервер работали через loopback-интерфейс, а NGINX был сконфигурирован для отдачи строки
OK
. Сравнивались три конфигурации: с accept_mutex on
(default), c accept_mutex off
и с reuseport
. Как видно на диаграмме, включение reuseport
в 2-3 раза увеличивает количество запросов в секунду и уменьшает задержки, а также их флуктуацию.
Также были проведены замеры, когда клиент и сервер были запущены на разных машинах и запрашивался html-файл. Как видно из таблицы, с
reuseport
происходит снижение задержек, аналогичное предыдущему замеру, а их разброс снижается еще сильнее (почти на порядок). Другие тесты также демонстрируют хорошие результаты от использования опции. С использованием reuseport
нагрузка распределялась равномерно по рабочим процессам. С включенной директивой accept_mutex
наблюдался дисбаланс в начале теста, а в случае отключения все рабочие процессы занимали больше процессорного времени.Latency (ms) | Latency stdev (ms) | CPU Load | |
---|---|---|---|
Default | 15.65 | 26.59 | 0.3 |
accept_mutex off | 15.59 | 26.48 | 10 |
reuseport | 12.35 | 3.15 | 0.3 |
В данных тестах частота запросов была крайне высокой, при этом они не требовали какой-либо сложной обработки. Различные наблюдения подтверждают, что наибольший эффект от применения опции
reuseport
достигается когда нагрузка отвечает данному паттерну. Таким образом, опция reuseport
не доступна для модуля mail
, поскольку почтовый трафик однозначно не удовлетворяет данным условиям. Мы рекомендуем всем производить собственные замеры, чтобы убедиться в наличии эффекта от reuseport
, а не слепо включать опцию везде, где только это возможно. Некоторые советы по тестированию производительности NGINX вы можете почерпнуть из выступления Константина Павлова на конференции nginx.conf 2014.Благодарности
Спасибо Sepherosa Ziehau и Yingqi Lu, каждый из которых предложил собственное решение для работы
SO_REUSEPORT
в NGINX. Команда NGINX использовала их идеи для реализации, которую мы считаем идеальной.