Статьи

Тюнинг NGINX

Хотя NGINX намного моложе других веб-серверов, он быстро стал популярным выбором. Частично его успех основан на том, что он является предпочтительным веб-сервером для тех, кто ищет легкий и эффективный веб-сервер.

В сегодняшней статье мы возьмем готовый экземпляр NGINX и настроим его так, чтобы получить больше от уже высокопроизводительного веб-сервера. Хотя эта статья не является полным руководством по настройке, она должна дать читателям четкое представление об основах настройки и нескольких общих параметрах настройки NGINX.

Однако прежде чем приступить к настройке, давайте сначала установим NGINX.

Установка NGINX

В этой статье мы будем запускать NGINX на сервере под управлением Ubuntu Linux, поэтому мы можем выполнить установку с помощью команды apt-get .

1
root@nginx-test:~# apt-get install nginx

На этом шаге будет установлена ​​общая установка NGINX, в которой уже есть некоторые параметры настройки, установленные из коробки. Однако установка NGINX по умолчанию не предлагает много возможностей для обслуживания контента. Чтобы создать реалистичное веб-приложение, давайте развернем пример сайта с GitHub.

1
2
3
4
5
6
7
root@nginx-test:~# git clone https://github.com/BlackrockDigital/startbootstrap-clean-blog.git /var/www/html
Cloning into '/var/www/html'...
remote: Counting objects: 308, done.
remote: Total 308 (delta 0), reused 0 (delta 0), pack-reused 308
Receiving objects: 100% (308/308), 1.98 MiB | 0 bytes/s, done.
Resolving deltas: 100% (119/119), done.
Checking connectivity... done.

При настройке производительности важно понимать тип приложения, которое настраивается. В случае NGINX важно знать, настраиваете ли вы статический контент или динамический контент, обслуживаемый последующим приложением. Разница между этими двумя типами содержимого может изменить параметры настройки, а также значения этих параметров.

В этой статье мы настроим NGINX для обслуживания статического HTML-контента. Хотя большинство параметров будут применяться к NGINX в целом, не все из них будут. Лучше всего использовать эту статью в качестве руководства для вашей собственной настройки и тестирования.

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

Установление базовой линии

Один из первых шагов в настройке производительности — установить единицу измерения. В этой статье мы будем использовать инструмент нагрузочного тестирования HTTP ApacheBench , также известный как ab для генерации тестового трафика в нашу систему NGINX.

Этот инструмент нагрузочного тестирования очень прост и полезен для веб-приложений. ApacheBench предоставляет довольно много опций для различных типов сценариев нагрузочного тестирования; однако в этой статье мы проведем тестирование довольно просто.

Мы будем выполнять команду ab с установленными параметрами -c (уровень параллелизма) и -n (количество запросов).

1
$ ab -c 40 -n 50000 http://159.203.93.149/

Когда мы выполним ab , мы установим уровень параллелизма ( -c ) на 40 , что означает, что ab будет поддерживать как минимум 40 одновременных HTTP-сеансов с нашим целевым экземпляром NGINX. Мы также установим ограничение на количество запросов, которые нужно сделать с помощью параметра -n . По сути, эти две опции вместе приведут к тому, что ab откроет 40 одновременных HTTP-сессий и отправит как можно больше запросов, пока не достигнет 50000 запросов.

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

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# ab -c 40 -n 50000 http://159.203.93.149/
This is ApacheBench, Version 2.3 <$Revision: 1528965 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/
 
Benchmarking 159.203.93.149 (be patient)
Completed 5000 requests
Completed 10000 requests
Completed 15000 requests
Completed 20000 requests
Completed 25000 requests
Completed 30000 requests
Completed 35000 requests
Completed 40000 requests
Completed 45000 requests
Completed 50000 requests
Finished 50000 requests
 
 
Server Software:        nginx/1.10.0
Server Hostname:        159.203.93.149
Server Port:            80
 
Document Path:          /
Document Length:        8089 bytes
 
Concurrency Level:      40
Time taken for tests:   16.904 seconds
Complete requests:      50000
Failed requests:        0
Total transferred:      420250000 bytes
HTML transferred:       404450000 bytes
Requests per second:    2957.93 [#/sec] (mean)
Time per request:       13.523 [ms] (mean)
Time per request:       0.338 [ms] (mean, across all concurrent requests)
Transfer rate:          24278.70 [Kbytes/sec] received

В приведенном выше выводе есть несколько интересных метрик. Сегодня мы сосредоточимся на метрике « Requests per second . Этот показатель показывает среднее количество запросов, которые наш экземпляр NGINX может обработать за секунду. При настройке параметров мы должны увидеть, как эта метрика идет вверх или вниз.

1
Requests per second:    2957.93 [#/sec] (mean)

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

При настройке производительности важно не забывать вносить небольшие изменения и сравнивать результаты с базовым уровнем. Для этой статьи наша базовая 2957.93 запросов в секунду. Чтобы параметр был успешным, он должен приводить к увеличению количества запросов в секунду.

С нашим базовым набором показателей давайте продолжим настройку NGINX.

Рабочие темы

Одним из основных параметров настройки в NGINX является количество доступных рабочих потоков . По умолчанию значение этого параметра равно auto , что говорит NGINX о создании одного рабочего потока для каждого процессора, доступного для системы.

Для большинства систем один рабочий процесс на каждый процессор обеспечивает равномерный баланс производительности и снижает накладные расходы. Тем не менее, в этой статье мы пытаемся получить максимальную отдачу от NGINX, обслуживая статический контент, который должен быть довольно низким из-за загрузки ЦП. Давайте посмотрим, сколько запросов в секунду мы можем получить, увеличив это значение.

Для нашего первого теста давайте продолжим и запустим два рабочих процесса для каждого процессора в системе.

Чтобы выяснить, сколько рабочих процессов нам нужно, нам сначала нужно узнать, сколько процессоров доступно для этой системы. Хотя есть много способов сделать это, в этом примере мы будем использовать команду lshw для отображения информации об оборудовании.

1
2
3
4
5
root@nginx-test:~# lshw -short -class cpu
H/W path      Device  Class      Description
============================================
/0/401                processor  Intel(R) Xeon(R) CPU E5-2650L v3 @ 1.80GHz
/0/402                processor  Intel(R) Xeon(R) CPU E5-2650L v3 @ 1.80GH

Из вышеприведенного вывода видно, что наша система представляет собой систему с 2 процессорами. Это означает, что для нашего первого теста нам нужно настроить NGINX для запуска в общей сложности 4 рабочих процессов.

Мы можем сделать это, отредактировав параметр /etc/nginx/nginx.conf файле /etc/nginx/nginx.conf . Это файл конфигурации NGINX по умолчанию и расположение для всех параметров, которые мы будем настраивать сегодня.

1
worker_processes auto;

Выше показано, что для этого параметра установлено значение по умолчанию auto . Давайте продолжим и изменим это значение на 4 .

1
worker_processes 4;

После установки нового значения и сохранения файла /etc/nginx/nginx.conf нам потребуется перезапустить NGINX, чтобы изменение конфигурации вступило в силу.

1
2
3
4
5
6
7
8
9
root@nginx-test:~# service nginx restart
root@nginx-test:~# ps -elf | grep nginx
1 S root     23465     1  0  80   0 - 31264 sigsus 20:16 ?        00:00:00 nginx: master process /usr/sbin/nginx -g daemon on; master_process on;
5 S www-data 23466 23465  0  80   0 - 31354 ep_pol 20:16 ?        00:00:00 nginx: worker process
5 S www-data 23467 23465  0  80   0 - 31354 ep_pol 20:16 ?        00:00:00 nginx: worker process
5 S www-data 23468 23465  0  80   0 - 31354 ep_pol 20:16 ?        00:00:00 nginx: worker process
5 S www-data 23469 23465  0  80   0 - 31354 ep_pol 20:16 ?        00:00:00 nginx: worker process
0 S root     23471 23289  0  80   0 3628 pipe_w 20:16 pts/0    00:00:00 grep --color=auto nginx
root@nginx-test:~#

Из вышесказанного мы можем видеть, что сейчас есть 4 запущенных процесса с именем nginx: worker process . Это указывает на то, что наше изменение прошло успешно.

Проверка эффекта

Начав работу с дополнительными работниками, давайте снова запустим ab чтобы увидеть, не было ли каких-либо изменений в пропускной способности.

1
2
# ab -c 40 -n 50000 http://159.203.93.149/ | grep "per second"
Requests per second:    3051.40 [#/sec] (mean)

Кажется, что наше изменение имело очень незначительный эффект: наши исходные Requests per second составляли 2957.93 , а наше новое значение — 3051.40 . Разница здесь примерно на 100 запросов в секунду. Хотя это улучшение, это не тот уровень улучшения, который мы искали.

1
worker_processes 8;

Давайте worker_processes значение worker_processes на 8 , в четыре раза превышающее число доступных процессоров. Чтобы изменения вступили в силу, нам снова нужно перезапустить службу NGINX.

1
root@nginx-test:~# service nginx restart

После перезапуска службы мы можем продолжить тестирование ab .

1
2
# ab -c 40 -n 50000 http://159.203.93.149/ | grep "per second"
Requests per second:    5204.32 [#/sec] (mean)

Кажется, что 8 рабочих потоков имеют гораздо более значительный эффект, чем 4 . По сравнению с нашими базовыми показателями мы видим, что с 8 рабочими потоками мы можем обрабатывать примерно на 2250 запросов больше в секунду.

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

Помните, что лучше вносить небольшие постепенные изменения и измерять производительность, увеличивая каждый шаг. Для этого параметра я просто увеличил бы его значение кратным двум и повторно запускал тест каждый раз. Я повторял бы этот процесс, пока количество запросов в секунду больше не увеличивается. Однако для этой статьи мы продолжим и перейдем к следующему параметру, оставив значение worker_processes равным 8 .

Рабочие связи

Следующий параметр, который мы собираемся настроить, — это конфигурация worker_connections в NGINX. Это значение определяет максимальное количество сеансов TCP на одного работника. Увеличивая это значение, мы надеемся, что мы сможем увеличить производительность каждого рабочего процесса.

Параметр worker_connections находится в блоке events в /etc/nginx/nginx.conf конфигурации /etc/nginx/nginx.conf .

1
2
3
4
events {
        worker_connections 768;
        # multi_accept on;
}

Настройка по умолчанию для установки UGNTU NGINX — 768 . В этом первом тесте мы попытаемся изменить этот параметр на 1024 и измерить влияние этого изменения.

1
2
3
4
events {
        worker_connections 1024;
        # multi_accept on;
}

Как и предыдущее изменение конфигурации, чтобы эта настройка вступила в силу, мы должны перезапустить службу NGINX.

1
root@nginx-test:~# service nginx restart

После перезапуска NGINX мы можем запустить еще один тест с помощью команды ab .

1
2
# ab -c 40 -n 50000 http://159.203.93.149/ | grep "per second"
Requests per second:    6068.41 [#/sec] (mean)

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

Увеличение рабочих потоков дальше

Если небольшое изменение в worker_connections может добавить 800 запросов в секунду, какое влияние окажет гораздо большее изменение? Единственный способ выяснить это — изменить параметр и протестировать снова.

Давайте продолжим и изменим значение worker_connections на 4096 .

1
2
3
4
5
6
worker_rlimit_nofile 4096;
 
events {
        worker_connections 4096;
        # multi_accept on;
}

Мы видим, что значение worker_connections равно 4096 , но есть и другой параметр, значение которого равно 4096 . Параметр worker_rlimit_nofile используется для определения максимального количества открытых файлов на рабочий процесс. Причина, по которой этот параметр теперь указан, заключается в том, что при настройке количества подключений на одного работника необходимо также настроить ограничения для открытого файла.

С NGINX каждое открытое соединение соответствует по крайней мере одному или иногда двум открытым файлам. Устанавливая максимальное количество соединений в 4096 , мы по сути определяем, что каждый работник может открывать до 4096 файлов. Без установки для worker_rlimit_nofile по крайней мере, такого же, что и worker_connections , мы можем фактически снизить производительность, поскольку каждый работник будет пытаться открывать новые файлы и будет отклонен из-за ограничений открытого файла или 1024 .

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

1
2
# ab -c 40 -n 50000 http://159.203.93.149/ | grep "per second"
Requests per second:    6350.27 [#/sec] (mean)

Судя по результатам прогона ab , мы смогли добавить около 300 запросов в секунду. Хотя это может и не быть столь значительным изменением, как наши более ранние 800 запросов в секунду, это все же является улучшением пропускной способности. Таким образом, мы оставим этот параметр как есть, чтобы перейти к следующему пункту.

Тюнинг для нашей рабочей нагрузки

При настройке NGINX или чего-либо еще по этому вопросу важно учитывать рабочую нагрузку настраиваемой службы. В нашем случае NGINX просто обслуживает статические HTML-страницы. Существует набор параметров настройки, которые очень полезны при обслуживании статического HTML.

1
2
3
4
http {
 
        open_file_cache max=1024 inactive=10s;
        open_file_cache_valid 120s;

Параметры open_file_cache в файле /etc/nginx/nginx.conf используются для определения того, как долго и сколько файлов NGINX может сохранять открытыми и кэшироваться в памяти.

По сути, эти параметры позволяют NGINX открывать наши HTML-файлы во время первого HTTP-запроса и сохранять эти файлы открытыми и кэшированными в памяти. По мере выполнения последующих HTTP-запросов NGINX может использовать этот кеш вместо повторного открытия наших исходных файлов.

Выше мы определяем параметр open_file_cache чтобы NGINX мог кэшировать max 1024 открытых файла. Однако из этих файлов кеш будет признан недействительным, если к ним не будет доступа в течение 10 секунд. Параметр open_file_cache_valid определяет временной интервал, чтобы проверить, все ли действительные кэшированные файлы все еще действительны; в этом случае каждые 120 секунд.

Эти параметры должны значительно сократить количество раз, когда NGINX должен открывать и закрывать наши статические HTML-файлы. Это означает меньшую общую работу на запрос, что должно означать более высокую пропускную способность. Давайте проверим нашу теорию с помощью еще одного запуска команды ab .

1
2
# ab -c 40 -n 50000 http://159.203.93.149/ | grep "per second"
Requests per second:    6949.42 [#/sec] (mean)

При увеличении почти 600 запросов в секунду параметры open_file_cache эффект. Хотя этот параметр может показаться очень полезным, важно помнить, что этот параметр работает в нашем примере, потому что мы просто обслуживаем статический HTML. Если бы мы тестировали приложение, которое каждый раз обслуживало динамический контент, эти параметры могут привести к ошибкам рендеринга для конечных пользователей.

Резюме

На данный момент мы взяли готовый экземпляр NGINX, измерили базовый показатель 2957.93 запросов в секунду и настроили этот экземпляр до 6949.42 запросов в секунду. В результате мы получили примерно 4000 запросов в секунду. Мы сделали это, не только изменив несколько ключевых параметров, но и поэкспериментировав с этими параметрами.

Хотя в этой статье были затронуты только некоторые ключевые параметры NGINX, методы, используемые в этой статье для изменения и измерения воздействия, можно использовать с другими общими параметрами настройки NGINX, такими как включение кэширования содержимого и сжатия gzip . Дополнительные параметры настройки приведены в Руководстве администратора NGINX, в котором содержится довольно много информации об управлении NGINX и его настройке для различных рабочих нагрузок.

Ссылка: Настройка NGINX от нашего партнера JCG Бена Кейна в блоге Codeship Blog .