В NGINX версии 1.9.1 появилось новая возможность, позволяющая использовать сокетную опцию 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 использовала их идеи для реализации, которую мы считаем идеальной.
ссылка на оригинал статьи http://habrahabr.ru/post/259403/
Добавить комментарий