У вас мощный сервер с десятком простых сайтов, клиенты довольны, сайты быстро открываются и регулярно обновляются. Приток посетителей с каждый днем все больше и больше. Но в один прекрасный момент эта идилия закончится, клиенты начнут жаловаться на частое появление ошибки 500. А почему она возникает? Давайте разберемся с одним из случаев.

 

Любая конфигурация связки apache+nginx с настройками по умолчанию когда нибудь приведет к регулярному повлению ошибки 500. Почитав логи nginx вы увидите следующее:

2015/02/15 12:55:34 [alert] 20231#0: accept() failed (24: Too many open files) while accepting new connection on 0.0.0.0:8082
2015/02/15 12:55:34 [alert] 20231#0: accept() failed (24: Too many open files) while accepting new connection on 0.0.0.0:8082
2015/02/15 12:55:34 [alert] 20231#0: accept() failed (24: Too many open files) while accepting new connection on 0.0.0.0:8082
2015/02/15 12:55:34 [alert] 20231#0: accept() failed (24: Too many open files) while accepting new connection on 0.0.0.0:8082
2015/02/15 12:55:34 [alert] 20231#0: accept() failed (24: Too many open files) while accepting new connection on 0.0.0.0:8082
 

При достаточно большом количестве посетителей файл nginx error.log может вырасти с 1мб до десятков гигабайт.

Ошибка связана с ограничением на одновременные подключения к серверу и соответствнно на одновременно открытые файлы. По умолчанию один процесс может открыть 1024 файла.

Для начала давайте посмотрим ограничения в системе, а далее поднимем лимит на открытые файлы.

Посмотреть текущее ограничение из консоли:

//смотрим от пользователя root
ulimit -n
 
//от пользователя www-data (это по умолчанию, у вас может быть другой пользователь)
su - www-data
ulimit -Hn
ulimit -Sn
 

В стандартной настройке системы оба значения будут равны 1024

Чтобы посмотреть системные ограничения в красивом виде выполните в консоли следующую команду:

for pid in `pidof nginx`; do echo "$(< /proc/$pid/cmdline)"; egrep 'files|Limit' /proc/$pid/limits; echo "Currently open files: $(ls -1 /proc/$pid/fd | wc -l)"; echo; done 
 

Результат выполнения команды

nginx: worker process
Limit                     Soft Limit           Hard Limit           Units
Max open files            1024                 1024                 files
Currently open files: 967
nginx: master process /usr/sbin/nginx Limit Soft Limit Hard Limit Units Max open files 1024 1024 files Currently open files: 783

 

Вот мы и убедились, что процесс nginx на грани по лимиту открытых файлов. На одно соединение выделяется по два файловых дескриптора, один для соединения с клиентом, а другой для открытия файла на диске. Добавляем worker_rlimit_nofile в самое начало конфигурационного файла /etc/nginx/nginx.conf

# Количество файловых дескрипторов которые будет использовать Nginx
worker_rlimit_nofile 16384;
 
# Меняем максимальное количество процессов (один процесс на одно ядро процессора)
worker_process 4;
 
# Количество соединений на процесс
worker_connections 4096;

Принцип установки зачений очень простой: worker_process *  worker_connections = worker_rlimit_nofile

Таким образом мы увеличили лимит открытых файловых дескрипторов и ускорили работу nginx за счет дополнительных процессов. Но, а как же система отнесется к таким запросам nginx? Ведь лимит открытых файлов для процессов как был 1024 так и остался неизменным. Сейчас мы это исправим.

Выполняем в консоли команду:

ulimit -n 16384

в /etc/security/limits.conf добавляем строки:

* soft nofile 16384
* hard nofile 16384
 

Теперь проверяем конфиг:

nginx -t

и перечитываем конфиги:

service nginx reload

На этом все! Nginx готов к росту посещаемости ваших проектов, стабильной и безотказной работе.