Як працює http-сервер nginx

Як працює HTTP-сервер nginx

Вже довгий час Apache є найбільш популярним HTTP-сервером з відкритим вихідним кодом. Але він може бути занадто громіздким для деяких pадач. І тут на сцену виходять нові гравці - легковагі, асинхронні HTTP-сервери, одним з яких є nginx.

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

Перш ніж звернутися до розгляду безпосередньо сервера nginx, розглянемо, чим відрізняється асинхронний (подієвий) підхід від паралельної обробки з'єднань в окремих процесах, або потоках.

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

n Це проста модель для програмування сервера і модулів.

n Кожне з'єднання обробляється незалежно, і таким чином можлива довга обробка даних, виконувана в одному процесі (потоці), не впливає на інші.

n Такий підхід погано масштабується. Наприклад 1000 одночасно відкритих з'єднань може бути цілком нормальним числом, але 1000 одночасно працюючих процесів, або потоків, можуть бути проблемою.

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

n Для багатьох застосувань тільки один процес з одним потоком може обробляти більше з'єднань, ніж в разі паралельної обробки.

n Так як один процес з одним потоком може обробляти відразу декілька з'єднань для обробки більшої кількості з'єднань, використовується менше ресурсів.

n Програмування асинхронних додатків може бути складніше, ніж додатків з паралельною обробкою.

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

n У найпростішому випадку асинхронний підхід не може використовуватися, якщо необхідна довга обробка даних.

Як можна помітити, обидва підходи мають свої переваги і недоліки. Щоб об'єднати гідності і зменшити недоліки з обох підходів, в даний час для асинхронних мережних додатків найбільш популярний гібридний підхід, при якому кілька асинхронних додатків працюють паралельно в окремих процесах, або потоках. Тепер розглянемо, як це працює в nginx.

Збірка і установка

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

Отже, для збірки нам знадобиться вихідний код nginx, вихідний код бібліотеки сумісних з Perl регулярних виразів (PCRE) і вихідний код модуля mod_wsgi. Тут ми використовуємо самі останні, на даний момент, версії mod_wsgi і бібліотеки PCRE. При використанні більш старих версій PCRE версія не повинна бути нижче 4.4:

$ Tar -xzf nginx-0.6.32.tar.gz

$ Tar -xjf pcre-7.8.tar.bz2

$ Tar -xzf mod_wsgi.tar.gz

$ Mv mod_wsgi-8994b058d2db mod_wsgi

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

if (rc! = NGX_OK rc! = NGX_AGAIN)

І потім докладемо:

$ Patch -d mod_wsgi -p0

Для складання 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

$ Chmod a + x nginx.sh

Розглянемо опції по порядку:

n Опція user описує, від імені якого користувача і групи будуть виконуватися робочі процеси.

n Опція worker_processes визначає кількість робочих процесів. Кількість робочих процесів - параметр, який впливає на продуктивність і в основному залежить від очікуваної навантаження на сервер і необхідної функціональності сайтів. У найпростішому випадку може бути тільки один робочий процес, але якщо використовується компресія даних, або SSL, то їх кількість може дорівнювати кількості процесорів або в два рази більшій кількості. В даному випадку я вибрав 4 робочих процесу, тому що приклад зі статичним сайтом використовує і компресію, і SSL і запускається на двухпроцессорной машині. У разі якщо використовуються не зовсім властиві nginx синхронні модулі, як наприклад mod_wsgi, потрібно вибрати кількість робочих процесів в залежності від очікуваної кількості одночасних запитів і швидкості їх обробки.

n Опції error_log і pid описують відповідно шлях до файлу журналу помилок разом з рівнем логгінг і шлях до файлу, в якому буде зберігатися ідентифікатор головного процесу сервера.

n Секція events описує опції, пов'язані з обробкою подій. Опція worker_connections описує обмеження на кількість одночасно оброблюваних робочими процесами з'єднань. Таким чином, в разі статичного сайту максимальну кількість одночасних з'єднань з сервером можна розрахувати за формулою: worker_processes * worker_connections. Також в цій секції можна вибрати метод обробки подій, наприклад use epoll, і інші параметри, пов'язані з обробкою подій.

n Секція http описує конфігурацію HTTP-сервера і всіх сайтів. Опції include і default_type описують каталог MIME-типів і тип за замовчуванням відповідно. Опція charset визначає кодування, яка буде додана в заголовок відповіді Content-Type. Якщо її не вказувати, браузери будуть використовувати власні кодування за замовчуванням як кодування контенту. Опція server_tokens управляє висновком номера версії сервера у відповідях. Опція sendfile включає використання системного виклику, оптимизирующего посилку файлів. Набір опцій, що починаються на gzip, описує параметри стиснення відповідей. Набір опцій, що починаються на SSL, описує налаштування SSL-сесій. Опція include підключає інший файл конфігурації, в даному випадку безпосередньо конфігурацію сайту.

Конфігурація сайту може виглядати наступним чином:

server_name example.ru * .example.ru;

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

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

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

auth_basic "Example admin place";

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

Розглянемо опції докладніше:

n Опція server_name задає ім'я і псевдоніми сайту.

n Опції error_log і access_log визначають шлях до файлу журналу помилок з рівнем логгірованія і журналу запитів відповідно.

n Секція location об'єднує конфігураційні параметри в залежності від URI запиту.

n Опції root і index описують кореневу директорію сайту і ім'я індексного файлу за замовчуванням.

n Опції if і rewrite використовуються для зміни URI запиту. В даному прикладі всі запити для інших доменів перенаправляються на example.ru.

n Опції, що починаються з ssl_, описують шлях до SSL-сертифікату та приватному ключу відповідно.

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

proxy_set_header Host $ host;

proxy_set_header X-Real-IP $ remote_addr;

proxy_set_header X-Forwarded-For $ proxy_add_x_forwarded_for;

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

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

error_page 502 503 504 /maintenance.html;

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

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

n Опція fastcgi_index задає ім'я індексного файлу для FastCGI.

n Опцією include ми підключаємо файл з параметрами, які будуть передаватися в FastCGI-запитах. На жаль, ми не можемо один раз підключити ці параметри на більш верхньому рівні, тому що наступна опція fastcgi_param, яка в свою чергу ставить ще один додатковий параметр, скасовує всі визначення параметрів більш високого рівня.

Налаштовуємо Python з WSGI

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-скрипт для підключення Trac і покладемо його як /home/www/wsgi.example.ru/wsgi.py, не забуваючи зробити виконуваним:

І останній момент - конфігурація сайту:

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

Тут опція wsgi_pass визначає ім'я скрипта, який буде виконуватися в рамках робочого процесу. Відповідно, так як скрипти виконуються синхронно в рамках робочих процесів, для оптимізації продуктивності сайту з WSGI, можливо, доведеться збільшити значення опції worker_processes в nginx.conf.

def application (environ, start_response):

return [ "Hello world!"]

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

Схожі статті