Пользователь
0,0
рейтинг
30 октября 2013 в 01:48

Разработка → Ускоряем Nginx за 5 минут

image
Попытайтесь повторить это сами

Как правило, настроенный должным образом сервер Nginx на Linux, может обрабатывать 500,000 — 600,000 запросов в секунду. Но этот показатель можно весьма ощутимо увеличить. Хотел бы обратить внимание на тот факт, что настройки описанные ниже, применялись в тестовой среде и, возможно, для ваших боевых серверов они не подойдут.

Минутка банальности.

yum -y install nginx

На всякий пожарный, создадим бэкап исходного конфига.

cp /etc/nginx/nginx.conf /etc/nginx/nginx.conf.orig
vim /etc/nginx/nginx.conf

А теперь можно и похимичить!

Начнём с директивы worker_processes. Если Nginx выполняет работу нагружающую процессор (например SSL или gzipping), то оптимально установить эту директиву в значение, равное количеству ядер процессора. Выигрыш при большем значении вы получите только в случае обработки очень большого количества статики.

# This number should be, at maximum, the number of CPU cores on your system. 
worker_processes 24;

Также, директива worker_processes, умноженная на worker_connections из секции event, даст максимально возможное количество клиентов.

# Determines how many clients will be served by each worker process.
worker_connections 4000;

Последняя пролетарская директива, которую я хочу затронуть — это worker_rlimit_nofile. Данная директива указывает сколько файловых дескрипторов будет использовать Nginx. На каждое соединение надо выделять по два дексриптора, даже для статических файлов (картинки/JS/CSS): один для соединения с клиентом, а второй — для открытия статического файла. Таким образом, значение worker_rlimit_nofile должно быть равным удвоенному значению Max Clients. В системе это значение можно установить из командной строки ulimit -n 200000 или используя /etc/security/limits.conf.

# Number of file descriptors used for Nginx.
worker_rlimit_nofile 200000;

Теперь разберёмся с логированием. Во-первых, оставим логирование только критических ошибок.

# Only log critical errors.
error_log /var/log/nginx/error.log crit

Если вы совсем бесстрашны и хотите отключить логирование ошибок целиком, то помните, что error_log off вам не поможет. Вы просто получите весь лог в файле off. Для отключения логирования ошибок надо делать так:

# Fully disable log errors.
error_log /dev/null crit;

А вот логи доступа не так страшно отключить полностью.

# Disable access log altogether.
access_log off;

Или, хотя бы, включить буфер чтения / записи.

# Buffer log writes to speed up IO.
access_log /var/log/nginx/access.log main buffer=16k;

Для обработки подключений Nginx поддерживает ряд методов. Наиболее эффективным для Linux является метод epoll.

# The effective method, used on Linux 2.6+, optmized to serve many clients with each thread.
use epoll;

Для того, чтобы Nginx пытался принять максимальное количество подключений, необходимо включить директиву multi_accept. Однако при слишком маленьком значении worker_connections, их лимит может быть очень быстро исчерпан.

# Accept as many connections as possible, after nginx gets notification about a new connection.
multi_accept on;

Конечно же, нам не обойтись без кеширования информации о:
  • дескрипторах недавно открытых файлов: их размера и даты модификации;
  • существовании директорий;
  • ошибках при поиске файлов: отсутствие самого файла, отсутствие прав на чтение и т.д.

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

# Caches information about open FDs, freqently accessed files.
open_file_cache max=200000 inactive=20s; 
open_file_cache_valid 30s; 
open_file_cache_min_uses 2;
open_file_cache_errors on;

Директива sendfile активирует копирование данных между файловыми дескрипторами средствами ядра, что намного эффективнее связки read() + write(), которая требует обмена данными с пользовательским пространством.

# Sendfile copies data between one FD and other from within the kernel.
sendfile on; 

После включения sendfile, можно заставить Nginx отправлять заголовки HTTP-ответов одним пакетом, а не отдельным частями.

# Causes nginx to attempt to send its HTTP response head in one packet,  instead of using partial frames.
tcp_nopush on;

Для keep-alive подключений можно выключить буферизацию (алгоритм Нейгла). Это будет полезно при частом запросе маленьких объёмов данных в режиме реального времени, без получения немедленного ответа, когда важна своевременная доставка данных. Классический пример — события наведения мышкой.

# Don't buffer data-sends (disable Nagle algorithm).
tcp_nodelay on; 

Стоит обратить внимание на ещё две директивы для keep-alive подключений. Их назначение выглядит очевидным.

# Timeout for keep-alive connections. Server will close connections after this time.
keepalive_timeout 30;
# Number of requests a client can make over the keep-alive connection.
keepalive_requests 1000;

Чтобы высвободить дополнительную память, выделенную под сокеты, включите директиву reset_timedout_connection. Она разрешит серверу закрывать подключение тех клиентов, которые перестали отвечать.

# Allow the server to close the connection after a client stops responding. 
reset_timedout_connection on;

Ещё можно существенно уменьшить тайм-ауты для директив client_body_timeout и send_timeout (дефолтное значение обеих — 60 секунд). Первая — ограничивает время на чтение тела запроса от клиента. Вторая — время ответа клиенту. Таким образом, если клиент не начнёт читать данные в указанный промежуток времени, то Nginx закроет подключение.

# Send the client a "request timed out" if the body is not loaded by this time.
client_body_timeout 10;
# If the client stops reading data, free up the stale client connection after this much time.
send_timeout 2;

И, конечно же, сжатие данных. Плюс — единственный и очевидный: уменьшение размера пересылаемого трафика. Минус — единственный и очевидный: не работает для MSIE 6 и ниже. Отключить сжатие для этих браузеров можно директивой gzip_disable, указав в качестве значения специальную маску “msie6”, которая соответствует регулярному выражению “MSIE [4-6]\.”, но работает быстрее (спасибо hell0w0rd за комментарий).

# Compression.
gzip on;
gzip_min_length 10240;
gzip_proxied expired no-cache no-store private auth;
gzip_types text/plain text/css text/xml text/javascript application/x-javascript application/xml;
gzip_disable "msie6";

Пожалуй, это всё, о чём я хотел рассказать. Скажу лишь ещё раз, что не стоит копировать приведенные настройки один в один. Я советую применять их по одной, каждый раз запуская какую-нибудь утилиту для нагрузочного тестирования (например, Tsung). Это весьма важно для понимания, какие настройки реально ускоряют ваш веб-сервер. Методичность в тестировании сэкономит вам уйму времени.

P.S. Все настройки одним куском для бесстрашных лентяев
# This number should be, at maximum, the number of CPU cores on your system. 
worker_processes 24;

# Number of file descriptors used for Nginx.
worker_rlimit_nofile 200000;

# Only log critical errors.
error_log /var/log/nginx/error.log crit

events {

    # Determines how many clients will be served by each worker process.
    worker_connections 4000;

    # The effective method, used on Linux 2.6+, optmized to serve many clients with each thread.
    use epoll;

    # Accept as many connections as possible, after nginx gets notification about a new connection.
    multi_accept on;

}

http {

    # Caches information about open FDs, freqently accessed files.
    open_file_cache max=200000 inactive=20s; 
    open_file_cache_valid 30s; 
    open_file_cache_min_uses 2;
    open_file_cache_errors on;

    # Disable access log altogether.
    access_log off;

    # Sendfile copies data between one FD and other from within the kernel.
    sendfile on; 

    # Causes nginx to attempt to send its HTTP response head in one packet,  instead of using partial frames.
    tcp_nopush on;

    # Don't buffer data-sends (disable Nagle algorithm).
    tcp_nodelay on; 

    # Timeout for keep-alive connections. Server will close connections after this time.
    keepalive_timeout 30;

    # Number of requests a client can make over the keep-alive connection.
    keepalive_requests 1000;

    # Allow the server to close the connection after a client stops responding. 
    reset_timedout_connection on;

    # Send the client a "request timed out" if the body is not loaded by this time.
    client_body_timeout 10;

    # If the client stops reading data, free up the stale client connection after this much time.
    send_timeout 2;

    # Compression.
    gzip on;
    gzip_min_length 10240;
    gzip_proxied expired no-cache no-store private auth;
    gzip_types text/plain text/css text/xml text/javascript application/x-javascript application/xml;
    gzip_disable "msie6";

}


Олег Полудненко @uaoleg
карма
53,2
рейтинг 0,0
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Спецпроект

Самое читаемое Разработка

Комментарии (127)

  • +2
    Специальная маска “msie6” (0.7.12) соответствует регулярному выражению “MSIE [4-6]\.”, но работает быстрее. Начиная с версии 0.8.11, из этой маски исключается “MSIE 6.0;… SV1”.

    nginx.org/ru/docs/http/ngx_http_gzip_module.html
    • 0
      Спасибо, обновил статью.
  • +4
    спасибо. Интересно бы было послушать о буферах (не о тех что вы подумали, а о, например, fastcgi_buffer… или client_body_buffer...)
    • 0
      Не обещаю, но к сведению принял.
  • +18
    оно ограничено числом сокетов, доступных в системе (это порядка 64 * 10^3).
    С чего вдруг?

    Теперь разберёмся с логированием. Во-первых, оставим логирование только критических ошибок.

    # Only log critical errors.
    error_log /var/log/nginx/error.log crit
    Очень вредный совет. Путем эконоимии даже не на спичках, а… не знаю с чем сравнить, вы упустите кучу важных ошибок.
    • –3
      Спасибо, про сокеты действительно напутал, уже убрал из статьи. А на счёт логов — не принимаю, я писал о том, что эти настройки применялись в тестовой среде, и не стоит их слепо копировать на лайв сервера.
      • +9
        В тестовой среде тем более важно отловить любые предупреждения, прежде чем что-то выкладывать «на лайв сервера».
  • +4
    А какие настройки лучше делать, если nginx всего лишь прокся дальше?
    • +1
      Те же самые. Разве что только кеширование статических файлов будет бестолково.
      Даже если nginx проксирует дальше, то всё равно он может компрессировать, обрабатывать запросы для клиентов и прочее быстрее.
      • 0
        наверно можно «попросить» бэкэнд не жать отдаваемый трафик, установив хедер nginx-ом (если у вас nginx жмет)… впрочем, все зависит от ситуации…
        • –1
          На самом деле, чем раньше сожмешь — тем меньше пересылать, меньше работы, в том числе и между бэкендом и nginx-ом.

          Можно даже настроить так, чтобы бэкенд сжимал всегда, а nginx будет сжатый ответ складывать в кэш, а при необходимости, если вдруг клиент не поддерживает сжатие — разжимать с помощью gunzip модуля.

          Конечно это не всегда применимо. Если у вас итоговая страница строится из нескольких SSI-подзапросов, то сжимать получится только итоговую страницу.
          • 0
            Вот вам другой пример: api, который сильно грузит бэкэнд, но отдаёт не так много данных, чтобы забить канал фронт-бэк. Я же писал — все зависит от ситуации.
            • 0
              Верно. Самый практичный вариант — попробовать разные варианты и замерять скорость на каждом, что бы понять что лучше в данной ситуации.
              Например, сжатие забирает процессорное время, но экономит на трафике. Получилось, что на сервере определённой конфигурации самый эффективный уровень сжатия был 6, а на другом сервере получилось 8.
              • 0
                самый эффективный 5-6
                8 — большая нагрузка на процессор при соответствующем трафика, а разница в размере несущественна.
                Так же, если статика не изменяется, можно заранее сжать и положить рядом с файлом уже сжатый файл и (или) кэшировать.
                • 0
                  Если процессора много (как было в моём случае), то 8 добавляет очень несущественную нагрузку. Именно поэтому надо пробовать на своём сценарии, так как чужие варианты могут работать немного иначе в конкретной ситуации.
                  Я сжимаю динамический контент, а статика обычно уже сжата достаточно хорошо что бы её не жать ещё раз.
  • +14
    И зачем ссылаться на неофициальный вики, при наличии официальной документации да ещё и на русском? Для кого мы стараемся? При этом ещё давать крайне вольную интерпретацию того, что делает часть «рекомендуемых» к изменению директив.
    • +2
      Вот всегда удивлялся странному поведению людей. Кучу раз видел статьи про настройку nginx типа этой и думал, что это монстр непостижимый. А тут самому пришлось, так я сразу в документацию, а там — диво дивное. Потратил всего день на ознакомление и настройку и все теперь быстро и приятно :) Спасибо вам!
    • –2
      Боюсь спросить, а для чего тогда вообще существует это вики? Там написана неправда?
      • +3
        В старые добрые ламповые времена, когда nginx писал один Игорь в свободное от работы время, документация существовала только на русском языке. Любознательный Cliff Wells решил попробовать nginx и ему понравилось. C помощью Google Translate он переводил документацию, а чтобы его усилия не пропали запустил wiki у себя на сервере и попросил Игоря настроить поддомен wiki.nginx.org.

        Сейчас там наверху каждой страницы с документацией красными буквами: WARNING: this article is obsoleted. Please refer to nginx.org/en/docs/ for the latest official documentation.
        • 0
          О, теперь заметил эту надпись. Обязательно поменяю ссылки на официальную документацию.
          • 0
            Поменял, теперь статья стала действительно лучше.
    • +6
      Это синдром «все лгут» и «власти скрывают». Почему-то люди боятся официальной документации как огня, хотя как раз уважающие себя продукты (к ним относятся Postfix, Apache HTTP, QT, ну и nginx тоже) делают очень хорошую документацию.

      Читая вот такую хаутушку всё равно лезешь в документацию, чтоб понимать, что ты делаешь и что ещё можешь сделать, а там выясняется, что можно было не читать хаутушку — в документации написано лучше.
  • +15
    Зачем прописывать use epoll;, если nginx и так выбирает механизм, лучше всего работающий на данной системе?
    И было бы любопытно почитать, обоснование полезности указанных настроек, их плюсы и минусы. Если по отключению логов все понятно, то остальное вызывает вопросы. Например:
    Почему вообще sendfile разработчики не включили по умолчанию?
    Зачем ограничивать keepalive_requests, пусть запрашивает себе на здоровье?
    tcp_nodelay так вообще включен по умолчанию.
    • +15
      Скорее всего это было просто надергано из другого источника (или нескольких). Итоговый конфиг и комментарии к нему обладают каким-то магическим сходством вплоть до мелких деталий с этой статьей: dak1n1.rannmann.com/blog/12-nginx-performance-tuning (а та в свою очередь также скомпонована из чьих-то советов на форумах и блогах).

      Так множится чушь, один написал «the number of socket connections available on the system (~64k)», другие повторяют.
      • +2
        плагиат значить… а я плюс поставил :(
        надо поставить флажок перевод c указанием источника
    • –9
      Зачем прописывать use epoll;, если nginx и так выбирает механизм, лучше всего работающий на данной системе?

      tcp_nodelay так вообще включен по умолчанию.

      Вполне возможно ситуация, когда вы настраиваете Nginx не с нуля. И ваш предшественник вполне мог переопределить дефолтные настройки не самым оптимальным образом. А данная директива весьма критична для оптимизации. Поэтому я её и упомянул.
      Почему вообще sendfile разработчики не включили по умолчанию?

      Да, согласен, эту директиву можно было лучше описать.
      Зачем ограничивать keepalive_requests, пусть запрашивает себе на здоровье?

      По умолчанию оно имеет значение 100, так что я его как раз увеличил.
    • +2
      keepalive принято ограничивать со времён, когда в апаче утекала память, и боролись с этим прибивая процесс каждые 300 запросов. Вот такая вот дурацкая традиция, об истоках которой некоторые люди даже не задумываются
      • –3
        А зачем тогда keepalive ограничивается в дефолтных настройках Nginx?
        • 0
          Не знаю. Я не вижу сегодня смысла вообще в любом ограничении кипалайва. Может, чтоб tcp-соединения хоть когда-нибудь заканчивались и начинались заново?
          • 0
            keepalive_requests по прежнему служит для избежания утечек памяти, переполнения всяких счетчиков и прочего. Во время обработки запроса могут быть выделения памяти, которые персистентны для всего соединения, особенно во всяких сторонних модулях (где вообще может быть всё, что угодно).

            Значение 100 по умолнчанию вполне разумно.
        • –5
          чтоб кол-во портов не закончилось
          Вы «типа» протюнили nginx, но даже не удосужились протюнить ядро через sysctl.

          тот же диапазон локальных портов увеличить
          net.ipv4.ip_local_port_range = 1024 65535
          • +3
            При чём здесь это? nginx висит у меня на одном порту и висит себе, какое отношение это имеет к количеству данных, которые через этот порт переданы?
            • 0
              а где я написал про количество данных?
              или Вы не знаете, что такое «диапазон портов» и каким-то боком это отнесли к количеству данных.
              При том же проксировании через nginx исходящие соединения создают локальный порт. Вот чтоб этот порто-диапозон не закончился и надо немного протюнить ядро.
              • –1
                А, речь про проксирование. Да, похоже, что в этом случае могут закончиться. Но я с трудом представляю себе это: статика и так отдаётся nginx, если он берёт что-то из кэша — прокси-соединение тоже не создаётся, и наконец та сторона, куда он передаёт один запрос из примерно пятисот — обычно это apache — тоже поддерживает keepalive.
                • 0
                  php-fpm пул на других серверах, что довольно таки часто можно встретить.
          • –1
            минусуют те, кто не видел линукс и кто никогда не сталкивался с доссом, нехваткой портов?
            • 0
              Да просто проблема реально неочевидная и большинство с ней никогда не сталкивалось. Я тут не исключение. О проблемах типа «порты закончились» как-то не задумываешься…
              • –1
                вот это показывает, что специалистов, кто реально сталкивался с не статичным HighLoad еденицы, в основном тут биомасса. которая минусует, но даже не знают о чем речь.
                • 0
                  Это намекает на то, что вам было полезно сразу в комментарии пояснить, о чём речь, а не после моего вопроса ;)
                • +1
                  Вы в своем сообщение выше, которое заминусовали, объяснили нехваткой портов назначение директивы keepalive_requests. Потом вы уточнили, что нехватка портов может случиться для исходящих соединений при проксировании. А теперь потрудитесь объяснить, как проксирование в nginx связано с обсуждаемой директивой, и как вообще эта директива в этом случае может помочь? Ответ я знаю — никак не связано, помочь не может.
            • 0
              При чём тут это? Я насколько знаю, keep-alive или они же persistent connections служат для того, чтобы в рамках одного подключения передать большой объём данных. Например, когда у вас на странице много графики. А с проксированием это не связано практически никак.
      • –1
        Утекала память не в Апаче, а в php скриптах. Точнее в mod_php она утекала.
        • 0
          возможно, да, я за давностью лет уже забыл
    • НЛО прилетело и опубликовало эту надпись здесь
      • –1
        эти настройки можно изменить на более низком уровне.
        через тот же sysctl

        настроки по умолчанию примерно такие:

        net.ipv4.tcp_keepalive_time = 300
        net.ipv4.tcp_keepalive_intvl = 75
        net.ipv4.tcp_keepalive_probes = 9

        Первый параметр — проверять созданное соединение через 300 сек.
        Второй — интервал проверки
        третий — кол-во проверок

        В условиях ддоса, настройки следует изменить на меньшие, примерно такие.

        net.ipv4.tcp_keepalive_time = 60
        net.ipv4.tcp_keepalive_intvl = 10
        net.ipv4.tcp_keepalive_probes = 5

        • +1
          Этот keepalive — это другой keepalive. Это «сколько времени держать поднятый сокет, если не было ни одного пакета». А keepalive в http-сервере — это обычно «сколько по одному tcp-соединению можно задать http-запросов».
          • 0
            А я не замену keepalive_requests указал,
            я указал для:
            «а закрывать открытое соединение некому.»

            • 0
              Вы написали эти настройки можно изменить на более низком уровне. Эти? Как TCP keepalive соотносится с обсуждаемым в ветке HTTP keepalive? Никак.

              Настройки, которые вы предложили менять через sysctl сразу для всей системы, можно задать в nginx индивидуально для сокета в параметрах директивы listen, причем работать будет на всех поддерживающих это ОС (включая даже DragonFlyBSD, где соответсвующие интервалы задаются в миллисекундах — будет произведена конвертация значений).
  • +16
    Вредные советы от uaoleg :)
  • +8
    Вот эту строчку я особо не навижу
    error_log /var/log/nginx/error.log crit
    когда какие то проблемы и нихрена в логах нет.
    • –5
      Хотел бы обратить внимание на тот факт, что настройки описанные ниже, применялись в тестовой среде и, возможно, для ваших боевых серверов они не подойдут.

      Я бы тоже не рискнул включить её на продакшене.
      • +3
        А на тестовом сервере (не бенчмарк, а именно тест перед выкатыванием) тем более логи надо пошумнее. Отсюда, вопрос, в каких условиях (кроме бенчмарка и писькомерства «сколько я запросов могу в секунду») это может быть полезно?
        • –6
          Бенчмарк и писькомерство — очень серьёзные причины.
  • +2
    Автор, не нужно включать sendfile, если не работаете с ram диском! Во-первых, вы теряете кэширование, что очень актуально для мелких файлов. Во-вторых, для эффективной работы с дисками (hdd и ssd) есть aio/directio, которые не работают вместе с sendfile.
    • 0
      Мне интересно, почему при sendfile теряется кэширование? (можно со ссылками на код ядра)
      • 0
        www.linux.com/community/forums/storage/sendfile-and-memory-cache

        В коде лучше сами поищите, если так интересно;) По опыту работу с высоконагруженными файловыми серверами, скажу что для дисков эту опцию не включать. Очень сильно растет iowait и в целом, диски работают намного хуже. И для крупных файлов и для мелких.
        • +3
          По ссылке написано «However, the OS will still cache the data as that is not a matter of the application calling sendfile() as it is a matter of how the OS caches data read from disc. So, yes, it will use system memory to cache the data»

          Посмотрел по диагонали код, в итоге реализация sendfile() сводится к slice(), а тот в итоге идет в vfs_read(), т.е. это стандартный код. Где отказ от кэширования?

          Допускаю, что я что-то пропустил — поэтому и спрашиваю.

          Ссылка на опыт — хорошо, но если даже причина в sendfile (а запросто, почему бы и нет), то хотелось бы четко понимать, в чем она заключается. Аргументов за кэширование я не вижу…
          • +1
            Я вам неправду написал. Ниже исправился.
        • 0
          Ну и вообще странно: насколько я понимаю, aio сейчас реализовано на уровне glibc, он принципиально не может работать быстрее при отправке больших файлов (т.к. данные все равно будут таскаться kernelspace/userland).

          directio — вы имеете в виду флаг для open syscall?

          O_DIRECT (Since Linux 2.4.10)

          Try to minimize cache effects of the I/O to and from this file. In general this will degrade performance, but it is useful in special situations, such as when applications do their own caching. File I/O is done directly to/from user space buffers.

          Вот здесь есть отказ от кэша. Получается, мы предполагаем, что nginx умеет кэшировать множество файлов самостоятельно, при этом оптимизировать кэш под раздачу файлов лучше, чем ядро — поэтому и предпочитает O_DIRECT и отказ от «родного кэша»…
          • 0
            Есть ещё ядерный aio, который сводится к пулу ядерных тредов, выполняющих обычные read/write, только полностью в kernel space, и посылающие нотификацию процессу, когда всё будет готово. А вот там как раз опять могут всплыть засады с O_DIRECT, подробностей о состоянии дел на текущий день, к сожалению, не знаю.
            • 0
              Да, понятно, спасибо… Интересно было бы увидеть полную картинку, конечно.
              • +1
                То, что было почти 10 лет назад, можно посмотреть тут: www.kernel.org/doc/ols/2003/ols2003-pages-351-366.pdf
                Более скудная, но зато свежая информация: www.fsl.cs.sunysb.edu/~vass/linux-aio.txt

                И да, если мы можете почитать sendfile по диагонали и что-то при этом понять — вы очень круты :)
    • +2
      Щито? sendfile в принципе работает через pagecache. Можете не верить мне, но Торвальдс пишет то же самое: yarchive.net/comp/linux/splice.html.

      Или вы про какое-то другое кеширование?
      • +1
        Извините, я все перепутал. sendfile действительно использует кэш, потому для мелких файлов таки лучше использовать его. aio+directio не использует, потому его лучше для крупных файлов. В голове, блин, перепуталось что-то(
    • 0
      а какие по размеру файлы «крупные» и «мелкие»?
      в среднем HTML страница занимает 60К — это относим в какую категорию?
      • 0
        Не относим никуда, я говорил о статических файлах. Если отдаете html просто с диска, то к мелким, естественно.
  • +16
    Что за чушь? Почему это число открытых сокетов 64к? Автор попутал с числом портов в TCP, так вот, это разные вещи. Число разрешённых сокетов для приложения определяется лимитом на число FD'шек.

    А вот за таймаут в 2с я бы по ушам сильно бил. В лаборатории ок, в реальной жизни у клиентов с неидеальным интернетом (особенно, если до сайта пинг порядка 300-400мс) сайт будет глючить и бибикать без явной причины.
    • –21
      Спасибо, с сокетами я действительно напутал, уже исправил. А по ушам бы я бил, тех кто воспринимает всё близко к сердцу, и читает невнимательно.
      Хотел бы обратить внимание на тот факт, что настройки описанные ниже, применялись в тестовой среде и, возможно, для ваших боевых серверов они не подойдут.
  • +24
    Добавил статью в избранное, почитал комментарии, удалил из избранного.
    • –2
      А статью-то прочитать забыли.
    • +2
      Аналогично )
    • +1
      Наоборот, только из-за комментариев и добавил в избранное :)
  • +4
    Я не совсем понял. Написано:
    значение worker_rlimit_nofile должно быть равным удвоенному значению worker_connections.

    Но при worker_connections 4000, worker_rlimit_nofile 200000? Почему 200000, а не 8000?
    • –3
      Прошу прощение, конечно же удвоенному количеству Max Clients.
    • +2
      worker_connections * worker_processes * 2
      Автор взял с небольшим запасом (при вычислении вышло 192000).
    • 0
      Потому что open_file_cache 200000. Но по логике тогда ограничение должно быть порядка 208010.
  • +7
    Все очень плохо.
    Не буду комментировать явные ошибки типа 64 тыс соединений, они просто показывают некомпетентность автора, извините.

    Экономия на логах — это не правильно. Если у вас узкое место — это запись логов на диск, купите диски побыстрее.
    Логгирование должно быть максимально подробным, и access_log в том числе. Это позволяет быстро локализовать проблему при наличии.

    Если отключить access_log, как советует автор, а error выставить в crit, а потом еще удалить всю статику, то система будет «выглядеть нормально», при этом клиенты будут видеть долбанное ничего. За то быстро :)
    • –5
      Спасибо, про 64.000 — да, это был явный феил, куда же без них. Но я убрал это ещё пол часа назад, или все читают только комменты, а не статью? :)
      Про логированию — в очередной раз позволю себе не согласится: я писал, что эти настройки я использовал в тестовом окружении, и что не стоит их слепо переносить на прод. Чем плохо отключить логирование, скажем на аксептансе, чтобы автотесты работали чуточку быстрее?
      • +2
        >Чем плохо отключить логирование, скажем на аксептансе, чтобы автотесты работали чуточку быстрее?

        Тем, что они не будут работать «чуточку быстрее».
        Это совет из серии «в php одинарные кавычки быстрее двойных». Только в отличии от данного совета, ваш еще и вредит, т.к. лишает пользователя диагностической и отладочной информации.
        • –6
          Это совет из серии «в php одинарные кавычки быстрее двойных».

          Т.е. писать строки в одинарных кавычках — это вредный совет? А его ещё и в официальной документации дают. Всё зависит от области применения, имхо.
          • +2
            По вашей ссылке написано
            Please make sure that for all special query operators (starting with $) you use single quotes so that PHP doesn't try to replace "$exists" with the value of the variable $exists.

            Что в переводе означает следующее:
            Пожалуйста убедитесь, что для всех операторов запроса (начинающихся с $) вы используете одинарные кавычки, чтобы PHP не пытался заменить текст '$exists' значением переменной $exists.

            Они по-разному обрабатываются, если что. Но это не означает, что одинарные работают быстрее. На выходе вы получите те же opcode, что с одинарными, что с двойными кавычками. И даже heredoc синтаксис даст такой же результат.

            Возвращаясь к логгированию — я всего лишь хотел сказать, что отсутствие логов не увеличит быстродействие (по крайней мере вы не заметите этого увеличения ни одним тестом), но при этом вы потеряете кучу полезной информации.
            • 0
              > отсутствие логов не увеличит быстродействие

              Строго говоря, логирование может сказаться на быстродействии, если дисковое I/O загружено под завязку, либо если объём логов слишком велик. В случае СУБД рекомендуется выносить лог транзакций на отдельный физический диск, хранящий исключительно лог. В этом случае скорость работы СУБД ограничится потоковой скоростью записи на диск (~100+ МБ/с). Полагаю, для Nginx как и для других логирующих систем этот принцип будет так же справедлив.
              • 0
                Логи пишутся всегда последовательно, «в конец».

                Я вообще рассматриваю вариант логирования через сеть на специально выделенный сервер. Так и безопаснее (подтереть логи за собой не выйдет), и проще (целевой системе не нужно задумываться об анализе вторжений, ротации и тому подобном).
                • +1
                  Да, логи пишутся в конец файла. Однако, если диск HDD, плюс на этом же диске хранится раздаваемая статика, БД и т.п., то головка диска будет совершать кульбиты туда-сюда, и IOPsы просядут.

                  С точки зрения производительности — лучше на другой физический диск на этом же сервере, с точки зрения безопасности — наверное Вы правы. Можно использовать syslog.
                  • –3
                    А что мешает создать папку в памяти и складировать логи туда, а раз в 10 минут по крону перекидывать на жесткий диск?

                    пример:
                    Так создаем папку в памяти
                    sudo mkdir /home/logs
                    sudo chmod 0777 /home/logs
                    sudo mount -t tmpfs -o size=512M tmpfs /home/logs

                    • +3
                      Зачем такие сложности? nginx сам умеет кэшировать запись логов.
                    • +2
                      Вы только что изобрели асинхронную запись. Только ОС сбрасывает буфер на диск не раз в 10 минут, а раз в несколько секунд.

                      Использовать асинхронную запись не мешает ничто кроме риска потерять данные (если они критичны). Поэтому журнал транзакций в СУБД выполняется в синхронном режиме, и это влияет на производительность I/O. А логи веб-сервера могут вестись в асинхронном режиме (скорее всего, так и есть).

                      Кроме того, лог можно направлять в syslog и отправлять по сети на соседний сервер. Тоже выход.
                      • 0
                        просветите пожалуйста, как изменить настройки, чтоб получать лог раз в n минут из памяти nginx, не напрягая жесткий диск каждые пару секунд.
                        • +3
                          access_log path [format [buffer=size [flush=time]]];

                          nginx.org/en/docs/http/ngx_http_log_module.html
                          • –2
                            спасибо, +1 к сожалению поставить не могу, так что только орально так. )
              • 0
                tail -1 /var/log/nginx/personal.access_log | wc
                      1      27     386
                


                Чтобы сделать поток ~100МБ/с — надо примерно 200k rps. Это мягко говоря не мало.
                • +1
                  Чуть дальше по ветке Masterme написал, что тупо просядут IOPS на HDD.
                • +1
                  Это если вынести лог на отдельный диск.

                  А я имел ввиду ситуацию, когда и лог, и раздаваемый контент находятся на одном диске. Всё дело в количестве IOPs, а также в том, как именно nginx ведёт лог — синхронно или асинхронно (я не знаю этого наверняка, но, возможно кто-то другой здесь знает). Если синхронно, то любой запрос к статике — это, грубо говоря, 2 обращения к диску — на чтение целевого файла и на запись лога. Если асинхронный — то ситуация получше, запись кидается в очередь в оперативной памяти, а ОС сама записывает на диск когда ей удобнее.
          • 0
            > писать строки в одинарных кавычках — это вредный совет?
            _надрачивать_ на одинарные кавычки — вредный совет

            > А его ещё и в официальной документации дают
            там дают совет «не забудьте, что в двойных кавычках происходит автозамена $-переменных на их значения», а вовсе не «одинарные кавычки быстрее двойных»
  • +4
    Блин, это еще и в лучшее попало.
    Люди, очнитесь! Читайте официальную документацию nginx.org/en/docs/ nginx.org/ru/docs/, а не эти «вредные советы».
    Nginx очень прост в настройке, не надо его бояться.
    • –3
      Из плохих советов — отключение логов? Один пункт из двух десятков? Да и то, я несколько раз подчеркнул, что делалось это в тестовом окружении, и не следует копировать это слепо на прод. Или вы против того, чтобы кто-то имел свой взгляд, отличный от официального?
  • +2
    А как же увеличение backlog?
    • 0
      Спасибо, действительно важная настройка. А у вас есть опыт, какие значения будут оптимальными и почему?
      • +1
        Тут не может быть оптимального значения. Потому как предсказать, на сколько быстро растащится очередь невозможно.

        Лично я для обычных сайтов ставлю 10. Позволяет сгладить всплески нагрузки, но не до такой степени, что бы страницы отдавались с критичной задержкой.
        • 0
          Интересно, почему на FreeBSD и на Mac OS X он имеет дефолтное значение -1, а на остальных системах 511.
          • 0
            Уверен, что атавизм.

            backlog так же полезен, если не больше, между nginx и бэкэндом. Помогает отрабатывать коннекты без 502 ошибок клиенту на сервере с ограниченным количеством ОЗУ (т.е. по количеству рабочих процессов мы сильно лимитированны) ценой небольшой задержки. Ибо «стоимость» коннекта в backlog-е сильно «дешевле» чем висящий рабочий процесс бэкэнда (в контексте PHP говорю, но и для других неСишных бэкэндов актуально).
            • 0
              Круто, спасибо за пояснение.
          • 0
            удалено как дубль.
  • 0
    Советую не копировать значения директив кеширования, а поиграть с ними, подобрав оптимальные для вашего окружения.

    Ну и как с ними играть? Если уж говорите что нужно что-то тюнить, то говорите на какие показатели во время работы смотреть после тюна чтоб понимать что нужно подкрутить. Вы же не пишите статью только для суворых админов…
    • –1
      например, Tsung
  • +1
    А почему топик не помечен как перевод? dak1n1.com/blog/12-nginx-performance-tuning
    • 0
      Переведите ту статью и сравните результат.
      • 0
        Переведите комментарии конфига из той статьи и сравните результат.
        • –3
          Да, сравните. Помимо той статьи я использовал много других источников.
          • +1
            Я вижу явный плагиат и вранье с Вашей стаороны, извините.

            Вступление абсолютно одинаковое

            Generally, a properly tuned Nginx server on Linux can handle 500,000 — 600,000 requests per second. My Nginx servers consistently handle 904k req/sec, and have sustained high loads like these for the ~12 hours that I tested them.

            It's important to know that everything listed here was used in a testing environment, and that you might actually want very different settings for your production servers.


            Из чего я делаю вывод, что сами Вы лично эти тесты не проводили.

            Далее вы просто перессказываете весь файл конфигурации, с переводом на русский язык. Я не нашел вообще ничего, что есть у Вас, и нет в той статье.
            • –3
              Статья была взята за основу, но к каждой настройке я писал развёрнутое пояснения по материалам wiki.nginx.org, вопросов на stackovwerflow.com, а ряда других источников. Как это может быть переводом, если я внёс свои пояснения к каждой директиве? Плюс благодаря комментариям читателей исправил ошибки и внёс улучшения в исходный конфиг. Что здесь плохого? Кому это навредит?
              • +1
                Я не говорю что это кому-то навредит.

                Я говорю, что вы выдаете работу другого человека (и поиск оптимальной конфигурации, и проведение тестов) за свою. Развернутые пояснения ко всем директивам есть в оригинальной статье — я вижу только их вольный перевод.
                • –2
                  Я не вижу смысла пересказывать ещё раз всю статью. Но постараюсь вас всё-таки отстоять свою позицию на примере первой же директивы. В приведенной вами статье к ней указан следующий комментарий:
                  # This number should be, at maximum, the number of CPU cores on your system.
                  # (since nginx doesn't benefit from more than one worker per CPU.)

                  В моей стать комментарий следующий:
                  Начнём с директивы worker_processes. Если Nginx выполняет работу нагружающую процессор (например SSL или gzipping), то оптимально установить эту директиву в значение, равное количеству ядер процессора. Выигрыш при большем значении вы получите только в случае обработки очень большого количества статики.

                  Я думаю очевидно, что моё описание куда более развёрнутое, объясняет в каких ситуациях какое значение для директивы будет более оптимальным и почему. Я потратил на эту работу достаточно личного времени для того, чтобы опубликовать её не как банальный перевод.
                  • +2
                    Я понимаю Ваше желание отстоять свой труд. Я лишь говорю о том, что не стоит присваивать себе действия других людей, и когда в таком количестве копируете материал (а у вас скопирована вся конфигурация) — ставьте ссылку на источник.

                    Однако, на примере первой же директивы я не понимаю, чем Ваше описание лучше чужого. Вы просто развернуто написали то же самое, посоветовали установить ее в конкретное значение. Почему ее нужно установить именно так — я не понял из Вашей статьи. А если мой nginx не занимается
                    SSL или gzipping
                    — мне можно ее в 1 установить? И все равно получу 900к реквестов в секунду?

                    В оригинальной статье мне намного понятнее, почему имеено так —
                    since nginx doesn't benefit from more than one worker per CPU.
                    То есть самое важное осталось без перевода.

                    Вашу позицию я понял, считаю что спор продолжать нет смысла.
        • 0
          Скажем не перевод, а компиляция. Но источники автор должен был указать.
  • +2
    После такого рьяного спора о логах я задался вопросом, почему в nginx не поступить так же как это реализовано в том же haproxy? А именно, зачем обязательно писать логи в файл? Почему бы не писать их в rsyslog на соседний сервер.
    Плюсы:
    не тратим IO
    храним безопасно логи на другом сервере
    отправляем логи по UDP следовательно если лог сервер ляжет, производительность не упадет никак.

    Насколько я понял встроенного решения такого в NGginx нет, но виден в инете несколько модулей
    • +1
      есть в платном nginx
    • 0
      кстати, как вариант, можно писать в pipe, из которого подхватывать syslog-ng и дальше как уггодно
  • +2
    Ад, угар и содомия, извините. Подавляющее большинство статьи — чушь, которую просто опасно применять на production.
    • –3
      Звучит неубедительно.
      • –2
        Не пойму, за что минусы? Критика mifa — на уровне школьника. Почему бы не написать, что конкретно не так? И я бы с радостью это исправил. И тысячи читателей получили бы более качественный материал.
      • +1
        Да более-менее грамотным людям и так все понятно…

        worker_processes 24;


        Треш. После этого статью вообще можно дальше не читать. Вы вообще представляете себе как воркер работает?

        Ненужная экономия на логах, 64к сокетов, бешеные таймауты, форсинг epoll — в общем, автор явно не понимает о чем говорит. А учитывая, что автор, судя по всему, не топикстартер, то это еще и просто перевод/компиляция некачественного материала.

        Даже не то жалко, что написали фигню. А то, что написали на Хабре — этого могут начитаться начинающие специалисты, а потом применять на практике, вот что страшно.
  • –3
    Это коммент должен был быть не здесь.
  • +2
    Так вот чем админы хабра сейчас заняты.
  • 0
    А какая конфигурация сойдёт для

    500,000 — 600,000
    • 0
      Дефолтная по идее где-то такое и даёт.
      • 0
        Не, вопрос про железо :)

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