Попытайтесь повторить это сами
Как правило, настроенный должным образом сервер Nginx на Linux, может обрабатывать 500,000 — 600,000 запросов в секунду. Мне удалось довести этот показатель до 904,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, даст максимально возможное количество клиентов. Однако это количество не получится сделать сколь угодно большим, т.к. оно ограничено числом сокетов, доступных в системе (это порядка 64 * 103).
# Determines how many clients will be served by each worker process. worker_connections 4000;
Последняя пролетарская директива, которую я хочу затронуть — это worker_rlimit_nofile. Данная директива указывает сколько файловых дескрипторов будет использовать Nginx. На каждое соединение надо выделять по два дексриптора, даже для статических файлов (картинки/JS/CSS): один для соединения с клиентом, а второй — для открытия статического файла. Таким образом, значение worker_rlimit_nofile должно быть равным удвоенному значению worker_connections. В системе это значение можно установить из командной строки 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 и ниже.
# 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 "MSIE [1-6]\.";
Пожалуй, это всё, о чём я хотел рассказать. Скажу лишь ещё раз, что не стоит копировать приведенные настройки один в один. Я советую применять их по одной, каждый раз запуская какую-нибудь утилиту для нагрузочного тестирования (например, 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 "MSIE [1-6]\."; }