Тонкая настройка Nginx. Защита, оптимизация. Оптимизация nginx
Оптимальная настройка Nginx
В стандартной конфигурации Nginx может работать при очень больших нагрузках. Тем не менее, эффективность его работы можно значительно повысить, настроив его параметры. Такая настройка называется тюнинг (tuning — подстройка, регулировка).
Как настраивать и тюнинговать Nginx
Обычно конфигурационный файл называется nginx.conf. Его можно найти:
Debian
/etc/nginx/nginx.confFreebsd
/usr/local/etc/nginx/nginx.confФайл настроек обычно выглядит так:
user www-data; worker_processes 1; events { worker_connections 1024; } http { ... }Оптимизация параметров
Обработка соединений
Максимальное количество соединений, которые Nginx может обслуживать одновременно определяются произведением двух параметров:
Всего соединений = worker_processes x worker_connectionsДиректива use устанавливает метод выбора соединений. Для разных операционных систем нужно использовать разные методы.
Linux
use epollFreebsd
use kqueueПо умолчанию, Nginx постарается выбрать наиболее эффективный метод самостоятельно.
Обработка запросов
multi_accept on; sendfile on; tcp_nodelay on; tcp_nopush on;Информация о файлах
Nginx умеет кешировать информацию о файлах, с которыми ему приходится работать (например, css стили или картинки). Если к таким файлам происходит много обращений, кеширование может значительно ускорить этот процесс.
open_file_cache max=200000 inactive=20s; open_file_cache_valid 30s; open_file_cache_min_uses 2; open_file_cache_errors on;Логирование
Основной лог лучше отключить для экономии дисковых операций, а лог ошибок лучше перевести в режим логирования только критических ситуаций.
Сжатие Gzip
Обязательно нужно использовать сжатие, это значительно уменьшит трафик. Проверить, включено ли сжатие, можно с помощью Gzip checker.
gzip on; gzip_disable "msie6"; gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript application/javascript;Обработка клиентов
Keepalive соединения позволяют избежать необходимости повторного создания соединения между клиентом и сервером.
keepalive_timeout 30; keepalive_requests 100;Много проблем могут создать медленные (тупящие) клиенты. Медленная передача тела запроса от клиента к серверу и неожиданное закрытие клиентом соединений могут создать большое количество лишних соединений на сервере.
reset_timedout_connection on; client_body_timeout 10; send_timeout 2;Ограничивайте отправку больших запросов на сервер (например, загрузку больших файлов), если это не предусмотрено сайтом.
После правки настроек необходимо выполнить перезагрузку:
nginx -s reloadВся конфигурация
worker_processes auto; events { use epoll; worker_connections 1024; multi_accept on; } http { include /etc/nginx/mime.types; default_type application/octet-stream; access_log off; error_log /var/log/nginx/error.log crit; keepalive_timeout 30; keepalive_requests 100; client_max_body_size 1m; client_body_timeout 10; reset_timedout_connection on; send_timeout 2; sendfile on; tcp_nodelay on; tcp_nopush on; gzip on; gzip_disable "msie6"; gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript application/javascript; open_file_cache max=200000 inactive=20s; open_file_cache_valid 30s; open_file_cache_min_uses 2; open_file_cache_errors on; }Самое важное
Самым большим эффектом на посетителей окажет включение сжатия gzip.
#nginx ID: 28
ruhighload.com
Оптимизация nginx
Как известно, nginx очень продуктивный веб-сервер, но всё же его тоже можно ускорить. Я облазил интернет и решил все советы собрать в одном месте.Поехали. Для начала нужно открыть конфиг nginx, ну, это и так должно бить понято. В debian он обычно в /etc/nginx/nginx.conf, в freebsd — /usr/local/etc/nginx/nginx.conf
Оптимизация
Я уже, наверное, задолбал теорией, так что давайте приступим к практике.
Обработка соединений
Максимальное количество соединений, которые Nginx может обслуживать одновременно, определяются произведением двух параметров:
Всего соединений = worker_processes x worker_connections worker_processes auto;Nginx и сам может посчитать и поверьте, сделает это лучше. Рекомендую ставить в auto в последних версиях.
worker_connections 1024;А use нам поможет выбрать тип соединения. В linux — epoll, freebsd — kqueue
use epoll;Если не укажем — nginx сам подумает. Умница! А вы говорите нет штучного интелекта.
Обработка запросов
multi_accept on; #nginx будет обрабатывать максимальное количество соединений sendfile on; #Метод отправки данных sendfile более эффективен, чем стандартный метод read+write # Nginx будет отправлять заголовки и начало файла в одном пакете: tcp_nodelay on; tcp_nopush on;Без этого никак.
Файлы
directio 10m;Эта опция будет читать файлы, больше 10 мб, минуя операционный кеш, поскольку для больших файлов он малоэффективен.
Cache-Control
location ~* ^.+.(js|css)$ { expires max; }Этот код будет кешировать js, css -файлы навечно. Но по скольку они время от времени изменяются, нужно делать так:
<link rel="stylesheet" href="/styles.v2.css" type="text/css" /> <script src="/scripts.v2.js"></script>Для удобства сделать rewrite на script.js/style.css и заливать файлы так, а если есть изменения — просто заменить цифру после v.С неизменяемой статикой всё значительно проще:
location ~* ^.+.(ogg|ogv|svg|svgz|eot|otf|woff|mp4|ttf|rss|atom|jpg|jpeg|gif|png|zip|tgz|gz|rar|bz2|doc|xls|exe|ppt|tar|mid|midi|wav|bmp|rtf)$ { expires max; }UPD: товарищ symbix советует указывать не regexp, а папку где оно хранится:
location /static/ {expires max;}Информация о файлах
Nginx умеет кешировать информацию о файлах, с которыми ему приходится работать (например, css стили или картинки). Если к таким файлам происходит много обращений, кеширование может значительно ускорить этот процесс.
open_file_cache max=200000 inactive=20s;Определяет максимальное количество файлов, информация о которых будет содержаться в кеше.
open_file_cache_valid 30s;Определяет через какое время информация будет удалена из кеша:
open_file_cache_min_uses 2;Nginx будет кешировать информацию о файлах, которые были использованы хотя бы 2 раза.
open_file_cache_errors on;Nginx будет кешировать информацию об отсутствующих файлах:
limit_rate
limit_rate 200K; #отдавать файлы со скоростью 200 кб/секЭта опция работает только в рамках одного запроса, а не клиента. Если вы хотите поставить ограничение на клиента, следует использовать переменную:
set $limit_rate 196K;В Nginx также есть возможность установить порог отдачи, после которой ограничение войдет в силу. Также имеет смысл для потокового медиа (в этом случае первая указанная часть будет отдаваться без ограничений):
limit_rate_after 1m; #Ограничение скорости отдачи будет накладываться после 1МбЛоги
access_log /dev/null; #нам логи не нужны error_log /var/log/nginx/error.log; #а вот ошибки нужно знать!UPD: BuriK666 советует ставить acces_log off; Похоже у новых версиях баг з созданиям файла off — исправили.
Сжатия gzip
gzip on; gzip_disable "msie6"; gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript application/javascript;Для text/html не нужно, поскольку nginx для него сжимает автоматически.
Обработка клиентов
keepalive
keepalive_timeout = 30; keepalive_requests 100; #максимально от одного клиентаВнимания! Это не копировать, а обдумать. Как подсказал gnomeby:Если держать keepalive для подгрузки статики, то будет примерно так:keepalive_timeout = 5; #keepalive_requests %максимальное количество подгрузок + 2-10%
Ну и конечно от посетителей самой нагруженной страницы очень зависит.Тут, думаю, всё ясно.
Ограничения и отключения
reset_timedout_connection on;#Если клиент перестал читать, отвечать nginx сбрасывает соединение с ним client_body_timeout 10;#nginx будет ждать 10 секунд тело запроса от клиента, после чего сбросит соединение send_timeout 2; #Если клиент прекратит чтение ответа, Nginx подождет 2 секунды и сбросит соединение client_max_body_size 1m; #больше одного мегабайта запрос - ни-ни, хотя нужно на стороне приложения ограничиватьС этим нужно быть очень осторожным.
The end! Надеюсь, этот пост будет вам полезен.
Автор: Webius
Источник
www.pvsm.ru
Ускоряем Nginx за 5 минут / Хабр
Попытайтесь повторить это сами Как правило, настроенный должным образом сервер 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; Конечно же, нам не обойтись без кеширования информации о:- дескрипторах недавно открытых файлов: их размера и даты модификации;
- существовании директорий;
- ошибках при поиске файлов: отсутствие самого файла, отсутствие прав на чтение и т.д.
habr.com
Настройка Nginx | Losst
Веб-сервер Nginx - это один из самых популярных веб-серверов с очень высокой производительностью и быстрой обработкой статических запросов от пользователей. При правильной настройке можно добиться очень высокой производительности от этого веб-сервера. Nginx очень быстро справляется со статическими файлами, будь то html страницы или другие виды ресурсов.
В одной из предыдущих статей мы уже рассматривали установку Nginx в Ubuntu и настройку его основных параметров, в этой же статье я хочу больше остановиться на производительности и подготовке веб-сервера к использованию в боевых условиях. Что касается дистрибутива Linux, то сегодня мы будем рассматривать CentOS, эта система часто используется на серверах и с настройкой Nginx тут могут возникнуть некоторые сложности. Дальше будет рассмотрена настройка Nginx CentOS, поговорим как включить полную поддержку http2, google pagespeed, и настроить основной конфигурационный файл.
Содержание статьи:
1. Установка Nginx
В официальных репозиториях CentOS есть Nginx и он, скорее всего, уже установлен в вашей системе. Но мы хотим чтобы сайт работал по протоколу http2, который позволяет передавать все данные одним подключением, а это увеличивает производительность. Для работы по http2 вам понадобиться настроить SSL сертификат, но об этом уже написано в статье получение сертификата Lets Encrypt Nginx. Но это еще не все. для переключения с обычного SSL на HTTP2.0 в большинстве браузеров сейчас используется протокол ALPN, а он поддерживается начиная с OpenSSL 1.02. В то время, как в репозиториях есть только OpenSSL 1.01. Поэтому нам нужно установить версию Nginx, собранную с OpenSSL 1.02. Для этого можно использовать Broken Repo:
sudo yum -y install yum-utils# sudo yum-config-manager --add-repo https://brouken.com/brouken.repo
Если вы используете репозиторий EPEL, то нужно указать что не надо из него брать Nginx:
sudo yum-config-manager --save --setopt=epel.exclude=nginx*;
Теперь для установки правильной версии Nginx достаточно набрать:
sudo yum install nginx
Будет установлена самая последняя версия Nginx 1.13.2, с полной поддержкой ALPN. Дальше перейдем к настройке.
2. Настройка Nginx
Первым делом следует рассмотреть структуру конфигурационного файла. На первый взгляд, тут все может показаться очень запутанным, но там все достаточно логично:
глобальные опцииevents {}http{server {location{}}server {}}
Сначала идут глобальные опции, которые задают основные параметры программы, например, от какого пользователя она будет запущена и количество процессов. Дальше есть секция events, в которой описано как Nginx будет реагировать на входящие подключения, затем идет секция http, которая объединяет все настройки касаемо работы протокола http. В ней находится секция server, каждая такая секция отвечает за отдельный домен, в секции server размещаются секции location, каждая из которых отвечает за определенный URL запроса, обратите внимание, что не файл на сервере, как в Apache, а именно URL запроса.
Основные глобальные настройки мы будем делать в файле /etc/nginx/nginx.conf. Дальше рассмотрим что именно будем менять и какие значения желательно установить. Начнем с глобальных опций:
- user - пользователь, от имени которого будет запущен сервер, должен быть владельцем каталога с файлами сайта, и от имени его же нужно запускать php-fpm;
- worker_processes - количество процессов Nginx, которые будут запущены, нужно установить ровно столько, сколько у вас есть ядер, например, у меня - 4;
- worker_cpu_affinity - этот параметр позволяет закрепить каждый процесс за отдельным ядром процессора, установите значение auto, чтобы программа сама выбрала что и к чему крепить;
- worker_rlimit_nofile - максимальное количество файлов, которые может открыть программа, на каждое соединение нужно как минимум два файла и каждый процесс будет иметь указанное вами количество соединений, поэтому формула такая: worker_processes * worker_connections* 2, параметр worker_connections разберем чуть ниже;
- pcre_jit - включите этот параметр для ускорения обработки регулярных выражений с помощью JIT компиляции;
В секции events стоит настроить два параметра:
- worker_connections - количество соединений для одного процесса, должно быть достаточным для обработки входящих соединений. Сначала нам нужно знать сколько этих входящих соединений есть, для этого смотрим статистику по адресу ip_сервера/nginx_status. Как включить рассмотрим ниже. В строке Active Connections видим количество активных соединений с сервером, также нужно учесть что соединения с php-fpm тоже считаются. Дальше обратите внимание на поля accepted и handled, первое отображает обработанных подключений, второе - количество принятых. Из значения должны быть одинаковыми. Если отличаются значит соединений не хватает. Смотрите примеры, первый снимок проблема, второй - порядок. Для моей конфигурации оптимальной может быть цифра в 200 соединений (всего 800, учитывая 4 процесса):
- multi_accept - позволяет программе принимать несколько соединений одновременно, тоже ускоряет работу, при большом количестве соединений;
- accept_mutex - установите значение этого параметра в off, чтобы сразу все процессы получали уведомление про новые соединения;
Также в секции events рекомендуется использовать директиву use epoll, так как этот самый эффективный метод обработки входящих соединений для Linux, но этот метод применяется по умолчанию, поэтому не вижу смысла добавлять его вручную. Рассмотрим еще несколько параметров из секции http:
- sendfile - использовать метод отправки данных sendfile. Самый эффективный метод для Linux.
- tcp_nodelay, tcp_nopush - отправляет заголовки и тело запроса одним пакетом, работает немного быстрее;
- keepalive_timeout - таймаут поддержания соединения с клиентом, если у вас нет очень медленных скриптов, то будет достаточно будет 10 секунд, устанавливаем значение сколько нужно чтобы пользователь мог быть подключен к серверу;
- reset_timedout_connection - разрывать соединения после таймаута.
- open_file_cache - кэшировать информацию об открытых файлах. Например, open_file_cache max=200000 inactive=120s; max - максимальное количество файлов в кэше, время кэширования.
- open_file_cache_valid - когда нужно проверить актуальность файлов. Например: open_file_cache_valid 120s;
- open_file_cache_min_uses - кэшировать только файлы, которые были открыты указанное количество раз;
- open_file_cache_errors - запоминать ошибки открытия файлов.
- if_modified_since - устанавливает каким образом будут обрабатываться заголовки if-modified-since. С помощью этого заголовка браузер может получить ответ 304 если страница не изменилась с момента последнего просмотра. Возможны варианты - не отправлять - off, отправлять при точном совпадении времени - exact, отправлять если время совпадает точно или больше - before;
Вот как-то так будет выглядеть настройка nginx conf:
user nginx;worker_processes 4;worker_cpu_affinity auto;worker_rlimit_nofile 10000;pcre_jit on;
error_log /var/log/nginx/error.log warn;load_module "modules/ngx_pagespeed.so";
events {multi_accept on;accept_mutex off;worker_connections 1024;}
http {
sendfile on;tcp_nopush on;tcp_nodelay on;
open_file_cache max=200000 inactive=20s;open_file_cache_valid 120s;open_file_cache_errors on;
reset_timedout_connection on;client_body_timeout 10;keepalive_timeout 65;
include /etc/nginx/sites-enabled.*.conf
}
3. Настройка http2
Я не буду подробно описывать настройку секции server, потому что делал это уже в статье установка Nginx в Ubuntu и здесь мне нечего добавить, настройка SSL это достаточно обширная тема и тоже будет рассмотрена в отдельной статье. Но чтобы настроить http2 вам нужно иметь уже SSL. Далее, просто подправьте директиву listen в вашей секции server:
listen 194.67.215.125:443 default_server;
На:
listen 194.67.215.125:443 http2 default_server;
Вот таким простым способом можно включить http2 если перед этим была установлена правильная версия Nginx.
4. Настройка PageSpeed
Google Pagespeed - это модуль Nginx, который выполняет различные оптимизации для того, чтобы страницы грузились быстрее, веб-сервер работал эффективнее, а пользователи не чувствовали дискомфорта. Сюда входит кэширование, оптимизация html кода, оптимизация картинок, объединение javascript и css кода и многое другое. Все это выполняется на уровне Nginx, поэтому эффективнее, чем если бы вы это делали в php. Но тут есть один недостаток, модуль удаляет заголовок Last Modified.
Дело в том, что PageSpeed устанавливает очень долгий строк кэширования для всех файлов, а в имя файла добавляет его хэш. Так скорость загрузки ресурсов выходит намного выше, поскольку браузер будет запрашивать файлы только с новым хэшем, а LastModified удаляется чтобы пользователи смогли увидеть изменения в случае если какой-либо файл будет изменен. А теперь рассмотрим как установить модуль. Нам придется собрать его из исходных кодов.
Сначала установите инструменты для сборки, очень важно, если не установите, потом получите ошибку и не будете знать что делать:
yum install wget gcc cmake unzip gcc-c++ pcre-devel zlib-devel
Скачайте и распакуйте исходники Nginx для вашей версии, например, 1.13.3:
wget -c https://nginx.org/download/nginx-1.13.3.tar.gz# tar -xzvf nginx-1.13.3.tar.gz
Настройка сервера nginx не включает пере сборку и замену программы из репозитория, мы просто используем эти исходники для сборки модуля. Скачайте и распакуйте исходники PageSpeed:
wget -c https://github.com/pagespeed/ngx_pagespeed/archive/v1.12.34.2-stable.zip# unzip v1.12.34.2-stable.zip
Скачайте и распакуйте библиотеку оптимизации PageSpeed в папку с исходниками модуля:
cd ngx_pagespeed-1.12.34.2-stable/# wget -c https://dl.google.com/dl/page-speed/psol/1.12.34.2-x64.tar.gz# tar -xvzf 1.12.34.2-x64.tar.gz
Скачайте и распакуйте исходники OpenSSL 1.02:
wget -c https://www.openssl.org/source/openssl-1.0.2k.tar.gz -O /opt/lib/$OPENSSL.tar.gz# tar xvpzf openssl-1.0.2k.tar.gz
Теперь нам нужно собрать модуль. Сначала смотрим опции, с которыми собран текущий Nginx:
nginx -V
А теперь переходим в папку с Nginx, подставляем все полученные опции, опцию --add-dynamic-module для PageSpeed, OpenSSL и пробуем собрать:
cd nginx-1.13.3# ./configure --prefix=/etc/nginx --sbin-path=/usr/sbin/nginx --modules-path=/usr/lib64/nginx/modules --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --pid-path=/var/run/nginx.pid --lock-path=/var/run/nginx.lock --http-client-body-temp-path=/var/cache/nginx/client_temp --http-proxy-temp-path=/var/cache/nginx/proxy_temp --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp --http-scgi-temp-path=/var/cache/nginx/scgi_temp --user=nginx --group=nginx --with-compat --with-file-aio --with-threads --with-http_addition_module --with-http_auth_request_module --with-http_dav_module --with-http_flv_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_mp4_module --with-http_random_index_module --with-http_realip_module --with-http_secure_link_module --with-http_slice_module --with-http_ssl_module --with-http_stub_status_module --with-http_sub_module --with-http_v2_module --with-mail --with-mail_ssl_module --with-stream --with-stream_realip_module --with-stream_ssl_module --with-stream_ssl_preread_module --with-cc-opt='-O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -m64 -mtune=generic' --with-ld-opt= --with-openssl=$HOME/openssl-1.0.2k --add-dynamic-module=$HOME/ngx_pagespeed-1.12.34.2-stable ${PS_NGX_EXTRA_FLAGS}# make
Если все было сделано правильно, то на выходе вы получите модуль ngx_pagespeed.so в папке obj, его нужно скопировать в папку /etc/nginx/modules:
cp ngx_pagespeed.so /etc/nginx/modules/ngx_pagespeed.so
Создаем папку для кэша:
mkdir -p /var/ngx_pagespeed_cache# chown -R nginx:nginx /var/ngx_pagespeed_cache
Теперь добавьте такую строчку для включения модуля в /etc/nginx/nginx.conf:
load_module "modules/ngx_pagespeed.so";
Затем, в секцию сервер достаточно добавить:
pagespeed on;pagespeed FileCachePath /var/ngx_pagespeed_cache;location ~ "\.pagespeed\.([a-z]\.)?[a-z]{2}\.[^.]{10}\.[^.]+" { add_header "" ""; }location ~ "^/ngx_pagespeed_static/" { }location ~ "^/ngx_pagespeed_beacon" { }
Теперь вам достаточно перезапустить nginx чтобы изменения вступили в силу:
nginx -t# systemctl restart nginx
Выводы
Настройка Nginx завершена, возможно, остались еще и другие оптимизации, которые помогут ускорить Nginx, но они не войдут в эту статью. А какие оптимизации используете вы? Напишите обязательно в комментариях! Надеюсь, эта информация была полезной вам.
Оцените статью:
Загрузка...losst.ru
Тонкая настройка Nginx. Защита, оптимизация.
Выделенный Web-сервер на основе nginx – отличный способ повышения производительности Web-сайтов. В скорости обработки статического контента ему просто нет равных: он легко выдерживает несколько тысяч одновременных соединений и может быть легко оптимизирован и подогнан под любую конфигурацию. Однако? выступая в качестве фронт-энда для Apache, nginx оказывается наиболее уязвимым местом всей Web-инфраструктуры, поэтому безопасности nginx необходимо уделить особое внимание.
Эта статья – своего рода ликбез, или, если хочешь, резюме всех техник повышения безопасности nginx. В ней не будет теории, описания основ настройки Web-сервера и прочей воды. Вместо этого ты получишь исчерпывающий практический материал, описывающий все основные шаги, которые необходимо проделать для того, чтобы получить по-настоящему защищенный Web-сервер.
Установка
Пакет nginx доступен в прекомпилированном виде для любого дистрибутива. Однако собрав сервер самостоятельно, ты сможешь сделать его более компактным и надежным, а также получишь возможность изменить строку приветствия Web-сервера, чтобы отбить несмышленых скрипт-кидди.
Измени строку приветствия Web-сервера
Скачай исходники nginx, открой файл src/http/ngx_http_header_filter_module.c и найди следующие две строки:
static char ngx_http_server_string[] = "Server: nginx" CRLF;static char ngx_http_server_full_string[] = "Server: " NGINX_VER CRLF;
Замени их на что-то вроде этого:
static char ngx_http_server_string[] = "Server: ][ Web Server" CRLF;static char ngx_http_server_full_string[] = "Server: ][ Web Server" CRLF;
Удали все неиспользуемые тобой nginx-модули
Некоторая часть модулей nginx подключается к Web-серверу прямо во время компиляции, и любой из них таит в себе потенциальную опасность. Возможно, в будущем в одном из них будет найдена уязвимость, и твой сервер окажется под угрозой. Отключив ненужные модули, ты сможешь значительно снизить риск возникновения такой ситуации.
Выполни сборку с помощью следующих команд:
# ./configure --without-http_autoindex_module --without-http_ssi_module# make# make install
Так ты получишь nginx с заранее отключенными (и в большинстве случаев бесполезными) модулями SSI (Server Side Includes) и Autoindex. Чтобы узнать, какие модули можно безболезненно выбросить из Web-сервера, запусти скрипт configure с флагом ‘—help’.
Препарируем nginx.conf
После установки nginx следует настроить. На страницах журнала уже был материал, описывающий этот процесс, мы же будем придерживаться темы статьи и поговорим о способах повышения безопасности сервера.
Отключи показ версии сервера на всех ошибочных страницах
Добавь в файл nginx.conf строку “server_tokens off”. Это заставит nginx скрывать информацию о типе и версии Web-сервера на страницах, генерируемых в ответ на ошибочный запрос клиента.
Настрой защиту от срыва стека
Добавь в секцию server следующие строки:
# vi /etc/nginx/nginx.conf
# Максимальный размер буфера для хранения тела запроса клиентаclient_body_buffer_size 1K;# Максимальный размер буфера для хранения заголовков запроса клиентаclient_header_buffer_size 1k;# Максимальный размер тела запроса клиента, прописанный в поле Content-Length заголовка. Если сервер должен поддерживать загрузку файлов, это значение необходимо увеличитьclient_max_body_size 1k;# Количество и размер буферов для чтения большого заголовка запроса клиентаlarge_client_header_buffers 2 1k;
Обрати внимание на директиву large_client_header_buffers. По умолчанию, для хранения строки URI nginx выделяет четыре буфера, размер каждого из которых равен размеру страницы памяти (для x86 это 4 Кб). Буферы освобождаются каждый раз, когда по окончанию обработки запроса соединение переходит в состояние keep-alive. Два буфера по 1 Кб могут хранить URI длиной только 2 Кб, что позволяет бороться с ботами и DoS-атаками.
Для повышения производительности добавь следующие строки:
# vi /etc/nginx/nginx.conf
# Таймаут при чтении тела запроса клиентаclient_body_timeout 10;# Таймаут при чтении заголовка запроса клиентаclient_header_timeout 10;# Таймаут, по истечению которого keep-alive соединение с клиентом не будет закрыто со стороны сервераkeepalive_timeout 5 5;# Таймаут при передаче ответа клиентуsend_timeout 10;
Контролируй количество одновременных соединений
Для защиты Web-сервера от перегрузки и попыток осуществить DoS-атаку добавь в конфиг следующие строки:
# vi /etc/nginx/nginx.conf
# Описываем зону (slimits), в которой будут храниться состояния сессий. Зона размером 1 Мб может хранить около 32000 состояний, мы устанавливаем ее размер равным 5 Мбlimit_zone slimits $binary_remote_addr 5m;# Задаем максимальное количество одновременных соединений для одной сессии. По сути, это число задает максимальное количество соединений с одного IPlimit_conn slimits 5;
Первая директива должна находиться в секции HTTP, вторая – в секции location. Когда количество соединений выйдет за пределы лимитов, клиент получит сообщение «Service unavailable» с кодом 503.
Разреши коннекты только к своему домену
Взломщики могут использовать ботов для сканирования подсетей и поиска уязвимых Web-серверов. Обычно боты просто перебирают диапазоны IP-адресов в поисках открытых 80 портов и посылают запрос HEAD для получения информации о веб-сервере (или главной странице). Ты можешь легко предотвратить такой скан, запретив обращение к серверу по IP-адресу (добавить в подсекцию location):
# vi /etc/nginx/nginx.conf
if ($host !~ ^(host.com|www.host.com)$ ) {return 444;}
Ограничь количество доступных методов обращения к Web-серверу
Некоторые боты используют различные методы обращения к серверу для попытки определения его типа и/или проникновения, однако в документе RFC 2616 четко сказано, что Web-сервер не обязан реализовывать их все, и неподдерживаемые методы могут просто не обрабатываться. Сегодня используемыми остаются только методы GET (запрос документа), HEAD (запрос заголовков сервера) и POST (запрос на публикацию документа), поэтому все остальные можно безболезненно отключить с помощью помещения следующих строк в секцию server конфигурационного файла:
# vi /etc/nginx/nginx.conf
if ($request_method !~ ^(GET|HEAD|POST)$ ) {return 444;}
Отшивай ботов
Другой способ блокирования ботов, сканеров и прочей нечисти основан на определении типа клиента (user-agent). Он не слишком эффективен, потому как большинство ботов косят под вполне легитимные браузеры, но в ряде случаев остается полезным:
# vi /etc/nginx/nginx.conf
# Блокируем менеджеры загрузкиif ($http_user_agent ~* LWP::Simple|BBBike|wget) {return 403;}# Блокируем некоторые типы ботовif ($http_user_agent ~* msnbot|scrapbot) {return 403;}
Блокируй Referrer-спам
Если твой сайт публикует Web-логи в общедоступном виде, ты легко можешь стать жертвой Referrer-спама (когда спам-боты обращаются к твоему серверу, указывая в заголовке referrer – адрес рекламируемого сайта). Такой вид спама может легко испортить SEO-рейтинги интернет-страницы, поэтому его необходимо блокировать в обязательном порядке. Один из способов сделать это – занести наиболее частые слова, встречающиеся в адресах рекламируемых сайтов, в черный список.
# vi /etc/nginx/nginx.conf
# Секция serverif ( $http_referer ~* (babes|forsale|girl|jewelry|love|nudit|organic|poker|porn|sex|teen) ){return 403;}
Блокируй хотлинк
Хотлинк – это включение в страницу изображения (или иного контента) с другого сайта. По сути, это воровство, потому как изображение, на которое ты потратил не один час своего свободного времени, не только свободно используется другими, но и создает нагрузку на твой Web-сервер, не приводя на него посетителей. Для борьбы с хотлинками достаточно сделать так, чтобы изображения отдавались клиенту только в том случае, если он запросил их, уже находясь на сайте (другими словами, заголовок referrer-запроса должен содержать имя твоего сайта). Добавь в секцию server конфигурационного файла nginx.conf следующие строки (host.com – это адрес твоего сайта):
# vi /etc/nginx/nginx.conf
location /images/ {valid_referers none blocked www.host.com host.com;if ($invalid_referer) {return 403;}}
В качестве альтернативы ты можешь настроить сервер на отдачу специального баннера с сообщением о воровстве вместо запрашиваемого изображения. Для этого замени строку «return 403» на строку:
rewrite ^/images/uploads.*\.(gif|jpg|jpeg|png)$ http://www.host.com/banned.jpg last
Защищай важные каталоги от посторонних
Как и любой другой Web-сервер, nginx позволяет регулировать доступ к каталогам на основе IP-адресов и паролей. Эту возможность можно использовать для закрытия некоторых частей сайта от посторонних глаз. Например, для отрезания URI от внешнего мира:
# vi /etc/nginx/nginx.conf
location /uploads/ {# Разрешаем доступ только машинам локальной сетиallow 192.168.1.0/24;# Отшиваем всех остальныхdeny all;}
Теперь к документам каталога uploads будут иметь доступ только пользователи локальной сети. Для установки пароля придется проделать более сложные действия. Сначала необходимо создать приватный для nginx-файл паролей и добавить в него необходимых пользователей (в качестве примера добавим пользователя admin):
# mkdir /etc/nginx/.htpasswd# htpasswd -c /etc/nginx/.htpasswd/passwd admin
Далее открой файл nginx.conf и впиши в него следующие строки:
# vi /etc/nginx/nginx.conf
location /admin/ {auth_basic "Restricted";auth_basic_user_file /etc/nginx/.htpasswd/passwd;}
Новых пользователей можно добавить с помощью следующей команды:
# htpasswd -s /etc/nginx/.htpasswd/passwd пользователь
Используй SSL
Если твой сайт работает с приватными данными пользователей, такими как номера кредитных карт, пароли от других сервисов, или же предоставляет доступ к другой важной информации, которая может стать лакомым кусочком для третьих лиц, позаботься о шифровании. Nginx хорошо работает с SSL, и этой возможностью нельзя пренебрегать.
Для настройки SSL-шифрования средствами nginx достаточно выполнить несколько простых шагов. Сначала ты должен создать сертификат с помощью следующей последовательности команд:
# cd /etc/nginx# openssl genrsa -des3 -out server.key 1024# openssl req -new -key server.key -out server.csr# cp server.key server.key.org# openssl rsa -in server.key.org -out server.key# openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt
Затем описать сертификат в конфигурационном файле nginx:
# vi /etc/nginx/nginx.conf
server {server_name host.com;listen 443;ssl on;ssl_certificate /etc/nginx/server.crt;ssl_certificate_key /etc/nginx/server.key;access_log /etc/nginx/logs/ssl.access.log;error_log /etc/nginx/logs/ssl.error.log;}
После этого можно перезагрузить Web-сервер:
# /etc/init.d/nginx reload
Естественно, без поддержки со стороны самого Web-сайта это делать бессмысленно.
Другие способы
Установи правильные значения системных переменных
Открой файл /etc/sysctl.conf и помести в него следующие строки:
# vi /etc/sysctl.conf
# Защита от smurf-атакnet.ipv4.icmp_echo_ignore_broadcasts = 1# Защита от неправильных ICMP-сообщенийnet.ipv4.icmp_ignore_bogus_error_responses = 1# Защита от SYN-флудаnet.ipv4.tcp_syncookies = 1# Запрещаем маршрутизацию от источникаnet.ipv4.conf.all.accept_source_route = 0net.ipv4.conf.default.accept_source_route = 0# Защита от спуфингаnet.ipv4.conf.all.rp_filter = 1net.ipv4.conf.default.rp_filter = 1# Мы не маршрутизаторnet.ipv4.ip_forward = 0net.ipv4.conf.all.send_redirects = 0net.ipv4.conf.default.send_redirects = 0# Включаем ExecShieldkernel.exec-shield = 1kernel.randomize_va_space = 1# Расширяем диапазон доступных портовnet.ipv4.ip_local_port_range = 2000 65000# Увеличиваем максимальный размер TCP-буферовnet.ipv4.tcp_rmem = 4096 87380 8388608net.ipv4.tcp_wmem = 4096 87380 8388608net.core.rmem_max = 8388608net.core.wmem_max = 8388608net.core.netdev_max_backlog = 5000net.ipv4.tcp_window_scaling = 1
Размести корневой каталог Web-сервера на выделенном разделе
Поместив корневой каталог Web-сервера в выделенный раздел и запретив на нем размещение любых исполняемых файлов и файлов-устройств, ты обезопасишь остальную часть системы от тех, кто сможет получить доступ к корню Web-сервера. При этом запись в файле /etc/fstab должна иметь примерно такой вид:
/dev/sda5 /nginx ext4 defaults,nosuid,noexec,nodev 1 2
Помести nginx в chroot/jail-окружение
Любая современная *nix-система позволяет запереть приложение в изолированной среде исполнения. В Linux для этого можно использовать технологии KVM, Xen, OpenVZ и VServer, во FreeBSD – Jail, в Solaris – Zones. Если ни одна из этих технологий не доступна, ты можешь поместить nginx в классический chroot, который хоть и намного более хрупок, но большинство взломщиков остановить сможет.
Установи правила SELinux для защиты nginx
Хорошей альтернативой изолированным средам исполнения являются локальные системы обнаружения и предотвращения вторжений, такие как SELinux или AppArmor. Будучи правильно настроенными, они смогут предотвратить попытки взлома Web-сервера. По дефолту ни одна из них не настроена для работы в связке с nginx, однако в рамках проекта SELinuxNginx (http://sf.net/projects/selinuxnginx/) были созданы правила для SELinux, которые может использовать любой желающий. Остается только скачать и установить:
# tar -zxvf se-ngix_1_0_10.tar.gz# cd se-ngix_1_0_10/nginx# make# /usr/sbin/semodule -i nginx.pp
Настрой брандмауэр
Обычно nginx устанавливают на выделенных машинах, готовых к высокой нагрузке, поэтому зачастую он остается единственным сетевым сервисом, работающим на сервере. Чтобы обезопасить сервер, достаточно создать совсем небольшой набор правил, которые будут открывать 80, 110 и 143-й порты (если, конечно, nginx должен работать еще и как IMAP/POP3-прокси) и закрывать от внешнего мира все остальное.
Ограничь количество соединений с помощью брандмауэра
Для не слишком нагруженного Web-сайта хорошей идеей будет ограничить количество попыток соединений с одного IP-адреса в минуту. Это сможет уберечь тебя от некоторых типов DoS-атак и брутфорса. В Linux это можно сделать с помощью стандартного iptables/netfilter-модуля state:
# iptables -A INPUT -p tcp --dport 80 -i eth0 \-m state --state NEW -m recent --set# iptables -A INPUT -p tcp --dport 80 -i eth0 \-m state --state NEW -m recent --update \--seconds 60 --hitcount 15 -j DROP
Правила урезают лимит на количество подключений с одного IP в минуту до 15. То же можно сделать и с помощью pf:
# vi /etc/pf.conf
webserver_ip="1.1.1.1"table <abuse> persistblock in quick from <abuse>pass in on $ext_if proto tcp to $webserver_ip \port www flags S/SA keep state \(max-src-conn 100, max-src-conn-rate 15/60, \overload <abusive_ips> flush)
Кроме лимита на количество последовательных подключений (15 в минуту), данное правило устанавливает дополнительный лимит на количество одновременных подключений равный 100.
Настрой PHP
Если ты используешь nginx в связке с PHP, не забудь настроить и его. Вот как должен выглядеть конфигурационный файл /etc/php/php.ini защищенного сервера:
# vi /etc/php/php.ini
# Отключаем опасные функцииdisable_functions = phpinfo, system, mail, exec# Максимальное время исполнения скриптаmax_execution_time = 30# Максимальное время, которое может потратить скрипт на обработку данных запросаmax_input_time = 60# Максимальное количество памяти, выделяемое каждому скриптуmemory_limit = 8M# Максимальный размер данных, отсылаемых скрипту с помощью метода POSTpost_max_size = 8M# Максимальный размер загружаемых файловupload_max_filesize = 2M# Не показывать ошибки PHP-скриптов пользователямdisplay_errors = Off# Включаем Safe Modesafe_mode = On# Включаем SQL Safe Modesql.safe_mode = On# Позволяем выполнять внешние команды только в этом каталогеsafe_mode_exec_dir = /путь/к/защищенному/каталогу# Защищаемся от утечки информации о PHPexpose_php = Off# Ведем логиlog_errors = On# Запрещаем открытие удаленных файловallow_url_fopen = Off
Выводы
Применив описанные в статье рекомендации, ты получишь гораздо более защищенный Web-сервер. Но имей в виду, что не все техники подойдут к твоей конфигурации. Например, защита от брутфорса, основанная на урезании размеров буферов, выделяемых nginx под обработку запросов клиентов, может привести к падению производительности, а в некоторых случаях и к сбоям в обработке запросов. Ограничение на количество подключений нанесет сильный удар по производительности даже средненагруженного Web-сайта, но принесет пользу, если страница имеет низкий поток посетителей. Всегда проверяй, как внесенные тобой изменения повлияли на производительность и общую работоспособность Web-страницы.
О герое дня
Nginx – один самых производительных и популярных Web-серверов в мире. Согласно данным Netcraft, он используется для поддержки более чем 12 миллионов Web-сайтов по всему миру, включая таких мастодонтов как Rambler, Yandex, Begun, WordPress.com, Wrike, SourceForge.net, vkontakte.ru, megashara.com, Либрусек и Taba.ru. Грамотная архитектура, основанная на мультиплексировании соединений с помощью системных вызовов select, epoll (Linux), kqueue (FreeBSD) и механизме управления памятью на основе пулов (небольших буферов от 1 до 16 Кб), позволяет nginx не проседать даже под очень высокими нагрузками, выдерживая свыше 10000 одновременных соединений (так называемая проблема C10K). Изначально написан Игорем Сысоевым для компании Rambler и открыт в 2004 году под BSD-подобной лицензией.
Взято с xakep.ru
Вконтакте
Google+
LiveJournal
Одноклассники
Мой мир
disnetern.ru
Оптимизация nginx и другие полезности
В прошлом посте я писал про то, что такое nginx и как его установить. Теперь же расскажу, как его оптимизировать под свои нужды.
Failover и балансировка
Крупные проекты редко состоят из одного сервера приложений. Часто их два или больше, и возникает задача балансировки клиентов по этим серверам, а также выполнения failover — необходимо чтобы выход из строя одного из серверов не был заметен для клиентов.Простейший способ рещить эту задачу — dns round-robin, т.е. назначение доменному имени нескольких ip-адресов. Но это решение имеет ряд недостатков, и гораздо лучше выглядит решение балансировки запросов по бакендам на фронтенде nginx. В конфигурационном файле выглядит это примерно так:# объявляем upstream — список бакендов
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | upstream backend { # перечисляем dns-имена или ip-адреса серверов и их «вес» server web1 weight=5; server 1.2.3.4:8080 weight=5; # а так можно подключаться к бакенду через unix-сокет server unix:/tmp/backend3 weight=1; } # конфигурация виртуального сервера server { listen <...>; server_name myserver.com; # отправляем все запросы из локейшена / в апстрим location / { proxy_pass http://backend; } } |
upstream backend { # перечисляем dns-имена или ip-адреса серверов и их «вес» server web1 weight=5; server 1.2.3.4:8080 weight=5; # а так можно подключаться к бакенду через unix-сокет server unix:/tmp/backend3 weight=1; } # конфигурация виртуального сервера server { listen <...>; server_name myserver.com; # отправляем все запросы из локейшена / в апстрим location / { proxy_pass http://backend; } }
Запросы, приходящие к nginx, распределяются по бакендам соответственно указаному весу. Кроме того, можно сделать так, чтобы запросы с одних и тех же IP-адресов отправлялись на одни и те же серверы (для этого в upstream нужно указать директиву ip_hash). Так можно решить проблему с сессиями, но все же лучше найти какой-нибудь способ их репликации или (что еще лучше) использовать .В случае, если один из серверов откажется принимать соединения или соединение к нему отвалится по таймауту, он на некоторое время будет исключен из upstream.
Собственно оптимизация nginx
1. Увеличение количества и объема буферов
Для хранения принятых запросов и еще не отданных ответов nginx использует буферы в памяти, а если запрос или ответ не помещается в них, nginx записывает его во временный файл (и пишет при этом предупреждение в log-файл). Поэтому необходимо установить такие размеры, чтобы в большинстве случаев не требовалось обращаться к временному файлу, а с другой стороны — чтобы буферы не использовали слишком много памяти.
Для этого используются следующие параметры:client_body_buffer_size (по умолчанию: 8k/16k — в зависимости от архитектуры) — задает размер буфера для чтения тела запроса клиента. Обычно стандартного значения хватает, его требуется повышать, только если ваше приложение устанавливает огромные cookies.proxy_buffer_size (по умолчанию: 4k/8k) — задает размер буфера, в который будет читаться первая часть ответа, получаемого от проксируемого сервера. В этой части ответа находится, как правило, небольшой заголовок ответа. Стандартного значения обычно хватает.proxy_buffers (по умолчанию: 8 4k/8k) — задает число и размер буферов для одного соединения, в которые будет читаться ответ, получаемый от проксируемого сервера. Установите этот параметр так, чтобы большинство ответов от бэкенда помещалось в буферы.
2. Механизмы обработки соединений
Есть одна тонкость, касающаяся механизма обработки соединений, а именно — способ получения информации о событиях на сокетах. Существуют следующие методы:
* select — стандартный метод. На большой нагрузке сильно нагружает процессор.* poll — стандартный метод. Также сильно нагружает процессор.* kqueue — эффективный метод, используемый в операционных системах FreeBSD 4.1+, OpenBSD 2.9+, NetBSD 2.0 и Mac OS X. На 2-процессорных машинах под управлением Mac OS X использование kqueue может привести к kernel panic.* epoll — эффективный метод, используемый в Linux 2.6+. В некоторых старых дистрибутивах есть патчи для поддержки epoll ядром 2.4.* rtsig — real time signals, эффективный метод, используемый в Linux 2.2.19+. При больших количествах одновременных соединений (более 1024) с ним могут быть проблемы (их можно обойти, но на мой взгляд, лучше с этим не связываться).* /dev/poll — эффективный метод, используемый в Solaris 7 11/99+, HP/UX 11.22+ (eventport), IRIX 6.5.15+ и Tru64 UNIX 5.1A+.
При компиляции nginx автоматически выбирается максимально эффективный найденый метод, однако скрипту configure можно насильно указать какой метод использовать. Если вы решили сделать это, то лучше использовать такие методы:Linux 2.6: epoll;FreeBSD: kqueue;Solaris, HP/UX и другие: /dev/poll;Linux 2.4 и 2.2: rtsig, не рекомендуется при больших нагрузках.
Включение gzip позволяет сжимать ответ, отправляемый клиенту, что положительно сказывается на удовлетворенности пользователя, но требует больше времени CPU. Gzip включается директивой gzip (on|off). Кроме того, стоит обратить на следующие важные директивы модуля gzip:
gzip_comp_level 1..9 — устанавливает уровень сжатия. Опытным путем выявлено, что оптимальные значения лежат в промежутке от 3 до 5, большие значения дают маленький выигрыш, но создают существенно большую нагрузку на процессор, меньшие — дают слишком маленький коэффициент сжатия.gzip_min_length (по умолчанию, 0) — минимальный размер ответа, который будет сжиматься. Имеет смысл поставить этот параметр в 1024, чтобы слишком малеьнике файлы не сжимались (т.к. эффективность этого будет мала).gzip_types mime-тип [mime-тип …] — разрешает сжатие ответа методом gzip для указанных MIME-типов в дополнение к «text/html». «text/html» сжимается всегда. Имеет смысл добавить такие mime-типы как text/css, text/javascript и подобные. Разумеется, сжимать gif, jpg и прочие уже компрессированые форматы не имеет смысла.
Кроме того, существует модуль gzip_static, который позволяет раздавать уже сжатые статические файлы. В конфирурационном файле это выглядит так:location /files/ {gzip on;gzip_min_length 1024;gzip_types text/css text/javascript;gzip_comp_level 5;gzip_static on;}
При использовании такой конфигурации в случае запроса «/files/test.html» nginx будет проверять наличие «/files/test.html.gz», и, если этот файл существует и дата его последнего изменения больше, чем дата последнего изменения файла test.html, будет отдан уже сжатый файл, что сохранит ресурсы процессора, которые потребовались бы для сжатия оригинального файла.
Оптимизация приложений
Существует очень полезный трюк, который позволяет указать разработчикам приложений, какие страницы нужно оптимизировать в первую очередь. Для этого потребуется в конфиге nginx указать новый формат лога:
1 2 3 4 5 6 | log_format my_combined '$remote_addr - $remote_user [$time_local] ' '"$request" $status $body_bytes_sent ' '"$http_referer" "$http_user_agent" ' '$upstream_response_time "$host"' access_log /var/log/nginx/access_log my_combined; |
log_format my_combined '$remote_addr - $remote_user [$time_local] ' '"$request" $status $body_bytes_sent ' '"$http_referer" "$http_user_agent" ' '$upstream_response_time "$host"' access_log /var/log/nginx/access_log my_combined;
Переменная $upstream_response_time содержит время ответа бэкенда, поэтому в лог попадает время обработки каждого запроса бэкендом. Далее понадобятся два скрипта:
1. /usr/local/bin/url_stats_report.sh:
1 2 3 4 5 6 7 | #!/bin/sh echo "=== Requests which took most of the time ===" > /tmp/report.txt echo "overall time - number of requests - average time - url" >> /tmp/report.txt cat /var/log/nginx/*access.log | /usr/local/bin/url_stats.py >> /tmp/report.txt cat /tmp/report.txt | mail -s "url performance report" root |
#!/bin/sh echo "=== Requests which took most of the time ===" > /tmp/report.txt echo "overall time - number of requests - average time - url" >> /tmp/report.txt cat /var/log/nginx/*access.log | /usr/local/bin/url_stats.py >> /tmp/report.txt cat /tmp/report.txt | mail -s "url performance report" root
2. /usr/local/bin/url_stats.py:
1 2 3 4 5 6 7 8 9 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 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | #!/usr/bin/env python import sys urls = {} try: while 1: line = raw_input() line_arr = line.split(" ") try: host = line_arr[-1] host = host[1:] host = host[:-1] url = line_arr[6] t = float(line_arr[-2]) #print host, url, t try: urls[host + url] = (urls[host + url][0] + t, urls[host + url][1] + 1) except KeyError, e: urls[host + url] = (t, 1) except ValueError, e: pass except EOFError, e: pass def sort_by_value(d): """ Returns the keys of dictionary d sorted by their values """ items=d.items() backitems=[ [v[1],v[0]] for v in items] backitems.sort(reverse=True) return [backitems[i][1] for i in range(0,len(backitems))] if (len(sys.argv) > 1): f = open(sys.argv[1], 'r') for k in f.readlines(): k = k.strip() try: print urls[k][0], urls[k][1], urls[k][0] / urls[k][1], k except: print 0, 0, k else: i = 0 for k in sort_by_value(urls): print urls[k][0], urls[k][1], urls[k][0] / urls[k][1], k i += 1 if i > 100: break |
#!/usr/bin/env python import sys urls = {} try: while 1: line = raw_input() line_arr = line.split(" ") try: host = line_arr[-1] host = host[1:] host = host[:-1] url = line_arr[6] t = float(line_arr[-2]) #print host, url, t try: urls[host + url] = (urls[host + url][0] + t, urls[host + url][1] + 1) except KeyError, e: urls[host + url] = (t, 1) except ValueError, e: pass except EOFError, e: pass def sort_by_value(d): """ Returns the keys of dictionary d sorted by their values """ items=d.items() backitems=[ [v[1],v[0]] for v in items] backitems.sort(reverse=True) return [backitems[i][1] for i in range(0,len(backitems))] if (len(sys.argv) > 1): f = open(sys.argv[1], 'r') for k in f.readlines(): k = k.strip() try: print urls[k][0], urls[k][1], urls[k][0] / urls[k][1], k except: print 0, 0, k else: i = 0 for k in sort_by_value(urls): print urls[k][0], urls[k][1], urls[k][0] / urls[k][1], k i += 1 if i > 100: break
Они не идеальны, но задачу выполняют: запуская /usr/local/bin/url_stats_report.sh (например, в postrotate утилиты logrotate), вы получаете наглядную картину, какие запросы занимают большую часть времени бэкенда.
Кеширование
На данный момент существует версия nginx-0.7.59 которая поддерживает кеширование и является стабильной.. Я не могу проверить, так как использую более раннюю версию 0.7.26Однако это все еще экспериментальная функция, но я решил рассказать о ней, т.к. ее одень давно ждали многое администраторы, да и лично для меня она очень полезна.Сейчас nginx умеет кешировать на диске ответы от http и fastcgi запросов на бакенды, указывать ключ для кеширования, учитывать заголовки «X-Accel-Expires», «Expires» и «Cache-Control» и вручную устанавливать максимальне время жизни объекта в кеше.Обслуживанием кеша (очиста старых файлов, наблюдение за размером и т.п.) занимается специальный процесс cache manager. Положительной особенностью реализации является то, что при старте nginx cache manager начинает проверку кеша в фоне, благодаря чему nginx не делает то что называется «дает сквида», т.е. он не висит несколько минут проверяя кеш перед стартом.Я намеренно не указываю пример конфигурации, т.к. во-первых директивы могут еще поменяться, а во-вторых нужно глубокое понимание механизма кеширования, что требует вдумчивого чтения документации (http://sysoev.ru/nginx/docs/http/ngx_http_proxy_module.html#proxy_cache) и архивов рассылки nginx-ru.
sqrs.ru
К бою готов! Руководство по оптимизации Nginx — PEKTOP
Большинство руководств по установке и настройке Nginx дают вам основы — apt-get install package, измените несколько строк здесь и там, и у вас готов веб-сервер! В большинстве случаев ванильная установка будет прекрасно работать для обслуживания вашего сайта. Тем не менее, если вы действительно пытаетесь выжать производительность из Nginx, вы должны будете пойти немного дальше. В этом руководстве я объясню какие параметры в Nginx должны быть точно настроены для оптимизации производительности для обслуживания большого количества клиентов. Это не полное руководство по тонкой настройки. Это краткая информация о некоторых настройках для повышения производительности. Ваш прирост в производительности может менять в зависимости от конкретной конфигурации и железа.
Базовая (оптимизированная) конфигурация
Единственный файл, который мы будем изменять nginx.conf, который содержит все свои настройки для Nginx. Надеюсь вы в состоянии найти nginx.conf в /etc/nginx/ на вашем сервере. Во-первых, мы поговорим о некоторых глобальных настройках, а затем пройдемся по каждому модулю в файле и поговорим о том, какие настройки помогут вам найти лучший вариант для обработки большого количества запросов, и почему они увеличивают производительность. Окончательный файл конфигурации можно найти в конце этого поста.
Верхний уровень конфига
Nginx имеет несколько параметров верхнего уровня, которые находятся за пределами модулей в файле nginx.conf.
user www-data; pid /var/run/nginx.pid; worker_processes auto; worker_rlimit_nofile 65000;
user www-data; pid /var/run/nginx.pid;
worker_processes auto;
worker_rlimit_nofile 65000; |
user и pid оставим по-умолчанию, т.к. они нам не помогут в увеличении производительности.
worker_processes изменяет количество процессов, которое должен использовать Nginx для обслуживания вашего сайта. Оптимальное значение зависит от множества факторов, включая (но не ограничиваясь) число ядер процессора, колличество жестких дисков для хранения данных и характер нагрузки. Если вы сомневаетесь, то установить этот параметр равный количеству доступных ядер процессора и это будет отличным началом (значение «auto» попытается автоматически определить это).
worker_rlimit_nofile устанавливает ограничение на максимальное количество открытых файлов для процессов. Если он не установлен, то ваша ОС сама будет ограничивать это. Скорее всего ваша ОС и Nginx может обрабатывать более «ulimit -n«, поэтому мы установим его настолько великим, чтобы никогда не было проблем с «слишком много открытых файлов» (прим. преводчика: too many open files). Не забудьте обновить это знанчие в своей операционной системе.
Модуль Events
Этот модуль содержит все параметры обработки соединений в Nginx.
events { worker_connections 2048; multi_accept on; use epoll; }
events { worker_connections 2048;
multi_accept on;
use epoll; } |
worker_connections устанавливает максимальное количество одновременных соединений на одном рабочем процессе. Так как мы столкнулись уже с worker_rlimit_nofile, то можно смело устанавливать его довольно большим.
multi_accept говорит Nginx принимать столько соединений, сколько возможно после получения уведомления о новом соединении.
use устанавливае какой метод обработки мы должны использовать для мультиплексирования клиентов на потоках. Если вы используете Linux 2.6+, то вы должны использовать Epoll. Если вы используете *BSD, то вы должны использовать Kqueue. Кроме того, если вы не включите этот параметр, то Nginx выберит его за вас. Хотите узнать большье о методах обработки соединений? Начните с документации.
Модуль HTTP
Контролирует все основные функции обработки HTTP. Тут есть довольно много настроек и мы будем рассматривать их по частям.
http { sendfile on; tcp_nopush on; tcp_nodelay on; ... }
http {
sendfile on;
tcp_nopush on; tcp_nodelay on;
... } |
sendfile позволяет использовать sendfile(). Это функци ОС, она копирует данные с диска сразу в кэш ОС и так как копирование происходит в ядре ОС, sendfile() более эффетивен чем read(), а затем write() (подробнее о sendfile()).
tcp_nopush позволяет отправлять все заголовки одним пакетом, а не один за другим.
tcp_nodelay заставляет Nginx не буфиризировать данные и отправлять маленькими, короткими очередями — утанавливайте этот параметр только для приложений, которые часто отправляют небольшие пакеты данных, не получая немедленный ответ, где требуется своевременная доставка данных.
access_log off; error_log /var/log/nginx/error.log crit;
access_log off;
error_log /var/log/nginx/error.log crit; |
access_log устанавливает, будет ли писаться журнал доступа. Отлючив журнал доступа вы выигрываете в скорости за счет ввода-вывода на диске (IO aka, YOLO).
error_log устанавливает логирование только критических ошибок (флаг crit).
keepalive_timeout 20; client_header_timeout 20; client_body_timeout 20; reset_timedout_connection on; send_timeout 20;
keepalive_timeout 20;
client_header_timeout 20; client_body_timeout 20;
reset_timedout_connection on;
send_timeout 20; |
keepalive_timeout назначает таймаут для keep-alive соединения. Сервер будет закрывать соединения по истечению этого времени. Мы становим его малым, так как каждое соединение держит открытым файл.
client_header_timeout и client_body_timeout устанавливает таймаут для заголовка и тела запроса соответственно. Установим их на таком же низком уровне.
reset_timeout_connection закрывает соединения для не отвечающих клиентов. Это позволит высвободить всю память, связанную с клиентом.
send_timeout устанавливает таймаут ответа клиенту. Этот таймаут не применяется ко всей передаче, а только между двумя последовательными операциями чтения. Если клиент не читал никаких данных для в это рвемя, то Nginx разрывает связь.
include /etc/nginx/mime.types; default_type text/html; charset UTF-8;
include /etc/nginx/mime.types;
default_type text/html;
charset UTF-8; |
директива include влючает содержимое другого файла в текущий. Здесь мы используем его для загрузки списка MIME-типов, который будет использован далее.
default_type устанавливает MIME-тип по-умолчанию, который будет включен в наш заголовок.
charset соответственно устанавливает кодировку по-умолчанию.
gzip on; # gzip_static on; gzip_proxied any; gzip_min_length 256; gzip_comp_level 4; gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;
gzip on;
# gzip_static on;
gzip_proxied any;
gzip_min_length 256;
gzip_comp_level 4;
gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript; |
gzip включает сжатие отсылаемых данных. Это позволит экономить на объеме отправляемых данных.
gzip_static включает поиск предварительно сжатых файлов. Этот парамет (в нашем примере закомметирован) требует предварительного сжатия ваших файлов, но не позволяет использовать максимально возможную степень сжатия (подробнее о gzip_static).
gzip_proxied позволяет или запрещает сжатие ответа на основе запроса/ответа. Мы установим его как any, чтобы сжимать и все запросы.
gzip_min_lenght устанавливает минимальное количество байт необходимое для сжатия. Если запрос занимает менее 256 байт, то мы не будем сжимать его, так как это будет замедлять общий процесс обработки запроса.
gzip_comp_level устанавливает степень сжатия данных. Возможное значение от 1 до 9. 9 самый медленный, но на выходе данные с самым маленьким объемом. Установим 4, чтобы сбалансировать скорость и степерь сжатия.
gzip_types устаналивает какие MIME-типы данных сжимать.
# cache informations about file descriptors, frequently accessed files # can boost performance, but you need to test those values open_file_cache max=65000 inactive=20s; open_file_cache_valid 30s; open_file_cache_min_uses 2; open_file_cache_errors on; ## # Virtual Host Configs # aka our settings for specific servers ## include /etc/nginx/conf.d/*.conf; include /etc/nginx/sites-enabled/*; }
# cache informations about file descriptors, frequently accessed files # can boost performance, but you need to test those values open_file_cache max=65000 inactive=20s; open_file_cache_valid 30s; open_file_cache_min_uses 2; open_file_cache_errors on;
## # Virtual Host Configs # aka our settings for specific servers ##
include /etc/nginx/conf.d/*.conf; include /etc/nginx/sites-enabled/*; } |
open_file_cache устанавливает максимальное количество записей в кэше, а также время кэширования. Установим наш максимум относительно высоким и избавимся от кэша через 20 сек.
open_file_cache_valid определяет интервал, когда необходимо проверять актуальность информацию о элементе в open_file_cache.
open_file_cache_min_uses определяет минимальное число обращений к файлу в течение времени, указанного в директиве inactive параметра open_file_cache.
open_file_cache_errors определяет, будет ли кэшироваться ошибки при поиске файлов.
include снова используется для включения файлов конфигурации в текущий. В том числе и настройки других модулей сервера.
Окончательный файл конфигурации
user www-data; pid /var/run/nginx.pid; worker_processes auto; worker_rlimit_nofile 65000; events { worker_connections 2048; multi_accept on; use epoll; } http { sendfile on; tcp_nopush on; tcp_nodelay on; access_log off; error_log /var/log/nginx/error.log crit; keepalive_timeout 20; client_header_timeout 20; client_body_timeout 20; reset_timedout_connection on; send_timeout 20; include /etc/nginx/mime.types; default_type text/html; charset UTF-8; gzip on; # gzip_static on; gzip_proxied any; gzip_min_length 256; gzip_comp_level 4; gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript; open_file_cache max=65000 inactive=20s; open_file_cache_valid 30s; open_file_cache_min_uses 2; open_file_cache_errors on; include /etc/nginx/conf.d/*.conf; include /etc/nginx/sites-enabled/*; }
1 2 3 4 5 6 7 8 9 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 37 38 39 40 41 42 43 44 |
user www-data; pid /var/run/nginx.pid; worker_processes auto; worker_rlimit_nofile 65000;
events { worker_connections 2048; multi_accept on; use epoll; }
http { sendfile on; tcp_nopush on; tcp_nodelay on;
access_log off; error_log /var/log/nginx/error.log crit;
keepalive_timeout 20; client_header_timeout 20; client_body_timeout 20; reset_timedout_connection on; send_timeout 20;
include /etc/nginx/mime.types; default_type text/html; charset UTF-8;
gzip on; # gzip_static on; gzip_proxied any; gzip_min_length 256; gzip_comp_level 4; gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;
open_file_cache max=65000 inactive=20s; open_file_cache_valid 30s; open_file_cache_min_uses 2; open_file_cache_errors on;
include /etc/nginx/conf.d/*.conf; include /etc/nginx/sites-enabled/*; } |
После редактирования файлов конфигурации, перезапустите nginx для того, чтобы убедиться, что он использует актуальные настройки.
sudo service nginx reload
sudo service nginx reload |
Заключение
Поехали! Теперь ваш Nginx готов к бою с армией посетителей, которые замедляли работу сервера ранее. Это ни в коем случае не является единственным путем, которым вы можете пойти, ускоряя ваш сайт. Я буду писать новые посты, в которых раскажу и другие способы в ближайшее время.
Здавайте вопросы и пишите предложения в комментариях.
Оригинальный пост на английском языке
pektop.net