Windows 8

Тонкая настройка Nginx. Защита, оптимизация

Тонкая настройка Nginx. Защита, оптимизация

Nginx – это веб-сервер вкупе с почтовым прокси-сервером, публично доступный с 2004 года. Разработка проекта началась в 2002 году, по-русски название звучит как энджин-экс. Будучи творением рук известного программиста, Игоря Сысоева, первоначально Nginx предназначался для компании Rambler. Он рассчитан на операционные системы, относящиеся к группе Unix-подобных. Сборка успешно тестировалась на OpenBSD, FreeBSD, Linux, Mac OS X, Solaris. На платформе Microsoft Windows Nginx стал работать с появлением бинарной сборки версии 0,7.52.

Статистика за март 2011 года свидетельствует, что количество сайтов, обслуживаемых Nginx, уже перешагнуло отметку в 22 миллиона. Сегодня Nginx используют такие известные проекты, как Rambler, Begun, Yandex, SourceForge.net, WordPress.com, vkontakte.ru и другие. Наряду с lighttpd, Nginx применяют для выдачи статичного контента, генерируемого «неудобным» веб-приложением, функционирующим «под началом» другого веб-сервера.
Но прежде чем углубляться в дебри функциональных особенностей Nginx – нелишним будет вспомнить, что такое веб-сервер вообще и прокси-сервер в частности.

Веб-сервер и прокси-сервер

Веб-сервером называется сервер, который принимает от веб-браузеров и других клиентов HTTP-запросы и выдаёт на них HTTP-ответы. Последние обычно представлены HTML- страницей, медиа-потоком, изображением, файлом, другими данными. Под веб-сервером понимается как программное обеспечение, осуществляющее веб-серверные функции, так и аппаратное. Обмен данными и запрошенной информацией осуществляется по протоколу HTTP.

В перечень дополнительных функций веб-серверов входит: авторизация и аутентификация пользователей, ведение журнала их обращений к ресурсам, поддержка HTTPS для защищённости коммутирования с клиентами и другие. Наиболее часто применяемым в Unix-подобных ОС веб-сервером является Apache. Третью строчку в списке клиентских предпочтений в настоящее время занимает Nginx.

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

Самым простым прокси-сервером считается Network Address Translator или NAT. В 2000 году прокси-NAT был встроен в дистрибутив Windows. Прокси-серверы, как и любое явление, имеют две стороны медали, то есть могут быть использованы как во благо, так и во зло. Например, с их помощью скрывают свои IP-адреса те, кто опасается санкций за свои неблаговидные действия в сети…

Функциональный ряд Nginx:

  • серверное обслуживание индексных файлов, статичных запросов, генерирование дескрипторов кэш открытых файлов, списка файлов;
  • акселерированное проксирование, элементарное распределение нагрузки, отказоустойчивость;
  • поддержка кэширования в ходе акселерированного проксирования и FastCGI;
  • поддержка FastCGI (акселелированная) и memcached серверов;
  • модульность, фильтры, включая «докачку» (byte-ranges) и сжатие (gzip);
  • HTTP-аутентификация, chunked ответы, SSI-фильтр;
  • параллельное выполнение нескольких подзапросов на странице, обрабатываемых через FastCGI или прокси в SSI-фильтре;
  • поддержка StartTLS и SSL;
  • возможность поддержки встроенного Perl;
  • простая аутентификация (USER/PASS, LOGIN);
  • серверперенаправление (IMAP/POP3-прокси) пользователя на IMAP/POP3-бэкенд с применением внешнего сервера аутентификации (HTTP).

Для тех, кто не «на ты» с данной терминологией – описание функционала Nginx может показаться весьма туманным. Но когда речь пойдёт о способах конкретного использования этого веб-сервера – он понемногу начнёт развеиваться.

Архитектура и конфигурация

Рабочие процессы в Nginx одновременно обслуживают множество соединений, обеспечивая их вызовами ОС (операционной системы) epoll (Linux), select и kqueue (FreeBSD). Данные, полученные от клиента, разбираются посредством конечного автомата. Обработку разобранного запроса осуществляет цепочка модулей, задаваемая конфигурацией. Формирование ответа клиенту происходит в буферах, которые могут указывать на отрезок файла или хранить данные в памяти. Последовательность передачи данных клиенту определяется цепочками, в которые группируются буферы.

В структурном отношении HTTP-сервер Nginx разделён на виртуальные серверы, которые в свою очередь делятся на location. Виртуальному серверу или директиве можно задать порты и адреса для приёма соединений. Для location можно задать точный URI, часть URI, или регулярное выражение.Для оперативного управления памятью служат пулы, являющиеся последовательностью заранее выбранных блоков памяти. Один блок, выделяемый изначально под пул, имеет длину от 1 до 16 килобайт. Он разделён на области – занятую и незанятую. По мере заполнения последней выделение нового объекта обеспечивается образованием нового блока.

Географическая классификация клиентов по их IP-адресу производится в Nginx посредством специального модуля. Система Radix tree позволяет оперативно работать с IP-адресами, занимая минимум памяти.

Преимущества Nginx

Nginx считается очень быстрым HTTP сервером. Вместо Apache или совместно с ним Nginx используют, чтобы ускорить обработку запросов и уменьшить нагрузку на сервер. Дело в том, что огромные возможности, заложенные модульной архитектурой Apache, большинству пользователей не требуются. Платить же за эту невостребованную функциональность приходится значительным расходом системных ресурсов. Для обычных сайтов, как правило, характерно явное «засилье» статичных файлов (изображений, файлов стилей, JavaScript), а не скриптов. Никакого специального функционала для передачи этих файлов посетителю ресурса не требуется, так как задача весьма проста. А, значит, и веб-сервер для обработки таких запросов должен быть простым и легковесным, как Nginx.

Способы применения Nginx

На отдельном порту/IP. Если ресурс насыщен изображениями или файлами для скачивания Nginx можно настроить на отдельном порту или же IP и раздавать через него статичный контент. Для этого, правда, придётся немного повозиться со сменой ссылок на сайте. При большом количестве запросов к статичным файлам есть смысл завести отдельный сервер и поставить на него Nginx.

Акселерированное проксирование . При этом варианте все посетительские запросы поступают вначале к Nginx. Запросы на получение статичных файлов (например, картинки, простого HTML, JavaScript или CSS-файла) Nginx обрабатывает самостоятельно. В случае обращения пользователя к тому или иному скрипту он переадресует запрос в ведомство Apache. Никаких трансформаций с кодом сайта делать при этом не нужно.

Если канал от сервера к посетителю и наоборот грешит медлительностью – такое применение Nginx может дать дополнительный эффект. Полученный от посетителя запрос Nginx передаёт для обработки Apache. Обработав запрос, Apache направляет страницу Nginx и с чувством выполненного долга прекращает соединение. Отправлять пользователю страницу Nginx может теперь как угодно долго, практически не расходуя системных ресурсов. Работа Apache на его месте сопровождалась бы неоправданно высокой нагрузкой на память при работе практически вхолостую. Кстати, этот вариант использования Nginx имеет ещё одно название: «frontend к Apache» .

Nginx плюс FastCGI. Apache может вообще не понадобиться, если интерпретатор языка, на котором написаны скрипты сайта, поддерживает FastCGI-технологию. К таким языкам относятся, например, PHP, Perl и ряд других. Правда, в этом случае возможно придётся модифицировать коды скриптов.

О том, как установить и настроить Nginx в сети есть немало детальных материалов. Узнать о Nginx подробнее можно и на сайте его разработчика Игоря Сысоева.

И другие). Текущая версия, 0.6.x, рассматривается как стабильная с точки зрения надежности, а релизы из ветки 0.7 считаются нестабильными. При этом важно заметить, что функциональность некоторых модулей будет меняться, вследствие чего могут меняться и директивы, поэтому обратной совместимости в nginx до версии 1.0.0 не гарантируется.

Чем же nginx так хорош и почему его так любят администраторы высоконагруженных проектов? Почему бы просто не использовать Apache?

Почему Apache - плохо?

Для начала нужно объяснить, как вообще работают сетевые серверы. Те, кто знаком с сетевым программированием, знают, что по сути существуют три модели работы сервера:

  1. Последовательная. Сервер открывает слушающий сокет и ждет, когда появится соединение (во время ожидания он находится в заблокированном состоянии). Когда приходит соединение, сервер обрабатывает его в том же контексте, закрывает соединение и снова ждет соединения. Очевидно, это далеко не самый лучший способ, особенно когда работа с клиентом ведется достаточно долго и подключений много. Кроме того, у последовательной модели есть еще много недостатков (например, невозможность использования нескольких процессоров), и в реальных условиях она практически не используется.
  2. Многопроцессная (многопоточная). Сервер открывает слушающий сокет. Когда приходит соединение, он принимает его, после чего создает (или берет из пула заранее созданных) новый процесс или поток, который может сколь угодно долго работать с соединением, а по окончании работы завершиться или вернуться в пул. Главный поток тем временем готов принять новое соединение. Это наиболее популярная модель, потому что она относительно просто реализуется, позволяет выполнять сложные и долгие вычисления для каждого клиента и использовать все доступные процессоры. Пример ее использования - Web-сервер Apache. Однако у этого подхода есть и недостатки: при большом количестве одновременных подключений создается очень много потоков (или, что еще хуже, процессов), и операционная система тратит много ресурсов на переключения контекста. Особенно плохо, когда клиенты очень медленно принимают контент. Получаются сотни потоков или процессов, занятых только отправкой данных медленным клиентам, что создает дополнительную нагрузку на планировщик ОС, увеличивает число прерываний и потребляет достаточно много памяти.
  3. Неблокируемые сокеты/конечный автомат. Сервер работает в рамках одного потока, но использует неблокируемые сокеты и механизм поллинга. Т.е. сервер на каждой итерации бесконечного цикла выбирает из всех сокетов тот, что готов для приема/отправки данных с помощью вызова select(). После того, как сокет выбран, сервер отправляет на него данные или читает их, но не ждет подтверждения, а переходит в начальное состояние и ждет события на другом сокете или же обрабатывает следующий, в котором событие произошло во время обработки предыдущего. Данная модель очень эффективно использует процессор и память, но достаточно сложна в реализации. Кроме того, в рамках этой модели обработка события на сокете должна происходить очень быстро - иначе в очереди будет скапливаться много событий, и в конце концов она переполнится. Именно по такой модели работает nginx. Кроме того, он позволяет запускать несколько рабочих процессов (так называемых workers), т.е. может использовать несколько процессоров.

Итак, представим следующую ситуацию: на HTTP-сервер с каналом в 1 Гбит/с подключается 200 клиентов с каналом по 256 Кбит/с:

Что происходит в случае Apache? Создается 200 потоков/процессов, которые относительно быстро генерируют контент (это могут быть как динамические страницы, так и статические файлы, читаемые с диска), но медленно отдают его клиентам. Операционная система вынуждена справляться с кучей потоков и блокировок ввода/вывода.

Nginx в такой ситуации затрачивает на каждый коннект на порядок меньше ресурсов ОС и памяти. Однако тут выявляется ограничение сетевой модели nginx: он не может генерировать динамический контент внутри себя, т.к. это приведет к блокировкам внутри nginx. Естественно, решение есть: nginx умеет проксировать такие запросы (на генерирование контента) на любой другой веб-сервер (например, все тот же Apache) или на FastCGI-сервер.

Рассмотрим механизм работы связки nginx в качестве «главного» сервера и Apache в качестве сервера для генерации динамического контента:

Nginx принимает соединение от клиента и читает от него весь запрос. Тут следует отметить, что пока nginx не прочитал весь запрос, он не отдает его на «обработку». Из-за этого обычно «ломаются» практически все индикаторы прогресса закачки файлов - впрочем, существует возможность починить их с помощью стороннего модуля upload_progress (это потребует модификации приложения).

После того, как nginx прочитал весь ответ, он открывает соединение к Apache. Последний выполняет свою работу (генерирует динамический контент), после чего отдает свой ответ nginx, который его буферизует в памяти или временном файле. Тем временем, Apache освобождает ресурсы. Далее nginx медленно отдает контент клиенту, тратя при этом на порядки меньше ресурсов, чем Apache.

Такая схема называется фронтэнд + бэкенд (frontend + backend) и применяется очень часто.

Установка

Т.к. nginx только начинает завоевывать популярность, имеются некоторые проблемы с бинарными пакетами, так что будьте готовы к тому, что его придется компилировать самостоятельно. С этим обычно не возникает проблем, надо лишь внимательно прочитать вывод команды./configure —help и выбрать необходимые вам опции компиляции, например такие:

./configure \
—prefix=/opt/nginx-0.6.x \ # префикс установки
—conf-path=/etc/nginx/nginx.conf \ # расположение конфигурационного файла
—pid-path=/var/run/nginx.pid \ # … и pid-файла
—user=nginx \ # имя пользователя под которым будет запускаться nginx
—with-http_ssl_module —with-http_gzip_static_module —with-http_stub_status_module \ # список нужных
—without-http_ssi_module —without-http_userid_module —without-http_autoindex_module —without-http_geo_module —without-http_referer_module —without-http_memcached_module —without-http_limit_zone_module # … и не нужных модулей

После конфигурирования стоит запустить стандартный make && make install, после чего можно пользоваться nginx.

Кроме того в Gentoo вы можете воспользоваться ebuild’ом из стандартного дерева портов; в RHEL/CentOS репозиторием epel (в нем расположени nginx 0.6.x) или srpm для версии 0.7, который можно скачать отсюда: http://blogs.mail.ru/community/nginx ; в Debian можно воспользоваться пакетом nginx из ветки unstable.

Конфигурационный файл

Конфигурационный файл nginx очень удобен и интуитивно понятен. Называется он обычно nginx.conf и распологается в $prefix/conf/ если расположение не было переопределено при компиляции. Я люблю класть его в /etc/nginx/, также делают и разработчики всех пакетов упомянутых выше.

Структура конфигурационного файла такова:

user nginx; # имя пользователя, с правами которого будет запускаться nginx
worker_processes 1; # количество рабочих процессов
events {
<…> # в этом блоке указывается механизм поллинга который будет использоваться (см. ниже) и максимальное количество возможных подключений
}

Http {
<глобальные директивы http-сервера, например настройки таймаутов и т.п.>;
<почти все из них можно переопределить для отдельного виртуального хоста или локейшена>;

# описание серверов (это то что в apache называется VirtualHost)
server {
# адрес и имя сервера
listen *:80;
server_name aaa.bbb;

<Директивы сервера. Здесь обычно указывают расположение докуменов (root), редиректы и переопределяют глобальные настройки>;

# а вот так можно определить location, для которого можно также переопределить практически все директивы указаные на более глобальных уровнях
location /abcd/ {
<директивы>;
}
# Кроме того, можно сделать location по регулярному выражению, например так:
location ~ \.php$ {
<директивы>;
}
}

# другой сервер
server {
listen *:80;
server_name ccc.bbb;

<директивы>
}
}

Обратите внимание на то, что каждая директива должна оканчиваться точкой с запятой.
Обратное проксирование и FastCGI

Итак, выше мы рассмотрели преимущества схемы frontend + backend, разобрались с установкой, структурой и синтаксисом конфигурационного файла, рассмотрим тепеть как реализовать обратное проксирование в nginx.

А очень просто! Например так:

location / {
proxy_pass http://1.2.3.4:8080;
}

В этом примере все запросы попадающие в location / будут проксироваться на сервер 1.2.3.4 порт 8080. Это может быть как apache, так и любой другой http-сервер.

Однако тут есть несколько тонкостей, связанных с тем, что приложение будет считать, что, во-первых, все запросы приходят к нему с одного IP-адреса (что может быть расценено, например, как попытка DDoS-атаки или подбора пароля), а во-вторых, считать, что оно запущено на хосте 1.2.3.4 и порту 8080 (соответственно, генерировать неправильные редиректы и абсолютные ссылки). Чтобы избежать этих проблем без необходимости переписывания приложения, мне кажется удобной следующая конфигурация:
Nginx слушает внешний интерфейс на порту 80.

Если бэкенд (допустим, Apache) расположен на том же хосте, что и nginx, то он «слушает» порт 80 на 127.0.0.1 или другом внутреннем IP-адресе.

Конфигурация nginx в таком случае выглядит следующим образом:

server {
listen 4.3.2.1:80;
# устанавливаем заголовок Host и X-Real-IP: к каждому запросу отправляемому на backend
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $host:$proxy_port;
# или «proxy_set_header Host $host;», если приложение будет дописывать:80 ко всем ссылкам
}

Для того, чтобы приложение различало IP-адреса посетителей, нужно либо поставить модуль mod_extract_forwarded (если оно исполняется сервером Apache), либо модифицировать приложение так, чтобы оно брало информацию о IP-адресе пользователя из HTTP-заголовка X-Real-IP.

Другой вариант бэкенд - это использование FastCGI . В этом случае конфигурация nginx будет выглядеть примерно так:

server {
<…>

# location, в который будут попадать запросы на php-скрипты
location ~ .php$ {
fastcgi_pass 127.0.0.1:8888; # определяем адрес и порт fastcgi-сервера,
fastcgi_index index.php; # …индексный файл

# и некоторые параметры, которые нужно передать серверу fastcgi, чтобы он понял какой скрипт и с какими параметрами выполнять:
fastcgi_param SCRIPT_FILENAME /usr/www/html$fastcgi_script_name; # имя скрипта
fastcgi_param QUERY_STRING $query_string; # строка запроса
# и параметры запроса:
fastcgi_param REQUEST_METHOD $request_method;
fastcgi_param CONTENT_TYPE $content_type;
fastcgi_param CONTENT_LENGTH $content_length;
}

# благодяря тому что локейшены с регулярными выражениями обладают большим «приоритетом», сюда будут попадать все не-php запросы.

location / {
root /var/www/html/
}

Статика

Для того, чтобы меньше нагружать бэкенд, статические файлы лучше отдавать только через nginx - он, с этой задачей справляется лучше, т.к. на каждый запрос он тратит существенно меньше ресурсов (не надо порождать новый процесс, да процесс nginx’а как правило потребляет меньше памяти, а обслуживать может множество соединений).

В конфигурационном файле это выглядит примерно так:

server {
listen *:80;
server_name myserver.com;

Location / {
proxy_pass


«>http://127.0.0.1:80;

}

# предположим что все статичные файлы лежат в /files
location /files/ {
root /var/www/html/; # указываем путь на фс
expires 14d; # добавляем заголовок Expires:
error_page 404 = @back; # а если файл не найден, отправляем его в именованный локейшн @back
}

# запросы из /files, для которых не было найдено файла отправляем на backend, а он может либо сгенерировать нужный файл, либо показать красивое сообщение об ошибке
location @back {
proxy_pass
» title=»http://127.0.0.1:80;

«>http://127.0.0.1:80;

}

Если вся статика не помещена в какой-то определенный каталог, то воспользоваться регулярным выражением:

location ~* ^.+\.(jpg|jpeg|gif|png|ico|css|zip|tgz|gz|rar|bz2|doc|xls|exe|pdf|ppt|txt|tar|wav|bmp|rtf|js)$ {
# аналогично тому что выше, только в этот location будут попадать все запросы оканчивающиеся на одно из указаных суффиксов
root /var/www/html/;
error_page 404 = @back;
}

К сожалению, в nginx не реализована асинхронная работа с файлами. Иными словами, nginx worker блокируется на операциях ввода-вывода. Так что если у вас очень много статических файлов и, в особенности, если они читаются с разных дисков, лучше увеличивать количество рабочих процессов (до числа, которое в 2-3 раза больше, чем суммарное число головок на диске). Это, конечно, ведет к увеличению нагрузки на ОС, но в целом производительность увеличивается. Для работы с типичным количеством статики (не очень большое количество сравнительно небольших файлов: CSS, JavaScript, изображения) вполне хватает одного-двух рабочих процессов.

To be continued

Ссылки

Тут можно найти дополнительноую информацию о nginx:

14 августа 2009 в 19:29

Настройка nginx

  • Nginx

Тема правильной настройки nginx очень велика, и, боюсь, в рамки одной статьи на хабре никак не помещается. В этом тексте я постарался рассказать про общую структуру конфига, более интересные мелочи и частности, возможно, будут позже. :)

Неплохой начальной точкой для настройки nginx является конфиг, который идёт в комплекте с дистрибутивом, но очень многие возможности этого сервера в нём даже не упоминаются. Значительно более подробный пример есть на сайте Игоря Сысоева: sysoev.ru/nginx/docs/example.html . Однако, давайте лучше попробуем собрать с нуля свой конфиг, с бриджем и поэтессами. :)

Начнём с общих настроек. Сначала укажем пользователя, от имени которого будет работать nginx (от рута работать плохо, все знают:))

Теперь скажем nginx-у, какое количество рабочих процессов породить. Обычно, хорошим выбором бывает число процессов, равное числу процессорных ядер в вашем сервере, но с этой настройкой имеет смысл поэкспериментировать. Если ожидается высокая нагрузка на жёсткий диск, можно сделать по процессу на каждый физический жёсткий диск, поскольку вся работа будет всё-равно ограничена его производительностью.

Worker_processes 2;

Уточним, куда писать логи ошибок. Потом, для отдельных виртуальных серверов, этот параметр можно переопределить, так что в этот лог будут сыпаться только «глобальные» ошибки, например, связанные со стартом сервера.

Error_log /spool/logs/nginx/nginx.error_log notice; # уровень уведомлений "notice", конечно, можно менять

Теперь идёт очень интересная секция «events». В ней можно задать максимальное количество соединений, которые одновременно будет обрабатывать один процесс-воркер, и метод, который будет использоваться для получения асинхронных уведомлений о событиях в ОС. Конечно же, можно выбрать только те методы, которые доступны на вашей ОС и были включены при компиляции.

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

Модули работы с событиями:
- select и poll обычно медленнее и довольно сильно нагружают процессор, зато доступны практически везде, и работают практически всегда;
- kqueue и epoll - более эффективны, но доступны только во FreeBSD и Linux 2.6, соответственно;
- rtsig - довольно эффективный метод, и поддерживается даже очень старыми линуксами, но может вызывать проблемы при большом числе подключений;
- /dev/poll - насколько мне известно, работает в несколько более экзотических системах, типа соляриса, и в нём довольно эффективен;

Параметр worker_connections:
- Общее максимальное количество обслуживаемых клиентов будет равно worker_processes * worker_connections;
- Иногда могут сработать в положительную сторону даже самые экстремальные значения, вроде 128 процессов, по 128 коннектов на процесс, или 1 процесса, но с параметром worker_connections=16384. В последнем случае, впрочем, скорее всего понадобится тюнить ОС.

Events {
worker_connections 2048;
use kqueue; # У нас BSD:)
}

Следующая секция - самая большая, и содержит самое интересное. Это описание виртуальных серверов, и некоторых параметров, общих для них всех. Я опущу стандартные настройки, которые есть в каждом конфиге, типа путей к логам.

Http {
# Весь код ниже будет внутри этой секции %)
# ...
}

Внутри этой секции могут находиться несколько довольно интересных параметров.

Системный вызов sendfile появился в Linux относительно недавно. Он позволяет отправить данные в сеть, минуя этап их копирования в адресное пространство приложения. Во многих случаях это существенно повышает производительность сервера, так что параметр sendfile лучше всегда включать.

Параметр keepalive_timeout отвечает за максимальное время поддержания keepalive-соединения, в случае, если пользователь по нему ничего не запрашивает. Обдумайте, как именно на вашем сайте посылаются запросы, и исправьте этот параметр. Для сайтов, активно использующих AJAX, соединение лучше держать подольше, для статических страничек, которые пользователи будут долго читать, соединение лучше разрывать пораньше. Учтите, что поддерживая неактивное keepalive-соединение, вы занимаете коннекшн, который мог бы использоваться по-другому. :)

Keepalive_timeout 15;

Отдельно стоит выделить настройки проксирования nginx. Чаще всего, nginx используется именно как сервер-прокси, соответственно они имеют довольно большое значение. В частности, размер буфера для проксируемых запросов имеет смысл устанавливать не менее, чем ожидаемый размер ответа от сервера-бэкенда. При медленных (или, наоборот, очень быстрых) бэкендах, имеет смысл изменить таймауты ожидания ответа от бэкенда. Помните, чем больше эти таймауты, тем дольше будут ждать ответа ваши пользователе, при тормозах бэкенда.

Proxy_buffers 8 64k;
proxy_intercept_errors on;
proxy_connect_timeout 1s;
proxy_read_timeout 3s;
proxy_send_timeout 3s;

Небольшой трюк. В случае, если nginx обслуживает более чем один виртуальный хост, имеет смысл создать «виртуальный хост по-умолчанию», который будет обрабатывать запросы в тех случаях, когда сервер не сможет найти другой альтернативы по заголовку Host в запросе клиента.

# default virtual host
server {
listen 80 default;
server_name localhost;
deny all;
}

Далее может следовать одна (или несколько) секций «server». В каждой из них описывается виртуальный хост (чаще всего, name-based). Для владельцев множества сайтов на одном хостинге, или для хостеров здесь может быть что-то, типа директивы

Include /spool/users/nginx/*.conf;

Остальные, скорее всего опишут свой виртуальный хост прямо в основном конфиге.

Server {
listen 80;

# Обратите внимание, в директиве server_name можно указать несколько имён одновременно.
server_name myserver.ru myserver.com;
access_log /spool/logs/nginx/myserver.access_log timed;
error_log /spool/logs/nginx/myserver.error_log warn;
# ...

Установим кодировку для отдачи по-умолчанию.

Charset utf-8;

И скажем, что мы не хотим принимать от клиентов запросы, длиной более чем 1 мегабайт.

Client_max_body_size 1m;

Включим для сервера SSI и попросим для SSI-переменных резервировать не более 1 килобайта.

Ssi on;
ssi_value_length 1024;

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

Nginx – это популярный и производительный веб-сервер и обратный прокси-сервер.

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

Примечание : Руководство выполнено на Ubuntu 12.04.

Иерархия каталогов Nginx

Nginx хранит конфигурационные файлы в каталоге /etc/nginx.

В этом каталоге находится ещё несколько каталогов и модульных конфигурационных файлов.

cd /etc/nginx
ls -F

conf.d/ koi-win naxsi.rules scgi_params uwsgi_params
fastcgi_params mime.types nginx.conf sites-available/ win-utf
koi-utf naxsi_core.rules proxy_params sites-enabled/

Пользователи Apache уже знакомы с каталогами sites-available и sites-enabled. Эти каталоги определяют конфигурации сайтов. Файлы обычно создаются и хранятся в sites-available; в sites-enabled хранятся только конфигурации включенных сайтов. Для этого нужно создать символическую ссылку из sites-available в sites-enabled.

Каталог conf.d тоже можно использовать для хранения конфигураций. Каждый файл с расширением.conf будет читаться при запуске Nginx. Синтаксис таких файлов не должен содержать ошибок.

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

Главным конфигурационным файлом Nginx является nginx.conf.

Файл nginx.conf

Файл nginx.conf читает соответствующие конфигурационные файлы и объединяет их в единый файл конфигурации при запуске сервера.

Откройте файл:

sudo nano /etc/nginx/nginx.conf

user www-data;
worker_processes 4;
pid /var/run/nginx.pid;
events {
worker_connections 768;
# multi_accept on;
}
http {
. . .

Первые строки задают общие сведения о Nginx. Строка user www-data указывает пользователя, с помощью которого запускается сервер.

Директива pid указывает, где будут храниться PID процессов для внутреннего использования. Строка worker_processes определяет количество процессов, которое может одновременно поддерживать Nginx.

Также в этой части файла можно указать логи (например, лог ошибок определяется с помощью директивы error_log).

За общими сведениями о сервере следует раздел events. Он управляет обработкой соединений Nginx. За ним идёт блок http. Прежде чем продолжить ознакомление с конфигурациями веб-сервера, нужно понять, как отформатирован конфигурационный файл Nginx.

Структура конфигурационного файла Nginx

Конфигурационный файл Nginx делится на блоки.

Первый блок – events, за ним идёт http и начинается главная иерархия конфигураций.

Детали конфигурации блока http делятся на уровни при помощи закрытых блоков, которые наследуют свойства из блока, в котором они расположены. В блоке http хранится большая часть общих конфигураций Nginx, которые делятся на блоки server, которые, в свою очередь, делятся на блоки location.

Во время настройки Nginx важно помнить следующее правило: чем выше уровень конфигурации, тем больше блоков наследует эту конфигурацию; чем ниже уровень конфигурации, тем она «индивидуальнее». То есть, если параметр Х должен применяться в каждом блоке server, то такой параметр нужно поместить в блок http.

Если вы внимательно рассмотрите файл, вы заметите, что он содержит много опций, которые определяют поведение программы как единого целого.

Например, чтобы настроить сжатие файлов, нужно установить такие параметры:

gzip on;
gzip_disable "msie6";

Это включит поддержку gzip для сжатия отправляемых клиенту данных и отключит gzip для Internet Explorer 6 (поскольку этот браузер не поддерживает сжатия данных).

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

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

Блок http в файле nginx.conf заканчивается так:

include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;

Это говорит о том, что блоки server и location, которые определяют настройки конкретных сайтов и URL-адресов, будут храниться за пределами этого файла.

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

Закройте файл nginx.conf. Теперь нужно изучить настройки отдельных сайтов.

Виртуальные блоки Nginx

Блоки server в Nginx являются аналогом виртуальных хостов Apache (но для удобства их тоже принято называть виртуальными хостами). По сути, блоки server – это технические характеристики отдельных веб-сайтов, размещённых на одном сервере.

В каталоге sites-available можно найти файл блока server по умолчанию, который поставляется вместе с сервером. Этот файл содержит все необходимые данные для обслуживания сайта.

cd sites-available
sudo nano default

root /usr/share/nginx/www;
index index.html index.htm;
server_name localhost;
location / {

}
location /doc/ {

alias /usr/share/doc/;
autoindex on;
allow 127.0.0.1;
deny all;

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

Блок server включает в себя все настройки, помещённые между фигурными скобками:

server {
. . .
}

Этот блок размещён в файле nginx.conf ближе к концу блока http с помощью директивы include.

Директива root определяет каталог, в котором будет храниться контент сайта. В этом каталоге Nginx будет искать запрашиваемые пользователем файлы. По умолчанию это каталог /usr/share/nginx/www.

Обратите внимание: все строки заканчиваются точкой с запятой. Так Nginx отделяет одну директиву от другой. Если точки с запятой не будет, Nginx прочитает две директивы (или несколько директив) как одну директиву с дополнительными аргументами.

Директива index определяет файлы, которые будут использоваться в качестве индекса. Веб-сервер будет проверять файлы в порядке их перечисления. Если ни одна страница не была запрошена, блок server найдёт и вернёт файл index.html. Если он не сможет найти этот файл, он попытается обработать index.htm.

Директива server_name

Директива server_name содержит список доменных имен, которые будут обслуживаться этим блоком server. Количество доменов неограниченно; домены в списке следует разделять пробелами.

Символ звёздочки (*) в начале или конце домена задаёт имя с маской, где звёздочка соответствует части (или нескольким частям) имени. Например, имя *.example.com будет соответствовать именам forum.example.com и www.animals.example.com.

Если запрашиваемый url-адрес соответствует нескольким директивам server_name, он сначала ответит той, с которой совпадает полностью.

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

Имена сервера, которые используют регулярные выражения, начинаются с тильды (~). К сожалению, данная тема выходит за рамки данной статьи.

Блоки location

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

Такие блоки могут содержать uri путь (например /doc/). Чтобы установить полное соответствие между location и uri, используется символ =. Символ ~ устанавливает соответствие с регулярными выражениями.

Тильда включает чувствительный к регистру режим, а тильда со звёздочкой – регистронезависимый режим.

Если запрос полностью соответствует блоку location, то сервер останавливает поиск и использует такой блок. Если сервер не находит полностью подходящего блока location, он сравнивает URI с параметрами директив location. Nginx выберет блок, в котором используется сочетание символов ^~ и который совпадает с URI.

Если опция ^~ не используется, Nginx выберет наиболее близкое совпадение и выполнит поиск по регулярным выражениям, чтобы попробовать подобрать один из доступных шаблонов. Если он найдёт такое выражение, то он использует его. Если такого выражения нет, то сервер использует найденное ранее совпадение с URI.

В качестве заключения следует отметить, что Nginx предпочитает точные соответствия. Если таких соответствий нет, он ищет регулярное выражение, а затем выполняет поиск по URI. Чтобы изменить приоритетность поиска по URI, используйте комбинацию символов ^~.

Директива try_files

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

Это позволяет вам с помощью дополнительных параметров определить, как Nginx будет обслуживать запросы.

В конфигурационном файле по умолчанию есть строка:

try_files $uri $uri/ /index.html;

Это значит, что при поступлении запроса, обслуживаемого блоком location, Nginx сначала попробует обслужить uri как файл (такое поведение задаёт переменная $uri).

Если сервер не обнаруживает соответствия переменной $uri, он попробует использовать uri как каталог.

С помощью слэша в конце сервер проверяет существование каталога, например, $uri/.

Если ни один файл или каталог не найден, Nginx выполняет файл по умолчанию (в данном случае это index.html в root-каталоге блока server). Каждая директива try_files использует последний параметр в качестве запасного варианта, потому этот файл должен существовать в системе.

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

Например, если блок location / не может найти запрашиваемый ресурс, вместо файла index.html он может вернуть ошибку 404:

try_files $uri $uri/ =404;

Для этого нужно поставить знак равно и задать код ошибки в качестве последнего параметра (=404).

Дополнительные параметры

Директива alias позволяет Nginx обслуживать страницы блока location вне заданного каталога (например, вне root).

Например, файлы, запрашиваемые в /doc/, будут обслужены из /usr/share/doc/.

Директива autoindex on позволяет включает листинг директорий Nginx для заданной директивы location.

Строки allow и deny управляют доступом к каталогам.

Заключение

Веб-сервер Nginx является многофункциональным и очень производительным средством, однако его терминология и параметры могут показаться запутанными.

Разобравшись с конфигурациями Nginx и научившись работать с ними, вы получите все преимущества этого мощного и легковесного инструмента.

Tags: ,

Тема правильной настройки nginx очень велика, и, боюсь, в рамки одной статьи на хабре никак не помещается. В этом тексте я постарался рассказать про общую структуру конфига, более интересные мелочи и частности, возможно, будут позже. :)

Неплохой начальной точкой для настройки nginx является конфиг, который идёт в комплекте с дистрибутивом, но очень многие возможности этого сервера в нём даже не упоминаются. Значительно более подробный пример есть на сайте Игоря Сысоева: sysoev.ru/nginx/docs/example.html . Однако, давайте лучше попробуем собрать с нуля свой конфиг, с бриджем и поэтессами. :)

Начнём с общих настроек. Сначала укажем пользователя, от имени которого будет работать nginx (от рута работать плохо, все знают:))

Теперь скажем nginx-у, какое количество рабочих процессов породить. Обычно, хорошим выбором бывает число процессов, равное числу процессорных ядер в вашем сервере, но с этой настройкой имеет смысл поэкспериментировать. Если ожидается высокая нагрузка на жёсткий диск, можно сделать по процессу на каждый физический жёсткий диск, поскольку вся работа будет всё-равно ограничена его производительностью.

Worker_processes 2;

Уточним, куда писать логи ошибок. Потом, для отдельных виртуальных серверов, этот параметр можно переопределить, так что в этот лог будут сыпаться только «глобальные» ошибки, например, связанные со стартом сервера.

Error_log /spool/logs/nginx/nginx.error_log notice; # уровень уведомлений "notice", конечно, можно менять

Теперь идёт очень интересная секция «events». В ней можно задать максимальное количество соединений, которые одновременно будет обрабатывать один процесс-воркер, и метод, который будет использоваться для получения асинхронных уведомлений о событиях в ОС. Конечно же, можно выбрать только те методы, которые доступны на вашей ОС и были включены при компиляции.

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

Модули работы с событиями:
- select и poll обычно медленнее и довольно сильно нагружают процессор, зато доступны практически везде, и работают практически всегда;
- kqueue и epoll - более эффективны, но доступны только во FreeBSD и Linux 2.6, соответственно;
- rtsig - довольно эффективный метод, и поддерживается даже очень старыми линуксами, но может вызывать проблемы при большом числе подключений;
- /dev/poll - насколько мне известно, работает в несколько более экзотических системах, типа соляриса, и в нём довольно эффективен;

Параметр worker_connections:
- Общее максимальное количество обслуживаемых клиентов будет равно worker_processes * worker_connections;
- Иногда могут сработать в положительную сторону даже самые экстремальные значения, вроде 128 процессов, по 128 коннектов на процесс, или 1 процесса, но с параметром worker_connections=16384. В последнем случае, впрочем, скорее всего понадобится тюнить ОС.

Events {
worker_connections 2048;
use kqueue; # У нас BSD:)
}

Следующая секция - самая большая, и содержит самое интересное. Это описание виртуальных серверов, и некоторых параметров, общих для них всех. Я опущу стандартные настройки, которые есть в каждом конфиге, типа путей к логам.

Http {
# Весь код ниже будет внутри этой секции %)
# ...
}

Внутри этой секции могут находиться несколько довольно интересных параметров.

Системный вызов sendfile появился в Linux относительно недавно. Он позволяет отправить данные в сеть, минуя этап их копирования в адресное пространство приложения. Во многих случаях это существенно повышает производительность сервера, так что параметр sendfile лучше всегда включать.

Параметр keepalive_timeout отвечает за максимальное время поддержания keepalive-соединения, в случае, если пользователь по нему ничего не запрашивает. Обдумайте, как именно на вашем сайте посылаются запросы, и исправьте этот параметр. Для сайтов, активно использующих AJAX, соединение лучше держать подольше, для статических страничек, которые пользователи будут долго читать, соединение лучше разрывать пораньше. Учтите, что поддерживая неактивное keepalive-соединение, вы занимаете коннекшн, который мог бы использоваться по-другому. :)

Keepalive_timeout 15;

Отдельно стоит выделить настройки проксирования nginx. Чаще всего, nginx используется именно как сервер-прокси, соответственно они имеют довольно большое значение. В частности, размер буфера для проксируемых запросов имеет смысл устанавливать не менее, чем ожидаемый размер ответа от сервера-бэкенда. При медленных (или, наоборот, очень быстрых) бэкендах, имеет смысл изменить таймауты ожидания ответа от бэкенда. Помните, чем больше эти таймауты, тем дольше будут ждать ответа ваши пользователе, при тормозах бэкенда.

Proxy_buffers 8 64k;
proxy_intercept_errors on;
proxy_connect_timeout 1s;
proxy_read_timeout 3s;
proxy_send_timeout 3s;

Небольшой трюк. В случае, если nginx обслуживает более чем один виртуальный хост, имеет смысл создать «виртуальный хост по-умолчанию», который будет обрабатывать запросы в тех случаях, когда сервер не сможет найти другой альтернативы по заголовку Host в запросе клиента.

# default virtual host
server {
listen 80 default;
server_name localhost;
deny all;
}

Далее может следовать одна (или несколько) секций «server». В каждой из них описывается виртуальный хост (чаще всего, name-based). Для владельцев множества сайтов на одном хостинге, или для хостеров здесь может быть что-то, типа директивы

Include /spool/users/nginx/*.conf;

Остальные, скорее всего опишут свой виртуальный хост прямо в основном конфиге.

Server {
listen 80;

# Обратите внимание, в директиве server_name можно указать несколько имён одновременно.
server_name myserver.ru myserver.com;
access_log /spool/logs/nginx/myserver.access_log timed;
error_log /spool/logs/nginx/myserver.error_log warn;
# ...

Установим кодировку для отдачи по-умолчанию.

Charset utf-8;

И скажем, что мы не хотим принимать от клиентов запросы, длиной более чем 1 мегабайт.

Client_max_body_size 1m;

Включим для сервера SSI и попросим для SSI-переменных резервировать не более 1 килобайта.

Ssi on;
ssi_value_length 1024;

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