...

NGINX Worker Connections — масштабирование тысяч запросов для обеспечения максимальной производительности хостинга

Я целенаправленно масштабирую рабочие процессы nginx, чтобы обрабатывать тысячи одновременных запросов с низкой Латентность для работы. Ключ заключается в сбалансированном сочетании параметров worker_processes, worker_connections, файловых дескрипторов и События.

Центральные пункты

  • Вместимость = worker_processes × worker_connections; в случае обратного прокси часто определяется количеством подключений клиентов и исходных серверов удвоился.
  • Дескрипторы файлов (worker_rlimit_nofile, ulimit) в соответствии с предполагаемой нагрузкой на соединения лифт.
  • События-Блок с использованием epoll, multi_accept и очередей ядра при высокой нагрузке подстригать.
  • Мониторинг с помощью stub_status и нагрузочных тестов для итеративных Персонализация.
  • Масштабирование комбинировать по вертикали и горизонтали, конфигурация отсоединить.

Архитектура NGINX: мастер, рабочие процессы и события

NGINX использует главный процесс, который запускает несколько рабочих процессов и эффективно управляет ими с помощью События обслуживает. Вместо обработки потоков на каждый запрос каждый рабочий процесс обрабатывает множество соединений в неблокирующем режиме с помощью модели, основанной на событиях, с низким Накладные. Я устанавливаю значение параметра worker_processes равным «auto», чтобы NGINX мог эффективно использовать ядра процессора и каждому процессу выделялся собственный рабочий процесс. Таким образом я лучше распределяю входящие соединения и снижаю задержку в часы пиковой нагрузки низкий. Для более подробного ознакомления с планированием процессов рекомендую ознакомиться с Оптимизация рабочих процессов, поскольку правильная параллелизация определяет реальную пропускную способность соединений. Решающим фактором является то, чтобы значение параметра `worker_connections` для каждого рабочего процесса было подобрано рационально, чтобы при умножении на количество процессов получалась ожидаемая Пиковая нагрузка покрывает.

Формула пропускной способности: worker_processes × worker_connections

Приблизительную пропускную способность я рассчитываю по формуле worker_processes × worker_connections, при этом проксируемые запросы часто занимают по два соединения на каждый пользовательский доступ, что, соответственно, уменьшает фактическое число вдвое может. Во многих стандартных установках изначально задано 512 соединений на каждый рабочий процесс, чего для производственных нагрузок зачастую бывает недостаточно ist. На практике начальные значения обычно составляют от 1024 до 4096 и зависят от профиля трафика и аппаратного обеспечения. Я планирую с запасом, то есть как минимум в два раза больше измеренной пиковой нагрузки, чтобы надежно справиться с пиковыми нагрузками смягчить. Важно проводить проверку с помощью тестов и реальных показателей, чтобы цифры не превратились в теоретическую игру стать.

Сценарий рабочие_процессы рабочие_соединения Теоретически, макс. Эффективно (прокси) FD на одного работника
Небольшой сайт 2 1024 2048 ~1024 ≥1024
API со средней нагрузкой 4 2048 8192 ~4096 ≥2048
Часы пик в магазине 8 4096 32768 ~16384 ≥4096

HTTP/1.1, HTTP/2 и TLS: влияние на рабочие процессы и задержку

Протоколы определяют профиль соединения. При использовании HTTP/1.1 я часто наблюдаю большое количество одновременных TCP-соединений на одного клиента, тогда как HTTP/2 сводит их количество к нескольким потокам, которые при этом загружены сильнее пучки. Это позволяет сэкономить на дескрипторах файлов, но при этом увеличивает нагрузку на буферы и механизм приоритезации. При использовании TLS я слежу за повторным использованием сессий, чтобы не проводить ресурсоемкие процедуры установления соединения при каждом запросе замедлиться. Общий кэш сеансов и оптимальные значения таймаутов позволяют снизить пиковые нагрузки на ЦП. Кроме того, я не устанавливаю слишком низкое значение keepalive_requests, чтобы долгосрочные соединения могли проявить свои преимущества разыгрываться. Для HTTP/2 я рассчитываю более высокую степень параллелизма на каждое соединение и обеспечиваю достаточно большой размер буферов отправки и приёма, не задействуя память растрачивать. При смешанном трафике я составляю план, исходя из консервативных оценок, и проверяю последствия для каждого варианта протокола в Тест.

Правильная настройка дескрипторов файлов и параметра ulimit

Каждому соединению требуется как минимум один дескриптор файла, а в случае обратного прокси — зачастую два, поэтому низкие значения ulimit создают серьезные Границы установить. Я увеличиваю значение worker_rlimit_nofile таким образом, чтобы было возможно реализовать worker_processes × worker_connections и оставались резервы для логов, сокетов и кэшей. На системном уровне я корректирую файлы limits.conf и fs.file-max, чтобы операционная система разрешала запланированное количество открытых файлов и не прерывала работу преждевременно тормоза. С помощью команды `ulimit -n`, а также параметра Systemd (LimitNOFILE) я проверяю, сохраняется ли настройка и соответствует ли она требованиям NGINX. Если игнорировать этот параметр, то, несмотря на высокое значение `worker_connections`, внезапно начнут возникать отклоненные соединения и будет расти Задержки.

Точная настройка блока событий: epoll, multi_accept, Backlogs

В Linux я использую epoll, так как этот механизм позволяет эффективно обрабатывать большое количество соединений с помощью асинхронных События обрабатывает. При значении параметра `multi_accept` равном `on` рабочий процесс принимает несколько новых соединений за одно событие, что сглаживает пиковые нагрузки и сокращает задержки при приеме снижает. Я соответствующим образом увеличиваю такие параметры ядра, как net.core.somaxconn и net.ipv4.tcp_max_syn_backlog, чтобы очереди Accept не переполнялись во время пиковых нагрузок. Оптимизации TIME_WAIT, такие как tcp_tw_reuse, снижают заторы на портах и поддерживают кривую пропускной способности высокий. Чтобы глубже разобраться в вопросах параллелизма и очередей, стоит ознакомиться с Оптимизация пула потоков, хотя NGINX в основном работает по событиям и благодаря этому очень экономичен масштабирование.

Правильное распределение сокетов списка: reuseport, backlog и accept_mutex

При очень большом количестве одновременных подключений я активно масштабирую канал приема. С помощью reuseport Каждому рабочему процессу выделяется собственный сокет прослушивания; благодаря этому устраняется конкуренция при обработке запросов accept, а нагрузка равномерно распределяется по всем ядрам. Я явно задаю размер списка ожидающих подключений (listen backlog), чтобы справиться с кратковременными пиками нагрузки. В этой конфигурации accept_mutex больше не требуется. Однако без reuseport accept_mutex, напротив, помочь, чтобы смягчить эффект «стадного поведения» при обработке запросов Accept. Важно: размеры списка ожидающих запросов в NGINX и ядре (somaxconn) должны сочетаться, иначе эффект будет потерян.

events {
    use epoll;
    worker_connections 4096;
    # accept_mutex on;   # с reuseport обычно не требуется
}

server {
    listen 443 ssl http2 reuseport backlog=65535;
    # ...
}

Кроме того, при необходимости я привязываю рабочие процессы к ядрам ЦП (worker_cpu_affinity), чтобы обеспечить стабильность кэш-строк и нагрузки на IRQ. В средах с выраженной архитектурой NUMA это позволяет избежать ненужных Поперечное движение в памяти.

Обратный прокси, источники трафика и Keep-Alive

В качестве обратного прокси-сервера NGINX часто поддерживает по два соединения на каждый запрос: одно с клиентом и одно с бэкендом, что позволяет реалистично планировать пропускную способность двойной имеет значение. Я целесообразно включаю Keep-Alive, чтобы соединения с вышестоящими серверами оставались повторно используемыми, а накладные расходы на каждый запрос уменьшается. Таким образом я снижаю нагрузку на PHP-FPM, сервер приложений или микросервисы и освобождаю слоты для новых сеансов пользователей. Баланс между таймаутами, временем простоя и повторным использованием определяет, насколько корректно происходит рециклирование соединений стать. Те, кто хочет ознакомиться с основными сведениями по этому вопросу, найдут их в Постоянные соединения практические рекомендации по загрузке и оптимизации работы сетиИспользовать.

Пулы Upstream, таймауты и повторные попытки

Чтобы рабочие процессы не ждали медленные бэкенды, я использую оптимальные таймауты и тщательно выверенные повторные попытки. Пул Keepalive на стороне сервера я поддерживаю достаточно большим, чтобы соединения оставались «теплыми», но не настолько большим, чтобы неактивные файловые дескрипторы занимали память и слоты связать. Я ограничиваю количество повторных попыток несколькими и переключаюсь только в случае явных ошибок передачи данных — таким образом я предотвращаю эффект «громового стада» при кратковременных сбоях бэкенда.

upstream app_backend {
    server 10.0.0.11:8080 max_fails=3 fail_timeout=10s;
    server 10.0.0.12:8080 max_fails=3 fail_timeout=10s;
    keepalive 64;  # — многократно используемые соединения с серверами вышестоящего уровня
}

server {
    location / {
 proxy_pass http://app_backend;
 proxy_connect_timeout   2s;
        proxy_read_timeout 15s;
 proxy_send_timeout 15s;
 proxy_next_upstream     error timeout http_502 http_503;
 proxy_next_upstream_tries 2;
    }
}

Одновременно я настраиваю параметры Keep-Alive (таймауты, количество запросов на соединение), чтобы быстро освободить ресурсы, занятые редко активными клиентами, разрешить.

Разумное планирование масштабирования: сочетание вертикального и горизонтального подходов

Для обеспечения высоких показателей трафика я использую как вертикальное, так и горизонтальное масштабирование одновременно в Рассмотрение. Вертикальное масштабирование я осуществляю за счет увеличения количества ядер процессора, объема оперативной памяти, использования быстрых SSD-накопителей и оптимизации сетевой конфигурации, чтобы каждый рабочий процесс работал плавно работает. Горизонтальное масштабирование я осуществляю с помощью безсостоятельных узлов NGINX, централизованно управляемой конфигурацией и распределенным ведением журналов, чтобы общая пропускная способность увеличивалась линейно растет. Локальные кэши и четко определенные политики, реализуемые через Maps или API, позволяют быстро внедрять изменения. Такое разделение снижает побочные эффекты и помогает адаптироваться к новым моделям трафика без необходимости перенастройки каждого узла обслуживать.

Точка зрения хостинга: задержка, частота сбоев и пользовательский опыт

Слишком малое количество worker_connections приводит к отклонению подключений, таймаутам и ухудшению Пользовательский опыт. Динамические приложения, такие как CMS или интернет-магазины, сразу же ощущают это, поскольку при загрузке страницы генерируется несколько запросов к бэкенду, и слоты быстрее короткие . Поэтому я начинаю с умеренных значений, таких как 1024 или 2048 на каждый рабочий процесс, и постепенно увеличиваю их на основе реальных результатов измерений. Параллельно с этим я поддерживаю высокую производительность вышестоящих служб и обеспечиваю достаточное количество дескрипторов файлов, чтобы не возникало искусственных Лимиты работают. Результаты тестов показывают, что тщательно настроенные платформы обеспечивают здесь реальные преимущества и надежно справляются с пиковыми нагрузками перехват.

Память, буферизация и пути ввода-вывода

Каждое соединение занимает оперативную память для метаданных и буферов. Я настраиваю параметры `proxy_buffers`, `client_body_buffer_size` и `large_client_header_buffers` таким образом, чтобы они вмещали типичные запросы, но при этом не занимали слишком много оперативной памяти из-за единичных аномальных запросов связать. Для статического контента функции sendfile и tcp_nopush ускоряют доставку, тогда как tcp_nodelay предназначена для небольших ответов, для которых задержка имеет критическое значение Важно остается. Если ресурсы хранятся на медленном хранилище, параметры aio threads и thread_pool помогают смягчить последствия блокировки. С помощью open_file_cache я сокращаю количество обращений к файлам и вызовов stat(), но при этом учитываю дополнительную потребность в файловых дескрипторах. Журналы я записываю с буферизацией (access_log … buffer=… flush=…), чтобы пиковые нагрузки на ввод-вывод не влияли на время отклика влиять.

Баланс между безопасностью и производительностью TLS

Процесс установления соединения TLS требует значительных вычислительных ресурсов процессора. Я сочетаю повторное использование сеансов с умеренными параметрами ключей и включаю настраиваемые оптимизации, такие как кэши сеансов и тикеты, если это целесообразно с точки зрения эксплуатации подходит. Оптимальное соотношение безопасности и производительности позволяет поддерживать стабильные задержки без ущерба для качества шифрования. При повышенной нагрузке я отслеживаю 95-й и 99-й процентили отдельно, так как в противном случае пиковые значения TLS могут скрываться за средними показателями скрыть. HTTP/2 снижает нагрузку на количество соединений, однако требует тщательного подхода к управлению потоком данных и сжатию заголовков, чтобы контролировать нагрузку на ЦП и память сохранить.

Устойчивость в условиях перегрузки: пределы и плавное сбрасывание нагрузки

Для обеспечения конфиденциальности необходимо целенаправленное Формирование незаменимо при пиковой нагрузке. С помощью limit_conn я ограничиваю количество параллельных соединений на один ключ (например, IP-адрес или сеанс), а limit_req сдерживает всплески нагрузки и защищает бэкэнды от синхронных Штормы. Критические конечные точки я изолирую с помощью более строгих правил, чем статические ресурсы. Если нагрузка возникает кратковременно, я возвращаю четко определенные коды ошибок 429/503 с параметром Retry-After, а не обрабатываю все запросы равномерно умереть с голоду . Я приостанавливаю затянувшиеся соединения (lingering_close), чтобы контролируемо освобождать ресурсы и предотвращать появление паттернов Slowloris опровергнуть. Такое активное отсеивание позволяет поддерживать задержку p95/p99 в допустимом диапазоне, даже если общий спрос временами превышает номинальную пропускную способность ложь.

Интеграция контейнеров и систем: устранение ограничений там, где они возникают

В контейнерах часто действуют более строгие ограничения. Я проверяю ограничения cgroup (CPU, RAM), соответствующим образом настраиваю ulimit -n внутри контейнера и фиксирую LimitNOFILE в определении службы. Параметры sysctl, такие как somaxconn и tcp_max_syn_backlog, должны быть установлены на Хозяин вступают в силу; пространства имён не всегда прозрачно изолируют эти настройки. На оркестрированных платформах я планирую ресурсы на каждый под/узел, привязываю рабочие процессы к выделенным ядрам и слежу за стабильностью сетевых путей (например, избегаю ненужных NAT-переходов), чтобы кривая задержки тихий остается. При выполнении последовательных обновлений я использую `worker_shutdown_timeout`, чтобы корректно закрыть существующие соединения завершиться.

Мониторинг и итеративная оптимизация

Без видимых результатов меры по оптимизации остаются Риск. Я включаю stub_status или аналогичные инструменты, чтобы постоянно отслеживать активные соединения, коэффициенты принятия и отказов. В ходе нагрузочных тестов я моделирую реалистичные схемы доступа и выявляю узкие места в очередях принятия, задержках вверх по потоку или загрузке ЦП—Насыщенность. Затем я осторожно настраиваю параметры worker_connections, количество процессов, ограничения на файлы и параметры TCP, а затем вновь проверяю результат. Этот цикл обеспечивает надежную работу платформы и предотвращает неожиданности в неблагоприятные Times.

Пример конфигурации и алгоритм расчёта

Допустим, я ожидаю 2000 одновременных запросов в режиме «in-flight» в часы пик и использую обратный прокси-сервер, тогда я примерно рассчитываю 4000 слотов для соединений плюс Буфер. Если NGINX работает на четырёх ядрах процессора, я обычно начинаю с настроек worker_processes auto и worker_connections от 1000 до 2000 на каждый рабочий процесс. Лимит файловых дескрипторов я устанавливаю для каждого рабочего процесса на достаточно высоком уровне, чтобы для соединений, журналов и внутренних сокетов хватало Место . Блок Events я настраиваю на epoll, включаю multi_accept и увеличиваю размеры очередей ядра в соответствии с моим пиковым трафиком. Минималистичный фрагмент кода может выглядеть примерно так, после чего я его дорабатываю с помощью тестов производительности Голосуйте:

worker_processes  auto;
worker_rlimit_nofile  65535;

events {
    use epoll;
    worker_connections  2048;
    multi_accept on;
}

http {
    keepalive_timeout   65;
    sendfile on;
    # дополнительные настройки прокси/кеша ...
}

Кроме того, я дополняю оптимизации списков и верхнего уровня, чтобы доработать обработку запросов и бэкенд-путь в условиях нагрузки:

events {
    use epoll;
    worker_connections 4096;
    # worker_cpu_affinity auto;  # при необходимости фиксированное назначение ядер
}

http {
    # Примеры оптимизаций TLS и сеансов
    ssl_session_cache    shared:SSL:50m;
    ssl_session_timeout  1h;

 upstream app_backend {
 server 10.0.0.11:8080;
 server 10.0.0.12:8080;
 keepalive 64;
    }

    server {
 listen 443 ssl http2 reuseport backlog=65535;

 location / {
 proxy_pass http://app_backend;
 proxy_connect_timeout     2s;
            proxy_read_timeout 15s;
 proxy_next_upstream error timeout http_502 http_503;
 proxy_next_upstream_tries 2;
 }
    }
}

Вкратце: конкретные ориентировочные показатели

Я настраиваю параметр `worker_processes` в соответствии с количеством ядер процессора, а значение `worker_connections` обычно устанавливаю в диапазоне от 1024 до 4096. При использовании обратного прокси я планирую два соединения на каждый запрос и оставляю запас пропускной способности, как минимум, в два раза превышающий измеренный пиковыйЗагрузить. Я устанавливаю значения параметра `worker_rlimit_nofile`, а также системные ограничения на достаточно высоком уровне, чтобы значения из файла `nginx.conf` оставались реально применимыми. Блок `events` я настраиваю на использование `epoll` и `multi_accept`, в то время как буферы ядра справляются с кратковременными всплесками трафика смягчать. Благодаря мониторингу и постепенным настройкам я создаю на этой основе надежный механизм привлечения трафика, который аккуратно обрабатывает растущее число посетителей несет.

Текущие статьи

Серверная стойка с хостингом NGINX для большого количества подключений
Веб-сервер Plesk

NGINX Worker Connections — масштабирование тысяч запросов для обеспечения максимальной производительности хостинга

Узнайте, как правильно настроить рабочие соединения nginx, чтобы обеспечить безопасное масштабирование NGINX и максимально повысить производительность хостинга при обработке тысяч запросов.

Настройка рабочих процессов NGINX на высокопроизводительном веб-сервере под управлением Linux
Веб-сервер Plesk

Оптимальная настройка рабочих процессов NGINX для обеспечения максимальной производительности

Узнайте, как правильно настроить рабочие процессы NGINX и значительно повысить производительность веб-сервера с помощью целенаправленной оптимизации NGINX.

Серверы хостинга под управлением Linux с оптимизированными файловыми системами Ext4 в центре обработки данных
Серверы и виртуальные машины

Параметры монтирования Ext4 для рабочих серверов Linux: практическое руководство для хостинговых сред

Ознакомьтесь с основными параметрами монтирования ext4 и практическими методами настройки файловой системы для вашего рабочего сервера Linux, чтобы оптимально сбалансировать производительность и безопасность данных в веб-хостинге.