Хабр Курсы для всех
РЕКЛАМА
Практикум, Хекслет, SkyPro, авторские курсы — собрали всех и попросили скидки. Осталось выбрать!
nginx: [emerg] duplicate listen options for 0.0.0.0:80 in /etc/nginx/common.conf:1
cat common.conf
listen 80 reuseport;
включение reuseport в 2-3 раза увеличивает количество запросов в секундуПодтверждаю, пробовал на siege, в моем случае не в 2-3 раза, но на реальном тесте, а не
Transactions 5099 hits
Availability 100.00 %
Elapsed time 2.97 secs
Data transferred 7.86 MB
Response time 0.00 secs
Transaction rate 1716.83 trans/sec
Throughput 2.65 MB/sec
Concurrency 14.90
Successful transactions 5099
Failed transactions 0
Longest transaction 0.11
Shortest transaction 0.00
Transactions 3924 hits
Availability 100.00 %
Elapsed time 2.97 secs
Data transferred 5.89 MB
Response time 0.01 secs
Transaction rate 1320.77 trans/sec
Throughput 1.98 MB/sec
Concurrency 14.90
Successful transactions 3924
Failed transactions 0
Longest transaction 0.13
Shortest transaction 0.00
nginx: [emerg] reuseport is not supported on this platformSO_REUSEPORT#if (NGX_HAVE_REUSEPORT)
...
#else
log("reuseport is not supported on this platform, ignored");
#endif
у ядра гораздо больше возможностей организовать оптимальное распределение входящих соединенийНе совсем так. Точнее даже совсем не так. Ядро понятия не имеет, когда тот или иной рабочий процесс освободится и сможет забрать соединение. Сейчас Linux просто раскладывает их псевдослучайно. Такое распределение хорошо только в том случае, если у нас все соединения одинаковые с точки зрения ресурсов, которые потребуются для их обработки. Но это более-менее так только в синтетических тестах. В реальности все сложнее. И какому-то из рабочих процессов могут в итоге насыпать тяжелых запросов в то время, как другой будет простаивать.
Я теперь понял, что никакой сериализации сокетов больше нет, грубо говоря, epoll() и т.д. так же больше не нужны? Теперь ядро само пробуждает потоки по очереди?Epoll никуда не делся, он всегда был отдельный в каждом рабочем процессе. Помимо принятия новых соединений, рабочие процессы делают много другой работы: читают запросы, отправляют ответы, обрабатывают таймауты, устанавливают соединения с бекендами. Рабочий процесс не может ждать на accept(), ему нужно работать с другими событиями, мониторить другие дескрипторы. Поэтому нужен механизм уведомления о событиях.
Как было:Если интенсивность поступления новых соединения маленькая — то да. Для борьбы с этим эффектом как раз и существует accept_mutex, который отключает нотификацию у отдельных процессов в этом случае. Это можно видеть во втором бенчмарке, его включение снижает нагрузку на CPU.
все воркеры спят -> new socket data -> notification всех воркеров -> все воркеры вступают в борьбу за лок -> один захватывает лок и принимает коннект, остальные засыпают
Как стало:См. выше. Воркерам не позволительно ждать на accept(), им нужно другие соединения обрабатывать.
воркеры спят в accept() -> new socket data -> ядро выбирает любой воркер, пробуждает и т.д.
Тогда штука реально опасная, особенно учитывая политику распределения коннектов. Какой-нибудь залогиненный пользователь для которого страница генерируется гораздо дольше чем для анонимного всегда будет попадать на один и тот же воркер, забивая его.Не настолько на самом деле. Псевдослучайное распределение будет раскидывать новые подключения от него случайным образом. С тем же успехом и раньше, установив keepalive соединение, можно было нагрузить запросами один рабочий процесс больше другого. Но в масштабах десятков и сотен тысяч соединений — все это довольно незначительные эффекты.
Однако, это также означает, что когда один из рабочих процессов заблокировался на какой-нибудь долгой операции, то это скажется не только на соединениях, которые им уже обрабатывает, но также и на тех, что еще ожидают в очереди.
есть ли какие-то причины не включать reuseport по умолчанию?
Увеличиваем производительность с помощью SO_REUSEPORT в NGINX 1.9.1