Как работает HTTP-сервер nginx::Журнал СА 10.2008
www.samag.ru
     
Поиск   
              
 www.samag.ru    Web  0 товаров , сумма 0 руб.
E-mail
Пароль  
 Запомнить меня
Регистрация | Забыли пароль?
Журнал "Системный администратор"
Журнал «БИТ»
Наука и технологии
Подписка
Где купить
Авторам
Рекламодателям
Архив номеров
Контакты
   

  Опросы
  Статьи

Электронный документооборот  

5 способов повысить безопасность электронной подписи

Область применения технологий электронной подписи с каждым годом расширяется. Все больше задач

 Читать далее...

Рынок труда  

Системные администраторы по-прежнему востребованы и незаменимы

Системные администраторы, практически, есть везде. Порой их не видно и не слышно,

 Читать далее...

Гость номера  

Дмитрий Галов: «Нельзя сказать, что люди становятся доверчивее, скорее эволюционирует ландшафт киберугроз»

Использование мобильных устройств растет. А вместе с ними быстро растет количество мобильных

 Читать далее...

Прошу слова  

Твердая рука в бархатной перчатке: принципы soft skills

Лауреат Нобелевской премии, специалист по рынку труда, профессор Лондонской школы экономики Кристофер

 Читать далее...

Как хорошо вы это знаете  

Портал Инкоманд. Для чего он? Для кого? Какие проблемы решает?

Компания «ЕМДЕВ» – создатель интернет-портала, предлагает всем желающим протестировать себя на

 Читать далее...

1001 и 1 книга  
19.03.2018г.
Просмотров: 9881
Комментарии: 0
Потоковая обработка данных

 Читать далее...

19.03.2018г.
Просмотров: 8095
Комментарии: 0
Релевантный поиск с использованием Elasticsearch и Solr

 Читать далее...

19.03.2018г.
Просмотров: 8195
Комментарии: 0
Конкурентное программирование на SCALA

 Читать далее...

19.03.2018г.
Просмотров: 5191
Комментарии: 0
Машинное обучение с использованием библиотеки Н2О

 Читать далее...

12.03.2018г.
Просмотров: 5868
Комментарии: 0
Особенности киберпреступлений в России: инструменты нападения и защита информации

 Читать далее...

Друзья сайта  

 Как работает HTTP-сервер nginx

Архив номеров / 2008 / Выпуск №10 (71) / Как работает HTTP-сервер nginx

Рубрика: Веб /  Веб

Дмитрий Васильев

Как работает HTTP-сервер nginx

Уже долгое время Apache является наиболее популярным HTTP-сервером с открытым исходным кодом. Но он может быть слишком громоздким для некоторых pадач. И здесь на сцену выходят новые игроки – легковесные, асинхронные HTTP-серверы, одним из которых является nginx.

Вот уже более восьми лет я использую HTTP-сервер Apache, и в большинстве случаев он меня во всем устраивает. Но недавно, установив его на один из небольших серверов с Ubuntu Linux, я подумал, что Apache не очень целесообразно использует ресурсы сервера. И с этой мыслью решил попробовать какой-нибудь альтернативный вариант. Я уже давно слышал о высокопроизводительных асинхронных серверах Lighttpd (произносится lighty, http://www.lighttpd.net) и nginx (произносится engine x, http://sysoev.ru/nginx), но до этого момента не использовал их на практике. Надо также заметить, что по статистике Netcraft на октябрь 2008 года Lighttpd и nginx занимают, в рейтинге соответственно, 5-е и 6-е места: http://survey.netcraft.com/Reports/200810.

Теперь, когда у меня было два варианта, оставалось самое сложное – выбрать наиболее подходящий для моего случая. Это сложный выбор, т.к. оба имеют практически одинаковые возможности (хотя nginx также может использоваться как почтовый прокси-сервер, я не учитывал это в сравнении). Оба используются на высоко посещаемых сайтах, например, YouTube использует Lighttpd, а Rambler – nginx. Оба имеют достаточно хорошую документацию, в том числе nginx имеет документацию на русском. В итоге для себя я остановился на nginx по следующим причинам:

  •  Многие источники (например, http://hostingfu.com/article/nginx-vs-lighttpd-for-a-small-vps) отмечают, что Lighttpd имеет проблемы со стабильностью и утечки памяти. Даже если эти проблемы остались в прошлом, похоже, что автор не уделял им достаточно внимания.
  •  Nginx, в отличие от Lighttpd, имеет две официальные ветки разработки (стабильную и экспериментальную), что, на мой взгляд, говорит о большей заботе автора о конечных пользователях и качестве проекта в целом.
  •  Мне хотелось иметь возможность использовать сервер с языком Python (http://www.python.org) с помощью стандартного интерфейса WSGI (http://ru.wikipedia.org/wiki/WSGI). При этом для nginx существует дополнительный модуль mod_wsgi, а в Lighttpd это можно делать только через шлюз FastCGI > WSGI.

Принципы работы

Прежде чем обратиться к рассмотрению непосредственно сервера nginx, рассмотрим, чем отличается асинхронный (событийный) подход от параллельной обработки соединений в отдельных процессах, или потоках.

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

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

 Недостатки:

  •  Такой подход плохо масштабируется. Например, 1000 одновременно открытых соединений может быть вполне нормальным числом, но 1000 одновременно работающих процессов, или потоков, могут быть проблемой.

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

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

 Недостатки:

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

Как можно заметить, оба подхода имеют свои достоинства и недостатки. Чтобы объединить достоинства и уменьшить недостатки из обоих подходов, в настоящее время для асинхронных сетевых приложений наиболее популярен гибридный подход, при котором несколько асинхронных приложений работают параллельно в отдельных процессах, или потоках. Теперь рассмотрим, как это работает в nginx.

Особенности nginx

Nginx разрабатывается Игорем Сысоевым (http://sysoev.ru) с весны 2002 года. Первая публичная версия вышла осенью 2004 года. На данный момент сервер находится в активной разработке с точки зрения функциональности, но нет никаких нареканий с точки зрения стабильности. Последняя стабильная версия на данный момент – 0.6.32 (http://sysoev.ru/nginx/nginx-0.6.32.tar.gz).

Архитектурно nginx – это асинхронный сервер, который использует один главный процесс для приема соединений и несколько рабочих процессов для их обработки. Рабочие процессы выполняются от непривилегированного пользователя. Асинхронная диспетчеризация может осуществляться как старыми вызовами select() и poll(), так и с использованием современных подходов специфичных для различных операционных систем: kqueue (для FreeBSD, начиная с версии 4.1), epoll (для Linux, начиная с версии 2.6), rt signals (для Linux, начиная с версии 2.2.19), /dev/poll (для Solaris, начиная с версии 7) и event ports (для Solaris, начиная с версии 10). Также для оптимизации производительности используются исключающие лишнее копирование данных системные вызовы sendfile(), sendfile64() или sendfilev() и сведены к минимуму операции копирования данных внутри сервера.

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

Сборка и установка

Хотя nginx уже доступен в пакетах для последних версий Ubuntu Linux, я решил собирать его из исходников, потому что хотел использовать более свежую стабильную версию и модуль mod_wsgi для поддержки WSGI-протокола Python. Если вам не нужно собирать nginx с mod_wsgi, вы можете пропустить все места, где он упоминается.

Итак, для сборки нам понадобится исходный код nginx, исходный код библиотеки совместимых с Perl регулярных выражений (PCRE) и исходный код модуля mod_wsgi. Здесь мы используем самые последние, на данный момент, версии mod_wsgi и библиотеки PCRE. При использовании более старых версий PCRE версия не должна быть ниже 4.4:

$ wget http://sysoev.ru/nginx/nginx-0.6.32.tar.gz

$ tar -xzf nginx-0.6.32.tar.gz

$ wget ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/pcre-7.8.tar.bz2

$ tar -xjf pcre-7.8.tar.bz2

$ mv pcre-7.8 pcre

$ wget -O mod_wsgi.tar.gz http://hg.mperillo.ath.cx/nginx/mod_wsgi/archive/tip.tar.gz

$ tar -xzf mod_wsgi.tar.gz

$ mv mod_wsgi-8994b058d2db mod_wsgi

Здесь я также переименовал директории для PCRE и mod_wsgi, чтобы в дальнейшем использовать для конфигурации один скрипт, не изменяя его. Автор mod_wsgi выбрал подход с применением патчей, чтобы успевать за изменениями в nginx, и поэтому мы должны приложить патч для нашей версии nginx. Запишем его как mod_wsgi_nginx-0.6.32.patch:

--- src/ngx_http_wsgi_handler.c 2008-03-26 22:35:15.000000000 +0300

+++ src/ngx_http_wsgi_handler.c 2008-10-06 16:55:07.000000000 +0400

@@ -71,7 +71,7 @@

if (r->method == NGX_HTTP_GET || r->method == NGX_HTTP_HEAD) {

/* XXX not sure */

- rc = ngx_http_discard_body(r);

+ rc = ngx_http_discard_request_body(r);

if (rc != NGX_OK && rc != NGX_AGAIN) {

return rc;

И затем приложим:

$ patch -d mod_wsgi -p0 < mod_wsgi_nginx_0.6.32.patch

Для сборки Nginx с SSL также необходимо установить библиотеку OpenSSL и для использования модуля ngx_http_gzip_module библиотеку zlib. Для сборки mod_wsgi понадобится установить пакет python-dev:

$ sudo apt-get install libssl-dev

$ sudo apt-get install zlib1g-dev

$ sudo apt-get install python-dev

$ touch nginx.sh

$ chmod a+x nginx.sh

$ vi nginx.sh

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

#! /bin/sh

./configure \

--prefix=/var/lib/nginx \

--sbin-path=/usr/sbin/nginx \

--conf-path=/etc/nginx/nginx.conf \

--pid-path=/var/run/nginx.pid \

--error-log-path=/var/log/nginx/error.log \

--http-log-path=/var/log/nginx/access.log \

--lock-path=/var/lock/nginx \

--http-client-body-temp-path=/var/lib/nginx/client_body \

--http-proxy-temp-path=/var/lib/nginx/proxy \

--http-fastcgi-temp-path=/var/lib/nginx/fastcgi \

--user=www-data \

--group=www-data \

--without-select_module \

--without-poll_module \

--without-http_ssi_module \

--without-http_geo_module \

--without-http_referer_module \

--without-http_memcached_module \

--without-http_limit_zone_module \

--without-http_empty_gif_module \

--without-http_browser_module \

--without-http_upstream_ip_hash_module \

--with-http_ssl_module \

--with-http_gzip_static_module \

--with-pcre=../pcre \

--add-module=../mod_wsgi

По умолчанию nginx устанавливается в директорию /usr/local/nginx и использует поддиректории для файлов конфигурации и различных временных файлов, но я привык придерживаться стандарта иерархии файловой системы (http://www.pathname.com/fhs), и поэтому в начале скрипта идут опции переназначения различных директорий. Затем идут опции установки пользователя и группы, под которыми будут работать рабочие процессы. В случае если данные пользователь и группа не созданы в вашей системе, их надо будет создать вручную. После этого находятся опции, включающие и отключающие различные модули, в том числе отключение поддержки системных вызовов select() и poll(), т.к. в моем случае, на Linux 2.6, будет использоваться вызов epoll(). Если вы не знаете какой системный вызов может использоваться в вашей системе, оставьте это решение скрипту конфигурации, который выберет наиболее оптимальный вариант. Соответственно если вам нужны другие пути к файлам и директориям, другой пользователь и группа, или другие модули, вы можете внести изменения в эти секции. После того как все готово со скриптом конфигурации, можно начать конфигурацию:

$ cd nginx-0.6.32

$ ../nginx.sh

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

 

Configuration summary

+ using PCRE library: ../pcre

+ using system OpenSSL library

+ md5 library is not used

+ sha1 library is not used

+ using system zlib library

 

nginx path prefix: "/var/lib/nginx"

nginx binary file: "/usr/sbin/nginx"

nginx configuration prefix: "/etc/nginx"

nginx configuration file: "/etc/nginx/nginx.conf"

nginx pid file: "/var/run/nginx.pid"

nginx error log file: "/var/log/nginx/error.log"

nginx http access log file: "/var/log/nginx/access.log"

nginx http client request body temporary files: "/var/lib/nginx/client_body"

nginx http proxy temporary files: "/var/lib/nginx/proxy"

nginx http fastcgi temporary files: "/var/lib/nginx/fastcgi"

 

Теперь можно начать компиляцию:

$ make

Если компиляция прошла успешно, устанавливаем nginx:

$ sudo make install

При установке для конфигурации выше будет создана директория /var/lib/nginx, бинарный файл сервера nginx будет установлен в директорию /usr/sbin (в случае присутствия старого файла он переименовывается в nginx.old), будет создана директория /etc/nginx, в которую будет перенесена конфигурация по умолчанию, и будут созданы директории /var/log/nginx и /var/lib/nginx с нужными правами доступа.

Запуск и управление

В простейшем случае мы можем запустить nginx следующим образом:

$ sudo /usr/sbin/nginx

После первого запуска можно зайти по адресу http://localhost/ и увидеть страницу приветствия. Для остановки сервера можно выполнить:

$ sudo killall nginx

Конечно, такой способ управления лучше всего использовать только для первого тестирования, а для обычного использования и в последующем автоматического запуска лучше написать скрипт управления и положить его в директорий /etc/init.d под именем nginx, не забывая дать права на исполнение:

#! /bin/sh

#

# /etc/init.d/nginx: start and stop nginx http server

#

 

 

PID_FILE=/var/run/nginx.pid

CAT=/bin/cat

NGINX=/usr/sbin/nginx

START_STOP_DAEMON=/sbin/start-stop-daemon

 

. /lib/lsb/init-functions

 

 

do_start()

{

$START_STOP_DAEMON --start --quiet --pidfile $PID_FILE --exec $NGINX

RETVAL=$?

 

if [ $RETVAL = 0 ]; then

log_success_msg "Server started at pid" $($CAT $PID_FILE)

elif [ $RETVAL = 1 ]; then

log_failure_msg "Server already running at pid" $($CAT $PID_FILE)

else

log_failure_msg "Error starting server"

fi

 

return $RETVAL

}

 

do_stop()

{

$START_STOP_DAEMON --stop --quiet --retry=TERM/30/KILL/5 --pidfile $PID_FILE --exec $NGINX

RETVAL=$?

 

if [ $RETVAL = 0 ]; then

log_success_msg "Server stopped"

elif [ $RETVAL = 1 ]; then

log_failure_msg "Server already stopped"

else

log_failure_msg "Error stopping server"

fi

 

return $RETVAL

}

 

 

is_running()

{

if [ -f $PID_FILE ]; then

kill -n 0 $($CAT $PID_FILE)

if [ $? = 0 ]; then

return 1

else

return 0

fi

fi

return 0

}

 

 

case "$1" in

start)

log_begin_msg

do_start

log_end_msg $?

;;

 

stop)

log_begin_msg

do_stop

log_end_msg $?

;;

 

status)

log_begin_msg

is_running

if [ $? = 0 ]; then

log_success_msg "Server not running"

log_end_msg 1

else

log_success_msg "Server running at pid" $($CAT $PID_FILE)

log_end_msg 0

fi

;;

 

 

restart)

log_begin_msg

do_stop

if [ $? = 0 ] || [ $? = 1 ]; then

do_start

fi

log_end_msg $?

;;

 

 

reload)

log_begin_msg

is_running

if [ $? = 0 ]; then

log_failure_msg "Server not running"

log_end_msg 1

else

$NGINX -t

if [ $? = 0 ]; then

kill -HUP $($CAT $PID_FILE)

if [ $? = 0 ]; then

log_success_msg "Server configuration reloaded"

log_end_msg 0

else

log_failure_msg "Error while reloading configuration"

log_end_msg 1

fi

else

log_failure_msg "Configuration errors found"

log_end_msg 1

fi

fi

;;

 

*)

log_success_msg "Usage: /etc/init.d/nginx {start|stop|status|restart|reload}"

exit 3

;;

esac

 

exit $?

Дадим скрипту нужные права:

$ sudo chmod a+x /etc/init.d/nginx

И теперь можно управлять nginx через наш скрипт, используя команды start, stop, status, restart и reload. Чтобы nginx запускался при старте системы можно воспользоваться следующей командой:

$ sudo update-rc.d nginx defaults

Эта команда создаст ссылки на скрипт /etc/init.d/nginx в каталогах, соответствующих различным уровням запуска: /etc/rc0.d – /etc/rc6.d.

Настраиваем статический сайт

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

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

user www-data www-data;

 

worker_processes 4;

 

error_log /var/log/nginx/error.log info;

pid /var/run/nginx.pid;

 

events {

worker_connections 1024;

}

 

http {

include /etc/nginx/mime.types;

default_type application/octet-stream;

charset utf-8;

server_tokens off;

sendfile on;

gzip on;

gzip_http_version 1.0;

gzip_comp_level 6;

gzip_proxied any;

gzip_disable "MSIE [1-6]\.(?!.*SV1)";

gzip_buffers 16 8k;

gzip_types text/plain text/html text/css

application/x-javascript text/xml application/xml

application/javascript text/js

application/xml+rss text/javascript application/atom+xml;

ssl_session_cache shared:SSL:10m;

ssl_session_timeout 10m;

 

include /etc/nginx/example.ru.conf

}

 Рассмотрим опции по порядку:

  • Опция user описывает, от имени какого пользователя и группы будут выполняться рабочие процессы.
  • Опция worker_processes определяет количество рабочих процессов. Количество рабочих процессов – параметр, который влияет на производительность и в основном зависит от ожидаемой нагрузки на сервер и требуемой функциональности сайтов. В простейшем случае может быть только один рабочий процесс, но если используется компрессия данных, или SSL, то их количество может быть равно количеству процессоров или в два раза большему числу. В данном случае я выбрал 4 рабочих процесса, т.к. пример со статическим сайтом использует и компрессию, и SSL и запускается на двухпроцессорной машине. В случае если используются не совсем свойственные nginx синхронные модули, как например mod_wsgi, нужно выбрать количество рабочих процессов в зависимости от ожидаемого количества одновременных запросов и скорости их обработки.
  • Опции error_log и pid описывают соответственно путь к файлу журнала ошибок вместе с уровнем логгинга и путь к файлу, в котором будет храниться идентификатор главного процесса сервера.
  • Секция events описывает опции, связанные с обработкой событий. Опция worker_connections описывает ограничение на количество одновременно обрабатываемых рабочими процессами соединений. Таким образом, в случае статического сайта максимальное количество одновременных соединений с сервером можно рассчитать по формуле: worker_processes * worker_connections. Также в этой секции можно выбрать метод обработки событий, например use epoll, и другие настройки, связанные с обработкой событий.
  • Секция http описывает конфигурацию HTTP-сервера и всех сайтов. Опции include и default_type описывают каталог MIME-типов и тип по умолчанию соответственно. Опция charset определяет кодировку, которая будет добавлена в заголовок ответа Content-Type. Если ее не указывать, браузеры будут использовать собственные кодировки по умолчанию как кодировку контента. Опция server_tokens управляет выводом номера версии сервера в ответах. Опция sendfile включает использование системного вызова, оптимизирующего посылку файлов. Набор опций, начинающихся на gzip, описывает параметры сжатия ответов. Набор опций, начинающихся на SSL, описывает настройки SSL-сессий. Опция include подключает другой файл конфигурации, в данном случае непосредственно конфигурацию сайта.

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

server {

listen 80;

server_name example.ru *.example.ru;

error_log /var/log/nginx/example.ru/error.log info;

access_log /var/log/nginx/example.ru/access.log;

location / {

root /home/www/example.ru/data/;

index index.html;

if ($host != "example.ru") {

rewrite ^(.*) http://example.ru$1 permanent;

}

}

}

server {

listen 443;

server_name example.ru;

error_log /var/log/nginx/example.ru/error.log info;

access_log /var/log/nginx/example.ru/access.log;

ssl on;

ssl_certificate /etc/nginx/cert/example.ru.pem;

ssl_certificate_key /etc/nginx/cert/example.ru.pem;

auth_basic "Example admin place";

auth_basic_user_file /home/www/example.ru/.htpasswd;

location / {

root /home/www/example.ru/data/admin/;

index index.html;

}

}

В данном случае файл /etc/nginx/example.ru.conf описывает две версии одного сайтаобычную HTTP-версию и HTTPS-версию, защищенную паролем. Секции server описывают конфигурацию виртуальных серверов.

Рассмотрим опции подробнее:

  • Опция listen определяет адрес и порт, на котором сервер будет принимать запросы. Здесь также можно задать дополнительные опции, управляющие приемом соединений. В том числе с помощью этой опции можно объединить конфигурацию HTTP- и HTTPS-серверов в одной секции, хотя в примере этого не сделано.
  • Опция server_name задает имя и псевдонимы сайта.
  • Опции error_log и access_log определяют путь к файлу журнала ошибок с уровнем логгирования и журналу запросов соответственно.
  • Секция location объединяет конфигурационные параметры в зависимости от URI запроса.
  • Опции root и index описывают корневую директорию сайта и имя индексного файла по умолчанию.
  • Опции if и rewrite используются для изменения URI запроса. В данном примере все запросы для других доменов перенаправляются на example.ru.
  • Опции, начинающиеся с ssl_, описывают путь к SSL-сертификату и приватному ключу соответственно.
  • Опции, начинающиеся с auth_basic, описывают текст комментария при вводе пароля и путь к файлу со списком паролей соответственно, в случае использования простой HTTP-авторизации. Файл со списком паролей может быть создан утилитой htpasswd из пакета сервера Apache. На данный момент nginx не поддерживает других методов авторизации кроме простой HTTP-авторизации.

Настраиваем HTTP-прокси

Часто HTTP-сервер является лишь посредником (прокси), стоящим перед другим HTTP-сервером. Например, такая конфигурация нужна, если один из сайтов сделан с применением технологии, которая уже имеет свой HTTP-сервер, или посредник используется как балансировщик нагрузки для нескольких стоящих за ним серверов. В nginx эта функциональность поддерживается модулем ngx_http_proxy_module.

Также с помощью модуля ngx_http_memcached_module nginx можно использовать совместно с Memcached (http://www.danga.com/memcached) для кэширования контента. Рассмотрим пример простого сайта, который перенаправляет запросы на сервер, сделанный с использованием технологии Zope 3 (http://www.zope.org). Сначала добавим следующие опции в секцию http файла /etc/nginx/nginx.conf:

proxy_set_header Host $host;

proxy_set_header X-Real-IP $remote_addr;

proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

include /etc/nginx/zope3.example.ru.conf

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

server {

listen 80;

server_name zope3.example.ru;

error_log /var/log/nginx/zope3.example.ru/error.log info;

access_log /var/log/nginx/zope3.example.zope3.ru/access.log;

error_page 502 503 504 /maintenance.html;

location /maintenance.html {

alias /home/www/zope3.example.ru/data/index.html;

}

location / {

proxy_pass http://127.0.0.1:8080/++skin++example/sites/example/++vh++http:zope3.example.ru:80/++/;

}

}

 Рассмотрим не описанные выше опции:

  • Опция error_page задает URI, который будет показываться для заданных кодов ошибок. В данном случае это ошибки, связанные с недоступностью вспомогательного сервера, или невозможностью обработать запрос.
  • Опция alias задает замену для указанного пути. Таким образом для страницы сайта /maintenance.html будет возвращено содержимое файла /home/www/zope3.example.ru/data/index.html, который может содержать страницу с описанием того, почему сервер в данный момент не доступен.
  • Опция proxy_pass задает адрес и путь на вспомогательном сервере, на который будет отображаться путь на сайте. Таким образом, в случае доступа к http://example.zope3.ru/page.html пользователю будет возвращен результат обработки запроса вспомогательным сервером по адресу http://127.0.0.1:8080/++skin++example/sites/example/++vh++http:zope3.example.ru:80/++/page.html.

Настраиваем PHP

На данный момент наиболее оптимальным способом связать nginx и PHP является протокол FastCGI. При этом PHP должен работать в отдельном процессе, что не является особой проблемой, так как PHP уже имеет собственный FastCGI-демон. Для управления демоном PHP можно использовать следующий скрипт, который в свою очередь можно сохранить как /etc/init.d/php-fastcgi и дать ему права на исполнение:

#! /bin/sh

 

EXEC_AS_USER=www-data

 

FCGI_HOST=127.0.0.1

FCGI_PORT=9000

 

PHP_FCGI_CHILDREN=5

PHP_FCGI_MAX_REQUESTS=1000

 

DAEMON=/usr/bin/php-cgi

PIDFILE=/var/run/php-fastcgi.pid

PHP_CONFIG_FILE=/etc/php5/cgi/php.ini

START_STOP_DAEMON=/sbin/start-stop-daemon

 

export PHP_FCGI_CHILDREN PHP_FCGI_MAX_REQUESTS

DAEMON_ARGS="-q -b $FCGI_HOST:$FCGI_PORT -c $PHP_CONFIG_FILE"

 

. /lib/lsb/init-functions

 

do_start()

{

$START_STOP_DAEMON --start --quiet --pidfile $PIDFILE --exec $DAEMON --test || return 1

$START_STOP_DAEMON --start --quiet --pidfile $PIDFILE --exec $DAEMON --background --make-pidfile \

--chuid $EXEC_AS_USER --startas $DAEMON -- $DAEMON_ARGS || return 2

}

 

do_stop()

{

$START_STOP_DAEMON --stop --quiet --retry=TERM/30/KILL/5 --pidfile $PIDFILE # --name $DAEMON

RETVAL="$?"

[ "$RETVAL" = 2 ] && return 2

$START_STOP_DAEMON --stop --quiet --oknodo --retry=0/30/KILL/5 --exec $DAEMON

[ "$?" = 2 ] && return 2

rm -f $PIDFILE

return "$RETVAL"

}

 

case "$1" in

start)

log_begin_msg

do_start

log_end_msg $?

;;

stop)

log_begin_msg

do_stop

log_end_msg $?

;;

restart)

log_begin_msg

do_stop

if [ $? = 0 ] || [ $? = 1 ]; then

do_start

fi

log_end_msg $?

;;

*)

echo "Usage: php-fastcgi {start|stop|restart}"

exit 3

;;

esac

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

server {

listen 80;

server_name php.example.ru;

 

error_log /var/log/nginx/php.example.ru/error.log info;

access_log /var/log/nginx/php.example.ru/access.log;

 

location / {

root /home/www/php.example.ru/data/;

index index.html;

}

 

location ~ \.php$ {

fastcgi_pass 127.0.0.1:9000;

fastcgi_index index.php;

include /etc/nginx/fastcgi_params;

fastcgi_param SCRIPT_FILENAME /home/www/php.example.ru/data$fastcgi_script_name;

}

}

 Кроме уже известных опций, здесь есть секция, которая определяет действия для всех путей, оканчивающихся на .php:

  • Опция fastcgi_pass определяет адрес FastCGI-сервера. В нашем случае это адрес, где запущен демон PHP.
  • Опция fastcgi_index задает имя индексного файла для FastCGI.
  • Опцией include мы подключаем файл с параметрами, которые будут передаваться в FastCGI-запросах. К сожалению, мы не можем один раз подключить эти параметры на более верхнем уровне, т.к. следующая опция fastcgi_param, которая в свою очередь задает еще один дополнительный параметр, отменяет все определения параметров более высокого уровня.

Настраиваем Python с WSGI

WSGI является протоколом, который связывает HTTP-сервер и приложение на Python. На данный момент уже есть большое количество серверов и приложений, работающих по этому протоколу, что позволяет использовать их как взаимозаменяемые компоненты. В примере я подключу к nginx известный трекер ошибок Trac (http://trac.edgewall.org). Прежде всего нам нужно создать файл с описанием параметров, передаваемых по WSGI. Файл можно записать как /etc/nginx/wsgi_params по аналогии с fastcgi_params:

wsgi_var REQUEST_METHOD $request_method;

wsgi_var QUERY_STRING $query_string;

 

wsgi_var CONTENT_TYPE $content_type;

wsgi_var CONTENT_LENGTH $content_length;

 

wsgi_var SERVER_NAME $server_name;

wsgi_var SERVER_PORT $server_port;

 

wsgi_var SERVER_PROTOCOL $server_protocol;

 

wsgi_var REQUEST_URI $request_uri;

wsgi_var DOCUMENT_URI $document_uri;

wsgi_var DOCUMENT_ROOT $document_root;

 

wsgi_var SERVER_SOFTWARE $nginx_version;

 

wsgi_var REMOTE_ADDR $remote_addr;

wsgi_var REMOTE_PORT $remote_port;

wsgi_var SERVER_ADDR $server_addr;

 

wsgi_var REMOTE_USER $remote_user;

После этого необходимо добавить в /etc/nginx/nginx.conf в секцию http опции:

wsgi_temp_path /var/lib/nginx/wsgi;

include /etc/nginx/wsgi_params;

Теперь сделаем WSGI-скрипт для подключения Trac и положим его как /home/www/wsgi.example.ru/wsgi.py, не забывая сделать исполняемым:

#! /usr/bin/env python2.4

 

import os

 

os.environ['TRAC_ENV'] = "/home/www/wsgi.example.ru/trac"

os.environ['PYTHON_EGG_CACHE'] = "/var/tmp"

 

import trac.web.main

application = trac.web.main.dispatch_request

И последний момент – конфигурация сайта:

server {

listen 80;

server_name wsgi.example.ru;

 

error_log /var/log/nginx/wsgi.example.ru/error.log info;

access_log /var/log/nginx/wsgi.example.ru/access.log;

 

location / {

wsgi_pass /home/www/wsgi.example.ru/wsgi.py;

}

}

Здесь опция wsgi_pass определяет имя скрипта, который будет выполняться в рамках рабочего процесса. Соответственно, так как скрипты выполняются синхронно в рамках рабочих процессов, для оптимизации производительности сайта с WSGI, возможно, придется увеличить значение опции worker_processes в nginx.conf.

Заключение

Я постарался охватить широкий спектр вопросов, связанных с nginx. Конечно, многие детали пока остались за кадром, но о них можно прочитать на следующих сайтах: http://sysoev.ru/nginx и http://wiki.codemongers.com/Main. Надеюсь, статья помогла вам расширить кругозор и выбрать правильный HTTP-сервер, подходящий для ваших задач.

Приложение

Протокол WSGI

До определенного момента для связи веб-приложения, написанного на Python и HTTP-сервера, использовалось множество подходов. Например, это могли быть протоколы CGI и FastCGI или модуль mod_python для Apache. Также многие приложения, например Zope, использовали жестко интегрированные HTTP-серверы. Стандартный протокол WSGI (http://www.python.org/dev/peps/pep-0333) был впервые предложен в декабре 2003 года и на данный момент поддерживается подавляющим большинством серверов и веб-приложений, написанных на Python. Протокол подробно описывает порядок передачи параметров приложению, передачи ответа серверу и обработку ошибок. Кроме того, учитываются расширения, специфичные для различных серверов. Простейшее приложение с использованием WSGI может выглядеть так:

def application(environ, start_response):

status = '200 OK'

response_headers = [('Content-type','text/plain')]

start_response(status, response_headers)

return ['Hello world!\n']

Таким образом, протокол позволяет, например, начать отлаживать веб-приложение, используя стандартный пакет wsgiref (появился в Python 2.5), и затем перейти на mod_wsgi (с nginx, или Apache) или HTTP-сервер из асинхронного каркаса Twisted.


Комментарии отсутствуют

Добавить комментарий

Комментарии могут оставлять только зарегистрированные пользователи

               Copyright © Системный администратор

Яндекс.Метрика
Tel.: (499) 277-12-41
Fax: (499) 277-12-45
E-mail: sa@samag.ru