Тонкая настройка 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, а второй отдавать статические картинки с локальной файловой системы. Для двух локейшнов это малоосмысленно, но для большего их числа имеет смысл также сразу определить переменную, в которой будет храниться корневой каталог сервера, и потом использовать её в описаниях локаций.

Более 50% трафика во всем мире обслуживает технология связки Apache и Nginx – веб сервера, которые имеют открытый исходный код. Nginx исполняет функцию фронтэнда, Apache – бэкэнда . Nginx первым принимает запросы пользователей и выдает по ним необходимый контент – изображения, файлы, скрипты. Тяжелый Apache в свою очередь не имеет с этим дело, а обрабатывает динамику. Nginx проксирует запросы и возвращает ответы . Данная связка отлично подходит для больших сайтов, которые посещают много пользователей. Для маленьких сайтов данная связка не даст роста производительности. Apache и Nginx снижает нагрузку на сервер в общем, благодаря тому, что Nginx обрабатывает статический контент, а Apache динамический.

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

Функциональный и быстрый Nginx был выпущен в 2004 году и после этого релиза начал набирать свою популярность. Благодаря своей легкости и масштабируемости хорошо работает на любом оборудовании. Nginx используют в двух направлениях: как веб сервер или как прокси.

Что делает Nginx в качестве веб сервера?

  • автоматически создает кэш дескрипторы и списки файлов, обслуживает индексные файлы и статические запросы;
  • ускоряет отказоустойчивость, проксирование и рапределение нагрузки;
  • кэширует при FastCGI и ускоряет проксирование;
  • поддерживает SSL;
  • поддерживает Perl;
  • имеет филтры и модульность;
  • аунтифецирует HTTP и фильтрирует SSL.

В качестве прокси Nginx:

  • полное обеспечение StartTLS и SSL;
  • легкость аутентификации (USER/PASS, LOGIN);
  • использует внешний HTTP-сервер для перенаправления на POP3/IMAP-бэкенд.

Как видим, Nginx выполняет множество функций, при этом не перегружая систему. По официальным данным, технологию используют более 56 млн. сайтов во всем мире (к примеру, Rambler, Yandex, Mail, Begun, WordPress.com, vk.com, Facebook, Rutracker.org), но по популярности Nginx уступает Apache. Почему же так популярен Apache?

Веб сервер Apache – кросплатформенное программное обеспечение, которое было создано в 1995 году. Благодаря большой документации и хорошей интеграции с сторонним ПО, Apache получил огромное распространение. Поддерживает следущие ОС – Linux, BSD, Mac OS, Microsoft Windows, Novell NetWare, BeOS. .

Преимущества веб сервера Apache:

  • поддержка языков программирования PHP, Python, Ruby, Perl, ASP, Tcl ;
  • легкость в подключении внешних модулей;
  • поддержка технологий CGI и FastCGI ;
  • наличие механизмов, которые обеспечивают безопасноть и разграничение к доступу данных;
  • возможность использовать СУБД для аутентификации пользователей;
  • гибкая и надежная конфигурация системы;
  • подходит для приложений, которым нужна мощная криптографическая защита данных ;
  • возможность создания пользовательских директорий для веб-сайта;
  • возможность настройки виртуальных хостов , с помощью которых на одном физическом сервере можно создать несколько виртуальных;
  • ведет протоколы того, что происходит на вашем сервере;
  • активная обратная связь с разработчиками и своевременное решения возникших ошибок в ПО.

Но несмотря на все достоинства веб-сервера Apache несколько тяжелый в настройке и работе, поэтому не каждый новичок сможет с ним справиться. Но если ваш проект нуждается именно в этом ПО, тогда вы сделаете правильный выбор в пользу Apache.

Хотите обезопасить работу PHP на сервере? Об этом более подробно .

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

Обо всех технологиях, которые поддерживает хостинг HyperHost, более подробно по .

Данная статья была предоставлена для общего ознакомления с возможностями связки веб серверов Apache и Nginx. Еще больше информации в .

Если понадобится наша помощь, обращайтесь!

Мы будем рады ответить на все интересующие вас вопросы по настройке веб серверов. Также у нас Вы всегда можете с бесплатным администрированием. Вся ли техническая поддержка хостеров одинакова? Об особенностях бесплатного и платного администрирования в специальной .

17248 раз(а) 9 Сегодня просмотрено раз(а)

На данный момент самую большую популярность набрали два веб-сервера. Это Apache и Ngnix. У каждого из них есть свои плюсы и минусы. Apache был разработан еще в 1995 году и при его разработке учитывались не все возможные потребности пользователей, он потребляет много памяти и ресурсов системы, зато он прост в настройке. Nginx был разработан чуть позже в 2002 году уже учитывая ошибки Apache и ориентируясь на максимальную производительность.

Мы не будем подробно вникать в плюсы и минусы этих обоих веб-серверов. У каждого из них своя область применения. В этой инструкции будет рассмотрена установка Nginx Ubuntu 16.04. Хотя я буду говорить об Ubuntu 16.04, все действия подойдут и для других дистрибутивов. Настройка Nginx везде одинакова, только команда установки отличается.

Первым делом нужно установить сам веб-сервер в систему. Программа есть в официальных репозиториях, но ее версия уже немного устарела, поэтому если хотите самую новую версию, нужно добавить PPA:

sudo apt-add-repository ppa:nginx/stable

Сейчас в официальных репозиториях доступна версия 1.10.0, а в стабильной PPA уже доступна 1.10.1. Если для вас версия не нужна можно обойтись и без PPA. Дальше обновите списки пакетов из репозиториев:

И устанавливаем ngnix:

sudo apt install nginx

После того как установка сервера Nginx будет завершена добавим программу в автозагрузку, чтобы она запускалась автоматически:

sudo systemctl enable nginx

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

Настройка Nginx Ubuntu

Настройка Nginx Ubuntu намного сложнее чем Apache. Здесь мы не будем рассматривать все опции и возможности программы, а поговорим только об основном. Есть различные конфигурации, в которых Nginx используется в качестве прокси сервера, а основной сервер Apache, но нас это интересовать не будет. Нам нужна установка Nginx как самостоятельного веб-сервера.

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

  • /etc/nginx/nginx.conf - главный файл конфигурации
  • /etc/nginx/sites-available/* - файлы конфигурации для виртуальных хостов, проще говоря для каждого сайта.
  • /etc/nginx/sites-enabled/* - файлы конфигурации активированных сайтов.

На самом деле файлы конфигурации для виртуальных хостов читаются только из директории sites-enabled, но здесь содержаться ссылки на sites-available. Такая система была придумана, чтобы дать возможность отключать на время те или иные сайты, не стирая их конфигурацию. Все остальные файлы содержат только объявления переменных и стандартные настройки, которые изменять не нужно. Что же касается nginx.conf, то в него включаются все файлы из sites-enables, а поэтому они могут содержать все точно такие же инструкции. А теперь давайте рассмотрим главный файл конфигурации:

sudo vi /etc/nginx/nginx.conf

Как видите файл разделен на секции. Общая структура такова:

глобальные опции
events {}
http{
server {
location{}
}
server {}
}
mail {}

  • глобальные опции отвечают за работу всей программы.
  • events - эта секция содержит настройки для работы с сетью.
  • http - содержит настройки веб-сервера. Должна содержать секцию servier для тонкой настройки каждого сайта.
  • server - в этой секции содержится настройка каждого размещенного на веб-сервере сайта.
  • location - секция location может находиться только внутри секции server и содержит настройки только для определенного запроса.
  • mail - содержит настройки почтового прокси.

Перед тем как перейти к опциям, нужно сказать еще пару слов о синтаксисе строки в конфигурационном файле. Он выглядит вот так:

параметр значение дополнительное_значение... ;

Строка должна обязательно заканчиваться ";", а все открытые скобки { должны быть закрыты.

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

  • user - пользователь, от имени которого будет работать программа.
  • worker_processes - устанавливает сколько процессов нужно запускать для параллелизации работы программы, нужно запускать не больше процессов, чем у вас есть ядер. Можно установить параметр auto и тогда программа определит это число сама.
  • pid = файл pid программы.
  • worker_rlimit_nofile - указывает максимальное количество файлов, которые может открыть программа. Рассчитывается как worker_processes * worker_connections* 2.

С глобальными опциями закончили, их было не так много и они не такие интереснее. Куда интереснее в плане оптимизации опции с секции events:

  • worker_connections - количество соединений, которые программа может обрабатывать одновременно на одном процессе. Если умножить worker_process на этот параметр, то мы получим максимальное количество пользователей, которые могут подключиться к серверу одновременно. Рекомендуется устанавливать значение от 1024 до 4048.
  • multi_accept - разрешить принимать много подключений одновременно, установите параметр on или off.
  • use - способ работы с сетевым стеком. По умолчанию используется poll, но для Linux эффективнее использовать epoll.
  • sendfile - использовать метод отправки данных sendfile. Значение on.
  • tcp_nodelay, tcp_nopush - отправлять заголовки и начало файла одним пакетом. Значение on.
  • keepalive_timeout - таймаут ожидания, перед тем как keepalive соединение будет разорвано, по умолчанию 65, но можно уменьшить до 10 секунд.
  • keepalive_requests - максимальное количество keepalive соединений от одного клиента, рекомендовано 100.
  • reset_timedout_connection - разрывать соединения после таймаута. Значение on.
  • open_file_cache - кэшировать информацию об открытых файлах. Строчка настройки выглядит вот так: open_file_cache max=200000 inactive=20s; max - максимальное количество файлов в кэше, время кэширования.
  • open_file_cache_valid - указывает по истечении какого времени нужно удалить информацию из кэша. Например: open_file_cache_valid 30s;
  • open_file_cache_min_uses - кэшировать информацию о файлах, которые были открыты как минимум указанное количество раз.
  • open_file_cache_errors - кэшировать информацию об отсутствующих файлах, значение on.

Основные параметры рассмотрели. Эти настройки помогут вам получить большую производительность от nginx. Секцию server и location мы рассмотрим в настройке виртуальных хостов.

Настройка сжатия Gzip

Сжатие контента необходимо, чтобы уменьшить размер загружаемых браузером данных. Это ускоряет загрузку сайта, но добавляет дополнительную нагрузку на процессор сервера. Чтобы включить сжатие в секции http нужно добавить параметр:

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

  • gzip_min_length - минимальная длина страницы в байтах, при которой нужно использовать сжатие, например, 1000 (1 кб)
  • gzip_proxied - нужно ли сжимать проксированые запросы, any говорит, что нужно сжимать все.
  • gzip_types - типы файлов, которые нужно сжимать, например: text/plain application/xml application/x-javascript text/javascript text/css text/json;
  • gzip_disable "msie6" - в IE 6 сжатие не поддерживается, поэтому отключаем.
  • gzip_comp_level - уровень сжатия, доступны варианты от 1 до 10. 1 - минимальное, 10 - максимальное сжатие.

Настройка виртуальных хостов

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

Рассмотрим пример настройки:

vi /etc/nginx/sites-enabled/сайт.conf

  • listen 80 - указывает, что нужно ожидать подключения на порту 80, может также содержать опцию default-server , которая означает, что этот домен будет открывается если домен не был задан в запросе.
  • root /var/www/html - директория, в которой находятся файлы сайта.
  • index index.html - страница, которая будет открываться по умолчанию.
  • server_name - доменное имя сайта.
  • access_log - файл для записи лога запросов к серверу, может использоваться как глобально в секции http, так и для определенного типа файлов в location.
  • error_log - лог ошибок веб-сервера, может принимать дополнительный параметр, указывающий подробность лога. warn - максимум, crit - только критические ошибки.

Это все основные настройки виртуального хоста, после них он уже будет работать. Но тут есть еще секция location, которая позволяет настроить поведение сервера для определенных директорий и файлов. Синтаксис location такой:

location адрес {}

В качестве адреса может использоваться как прямой запрос относительно корня сервера, так и регулярные выражения. Для использования регулярных выражений перед ним ставится символ "~". Примеры рассмотрим ниже, а пока рассмотрим возможные директивы:

  • allow - разрешить доступ к местоположению для пользователей, all - всех, также можно указать ip или подсеть.
  • deny - запретить доступ к местоположению, all - для всех.
  • try-files - пытается открыть файлы в определенном порядке, открывает первый обнаруженный файл. Например, такая конструкция: $uri $uri/index.html $uri.html =404; сначала пытается открыть $uri, затем index.html, если не найден $uri.html, и аж потом, если ни одного из предложных файлов не существует, выдает ошибку 404.
  • expires - задает время кэширования браузером отданного элемента, например, 1d - один день, 2h - два часа, 30s - 30 секунд.

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

Не выполнять логирование для favicon:

location = /favicon.ico {
log_not_found off;
access_log off;
}

Запретить доступ к файлам, начинающимся с точки:

location ~ /\. {
deny all;
}

Кэшировать обычные файлы на 90 дней:

location ~* ^.+\.(ogg|ogv|svg|svgz|eot|otf|woff|mp4|ttf|rss|atom|jpg|jpeg|gif|png|ico|zip|tgz|gz|rar|bz2|doc|xls|exe|ppt|tar|mid|midi|wav|bmp|rtf)$ {
access_log off; log_not_found off; expires 90d;

И другие). Текущая версия, 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:

Привет! Сегодня мы поговорим о таком нужном понятии, как виртуальные хосты (Virtual Hosts) в web-сервере nginx. В качестве примера мы будем использовать операционную систему Ubuntu. Для других Linux-систем настройка будет выглядеть очень похоже. Эта статья-инструкция будет интересна, в основном, начинающим web-мастерам и администраторам, т.к. у них чаще всего возникает данный вопрос.

Виртуальный хост — это…

Для начала давайте дадим определение виртуальному хосту. Итак, виртуальный хост — это разделение адресного пространства web-сервера, например, по имени сайта, позволяющее запускать несколько web-сайтов/приложений на одном физическом сервере. Если говорить в терминологии документации nginx, виртуальный хост также называется «Server Block» , но для большего сходства с Apache я буду называть его единообразно, т.к. назначение у них одно и то же. И ещё одно соглашение — давайте то, что мы будем настраивать, для простоты называть сайтом.

Создание виртуального хоста

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

Предустановка

Сейчас я скажу вещь, которую необходимо знать каждому! Для того, чтоб настроить виртуальный хост в nginx, вам нужен установленный на вашей машине wеb-сервер nginx. Капитан Очевидность с нами! Если nginx у вас уже установлен, можете смело пропускать этот шаг и двигаться дальше по инструкции. Если же его у вас по каким-то причинам на машине всё ещё нет, введите в консоли команду:

Sudo apt-get install -y nginx

Опцию «-y» команде apt-get мы добавляем для того, чтоб не отвечать да-да-да на назойливые вопросы установщика, ведь мы уверены, что хотим поставить этот пакет и согласны с использованием занимаемого им места на диске. Если вы всё-таки не уверены, что со всем согласны, то не добавляйте эту опцию.

Создание директории сайта

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

Путь к этой папке в конфигурации создаваемого хоста будет Document Root , своего рода контекстом, точкой изоляции, выше которой снаружи без предварительной настройки конфигурации подняться нельзя и относительно которой строятся пути до запрашиваемых файлов. С опцией «-p» у команды mkdir мы можем не заботиться о создании родительских директорий, они будут созданы автоматически:

Sudo mkdir -p /var/www/mysite.ru/public_html

Здесь мы используем реальный подтверждённый DNS домен с корректными записями, указывающими на нашу машину. Для создания виртуального хоста с незарегистрированным доменом, например, для локальной разработки, вам необходимо внести соответствующую запись в файле /etc/hosts. Подробнее об этом будет в конце статьи.

Права доступа

Сейчас права у нашей созданной папки есть только у root-пользователя. Мы должны дать права на директорию для нужного пользователя, чтоб не работать с ней постоянно в режиме супер-пользователя. Вы можете заменить пользователя «www-data», используемого ниже, на другого, но по умолчанию nginx работает от имени именно этого пользователя.

Sudo chown -R www-data:www-data /var/www/mysite.ru/public_html

Теперь сделаем так, чтобы все пользователи могли читать наши новые файлы:

Sudo chmod 755 /var/www

Мы подразумеваем, что работаем с VPS, на котором все пользователи ничего плохого не затевают или на котором есть только вы. Поэтому мы можем дать права 755 на папку /var/www. Если в вашем случае нельзя выдавать всем пользователям системы права на чтение этой директории, изучите вопрос с разграничением прав и настройте самостоятельно.

Теперь у вас всё с правами готово!

Создание страницы

Теперь нам необходимо разместить в нашей папке какие-нибудь статические файлы (HTML-страницы, картинки, скрипты, стили и т.д.), которые наш сервер будет раздавать. Давайте создадим HTML-страницу index.htm, которая будет на нашем сайте главной:

Sudo nano /var/www/mysite.ru/public_html/index.htm

И добавим в него немного разметки, которая будет показываться пользователю:

mysite.ru

Ура! Вы смогли настроить Virtual Host в nginx!

Сохраняем и выходим.

Создание конфигурации виртуального хоста

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

В nginx в директории /etc/nginx/sites-available есть шаблон для создаваемых конфигураций. Давайте скопируем его для нашего сайта:

Sudo cp /etc/nginx/sites-available/default /etc/nginx/sites-available/mysite.ru

Конфигурация виртуального хоста

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

Sudo nano /etc/nginx/sites-available/mysite.ru

Нам нужно внести изменения в текущую конфигурацию. В результате для нашего простого случая должно получиться примерно следующее:

Server { listen 80; root /var/www/mysite.ru/public_html; index index.html index.htm; server_name mysite.ru www.mysite.ru; }

От вас здесь требуется правильно указать путь к папке со статикой сайта и имя сервера, по которому вы будете обращаться к своему сайту. Если путь вы укажете неверно или не укажете вовсе, то вы не сможете настроить виртуальный хост. В качестве server_name вы также можете задать IP-адрес или несколько имён через пробел, по которым будет доступен хост, как мы и сделали.

Всё, с этим файлом мы закончили. Сохраняйте его и закрывайте.

Активация виртуального хоста

В nginx есть папки sites-available и sites-enabled. В первой хранятся конфигурации ВСЕХ виртуальных хостов, которые могут быть на данном сервере, а в директории sites-enabled символические ссылки на активные. Никто не запрещает в sites-enabled размещать оригинал файла конфигурации, а не ссылку, но это будет менее удобно, т.к. в случае необходимости отключения придётся либо удалять файл (тогда будет проблематично включить обратно), либо перемещать его в другую директорию (тогда мы должны помнить, куда мы перенесли). Гораздо проще грохнуть символическую ссылку!

Поэтому, теперь, чтоб активировать наш виртуальный хост, нам нужно создать символическую ссылку между директорией sites-available, где лежит наш файл конфигурации, и sites-enabled. В Apache для этого есть специальная команда a2ensite. В nginx такой команды нет, поэтому выполним следующее:

Sudo ln -s /etc/nginx/sites-available/mysite.ru /etc/nginx/sites-enabled/mysite.ru

Чтобы избежать «conflicting server name error» и быть уверенным, что ваш сайт отдаёт нужную информацию, можно из числа активных хостов удалить дефолтный:

Sudo rm /etc/nginx/sites-enabled/default

Перезагрузка

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

Sudo nginx -t

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

Если в ответ вы получили примерно следующее:

Nginx: the configuration file /etc/nginx/nginx.conf syntax is ok nginx: configuration file /etc/nginx/nginx.conf test is successful

То всё у вас хорошо и вы можете смело перезапускать сервер командой:

Sudo service nginx restart

В противном случае вам надо посмотреть файл конфигурации хоста. Что-то вы там не так указали.

Настройка локальных хостов

Если вы указали в качестве server name IP-адрес, вы можете пропустить этот шаг, т.к. настройка локального хоста вам не нужен, ваш виртуальный хост будет работать и без него. Но, если вы хотите работать с вашим виртуальным хостом без реального доменного имени, вы можете настроить локальные хосты на вашей машине. Как я уже говорил выше, это очень удобно, например, при разработке. Я могу создать mysite.dev, и на нём будет крутиться локальная нестабильная версия сайта. Для MacOS и Linux-систем надо выполнить следующую команду:

Sudo nano /etc/hosts

Если вы работаете под Windows, то файл с локальных хостов должен лежать примерно по этому пути C:\Windows\System32\drivers\etc\hosts.

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

12.34.56.789 mysite.ru 12.34.56.789 www.mysite.ru

Теперь до тех пор, пока эта запись не будет удалена, обращения по адресу mysite.ru будут получать информацию о данном хосте из этого файлика и перенаправлять вас к вашему удаленному серверу. Если сервер развернут локально, нужно написать вместо «12.34.56.789» «127.0.0.1».

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

Результаты

Теперь мы можем посмотреть результаты наших трудов! Вводим в браузере адрес http://mysite.ru или http://www.mysite.ru и любуемся созданной нами главной страницей из index.htm. Оба адреса должны показывать нашу главную страницу. Вот и всё! Наш виртуальный хост прекрасно работает.