FreeBSD - Nginx - Доклад Игоря Сысоева
Материал из Wiki - Iphoster - the best ever hosting and support. 2005 - 2024
FreeBSD - Nginx - Доклад Игоря Сысоева
NGINX – зачем он вообще нужен, текущие и будущие возможности
Nginx я начал разрабатывать весной 2000 года и делал его около двух лет. Сначала он начал работать в Рамблере. Но первым проектом все-таки был www.zvuki.ru, на котором он отдавал mp3, затем www.foto.rambler.ru. Потом на нем начали делать Mamba (www.mamba.ru ) и эстонский сайт www.raid.ee (вроде Mamba). Но тогда он еще не был доступен — это была стадия альфа-тестирования. Сейчас nginx находится в стадии бэта-тестирования, но, в принципе, он стабилен.
В 2004 году вышел первый публично доступный релиз. Уже прошло 2,5 года. В марте прошлого года nginx проксировал и обслуживал 9,8% виртуальных российских серверов. В марте этого года на долю nginx приходилось уже, по-моему, 22,3% или 22,7%. Нельзя говорить, что пятая часть Рунета работает на nginx. Надо понимать, что это виртуальные серверы, не инсталляции nginx. На одном теле может быть тысяча серверов. Кроме того, все эти числа означают, что nginx используется как фронтенд. Сервер, который стоял до этого, в большинстве случаев никуда не делся. Как правило, это Apache. Иногда люди реализуют всю схему без сервера, то есть они запускают, поставив CGI, PHP, Perl. Кто, что умеет, то и запускает.
Что умеет делать nginx? При проектировании основное, что в него закладывалось, это передача статических файлов, картинок, объемных файлов по большому числу соединений, удержание постоянного (keep-alive) соединения с клиентом и проксирование запросов на другие сервера, то есть выполнение роли акселератора. Потом реальность внесла свои коррективы, появилась поддержка FastCGI, memcached.
Архитектурно nginx выглядит следующим образом. Есть основной процесс — мастер-процесс. Его, как правило, запускают под рутом, поскольку некоторые операции, которые он должен выполнить, возможны только именно от этого пользователя. Мастер-процесс запускает рабочие процессы — воркеры, которые занимаются облуживанием соединения. Каждый воркер работает с тысячами, возможно, с десятками тысяч соединений. Ему это не накладно. Воркеров может быть несколько, это позволяет работать на многопроцессорных машинах. Чем больше воркеров, тем больше операций можно производить.
Здесь показано одно из применений nginx. Он обрабатывает статические запросы с диска, передает что-то другим серверам, серверу FastCGI и может забирать запросы из memcached. Если в memcached ответа нет, можно перенаправить на эти сервера, которые его туда положат для следующего раза.
Почему nginx появился? Дело в том, что Apache, по крайней мере, тех времен, был не масштабируемым решением. Сейчас он тоже не особо масштабируемый, но стал лучше. Имеется в виду Apache2, хотя и у него есть проблемы. У Apache, который работает в режиме prefork, есть проблема: один процесс — это одно соединение. А на одно соединение расходуется как минимум 200-300 килобайт памяти. В результате, тысяча таких соединений займет на машине 2-3 гигабайта. В общем, он забирает много памяти, причем, это Apache, который отдает статику и ничем умным не занимается. В Apache mod_perl или PHP размеры процесса резко возрастают: я написал от 1 до 100 мегабайт, хотя нет предела совершенству. Все это физическая память. То есть, на гигабайтной машине Вы запустите, условно, десять стомегабайтных процессов и вся память будет выбрана. Самое неприятное заключается в том, что клиент медленный, и все эти 100 мегабайт физической памяти привязаны к нему, хотя они могли бы уже понадобиться для обслуживания других соединений.
Что позволяет делать nginx? Один процесс обрабатывает тысячи соединений. На неактивное keep-alive соединение тратится 250 байт. То есть, если у Вас на машине 10000 неактивных keep-alive соединений, то будет расходоваться только 2,5-3 мегабайт памяти. Обычное соединение, по сравнению с Apache, тоже более умеренно: обычно уходит памяти от 32 до 100 килобайт, в зависимости от того, как сконфигурированы буферы.
Многие замечали, что после установки на сервере резко падает нагрузка на процессор, появляется память — все дело в «волшебных пузырьках». «Волшебные пузырьки» это: kqueue, механизм которого доступен на FreeBSD, NetBSD, OpenBSD, MacOSX; механизм epoll и риэлтайм сигналы (rtsig) — на Linux; /dev/poll и eventport — на Solaris (eventport – это десятая последняя версия Solarisа).
Кроме того, nginx умеет использовать select, poll (но это не «волшебные пузырьки»). Последний «волшебный пузырек» — это sendfile. Он есть на FreeBSD, Linux, Solaris. Sendfile позволяет уменьшить использование процессора и памяти.
Хорошая программа получается только тогда, когда человек сам ей пользуется. Поскольку я долгое время работал администратором в Рамблере и в то же время разрабатывал nginx, то хотел сделать программу, которая была бы удобна для администратора. Поэтому данный слайд называется «Мечта администратора».
У nginx достаточно гибкая конфигурация, приблизительно такая, как у Apache, в каких-то местах даже лучше, а в каких-то и хуже. Изменение настроек и обновление исполняемого файла можно делать, не прерывая обслуживание клиента. Практически все nginx в Рамблере апгрейдятся именно без прерывания обслуживания клиента.
Быстрая ротация логов. Apache ротирует логи по сигналу переконфигурации: старые процессы продолжают писать старые логи, поэтому сжимать их рекомендуется примерно через полчаса после того, как все клиенты закончат свою работу. Nginx файлы ротирует мгновенно, поэтому через секунду их можно сжимать и делать с ними все, что угодно.
Очень сложно понять без отладочного лога, что что-то не работает. Когда я разрабатывал nginx, была мысль убрать отладочный лог, но оказалось, что это единственный способ решения проблем удаленно. Когда у людей возникает проблема, можно найти ошибку у них, либо в nginx. Это очень удобная вещь.
Что умеет nginx? Это модульный сервер. Можно добавлять какие-то модули. Они в чем-то похожи на Apache, поскольку у меня к моменту разработки nginx был неплохой Apache-вский background. Я знал, как он устроен. В nginx очень много вещей пришло из Apache (конфигурация, пулы памяти, модули). Пришло что-то, что мне не нравится, в частности rewrite.
Что еще можно делать? Можно изменять, переписывать URLы. Можно принимать решения на основании большого количества переменных. Почти все параметры запроса доступны в виде переменных: с ними можно что-то делать. На самом деле rewrite и переменная — это «куцая» вещь. Я собираюсь ее развивать в более удобную форму.
Geo-targeting позволяет выполнять определенные операции в зависимости от адреса клиента (то есть, Россия, Украина, США и прочее).
Ограничение доступа в зависимости от адреса клиента и по паролю — это обычные access denied и basic-авторизация.
Недавно появилось ограничение числа соединений с одного адреса.
Перенаправление ошибок 404 и т.п.
В SSL есть кэш SSL-сессий, который позволяет снизить нагрузку на процессор; есть проверка клиентских сертификатов и проксирование соединений с другими защищенными серверами, работающими по https.
Есть некоторое подмножество WebDAV, которое применяется для того, чтобы выкладывать на большое количество серверов одно и то же. Главная команда здесь это PUT. Остальные команды (DELETE, MKCOL, COPY, MOVE) тоже можно использовать. Возможно, WebDAV будет развиваться до его полноценной реализации.
Есть еще встроенный perl — это пока еще экспериментальная вещь. Интерфейс в ней, возможно, будет меняться. На perl можно делать несложные не блокирующиеся операции (проверка параметра запроса, перенаправления и т.д.).
Я решил показать более подробно три возможностиnginx. Одна из них называется фильтрами вывода. Это тоже модули. Каждый из этих квадратиков — это модули, которые при сборке можно добавить, либо убрать.
Ranges — это фильтр, который позволяет реализовать то, что в народе называется «докачка».
Header footer добавляет либо до, либо после ответа какой-то другой запрос.
SSI — это Server Side Includes. Следующий слайд будет посвящен в основном ему.
Модуль charset делает перекодировку. Несмотря на то, что в интернете сейчас в ходу две кодировки — UTF8 и Windows-1251, в Рамблере исторически использовалась KOI, поэтому приходилось перекодировать, так и появился этот модуль.
GZIP — это сжатие.
А про chunk’и Вам знать необязательно.
SSI — это моя гордость. Ее необходимость была понятна с самого начала. Фильтр позволяет вставлять запросы с локального диска и удаленных серверов. Например, один из них (показывает на «.. ..#include virtual=”/perl/one.html”-->) и уходит на один сервер, второй (показывает на «.. ..#include virtual=”/perl/two.php”-->) — на FastCGI. При этом ответ от Apache может еще раз пройти через этот фильтр, еще раз сходить к десяти серверам, получить от каждого ответ и снова пропустить через фильтр. Получается очень сложно устроенная рекурсивная вещь. Я иногда сам забываю некоторые моменты того, как она устроена. Она работает нормально (есть только один известный баг, который я скоро исправлю). Почти везде, где в Рамблере есть nginx, используется SSI.
Есть такое понятие, как распределение нагрузки и отказоустойчивость. Мы описываем upstream, проксируем запросы на backend. Есть две машины, которые должны выдавать одинаковое содержимое. Если одна из машин падает, то все запросы переходят на другую. При этом если она упадет в момент передачи запроса, то он не потеряется, а уйдет на вторую. Если упадет во время передачи ответа, то уже ничего не сделаешь. У апстримов (upstream) можно задавать разные веса — эта функциональность будет развиваться.
Еще одно преимущество — возможность X-Accel-Redirect. Как она работает? Представьте, что у Вас есть контент, который нужно защитить паролем, чтобы люди оплатили деньги, или еще что-то. Nginx передает запросы на backend, который принимает решение, разрешать ли этому пользователю доступ к защищенной информации и выдает заголовок X-Accel-Redirect, в котором указан URL к защищенному файлу, и nginx уже отдает этот файл. При этом, если кто-то узнает местоположение, то запросить этот URLнапрямую извне он не сможет, потому что есть слово internal. Internal означает, что эти запросы можно обслуживать только в результате рерайта (rewrite) внутри nginx, в результате внутренних redirectов и тому подобное. Для запросов извне для этого location будет вызываться ошибка 404.
Что вряд ли будет поддерживаться? Это CGI, .htaccess, piped logs. CGI несовместим с высокой производительностью. Если у Вас на сервере используется CGI, то nginx не поможет. Это будет бесполезная трата времени, хотя, может быть, узнаете что-то новое, но на сервере это никак не отразится.
Архитектурный nginx не планировался никогда для .htaccess. И в его текущую архитектуру вставить достаточно проблематично. Не то, чтобы я был особенно против .htaccess’ов, но вставить их сейчас достаточно сложно. К тому же, они тоже замедляют работу.
Piped logs — это логирование не на локальную файловую систему, а в какой-то другой процесс (лог-ротейты). На мой взгляд, это неправильный способ. Единственный способ надежно писать лог — это локальный диск. Потом с ним можно делать все, что угодно: крутить, сжимать и прочее. Nginx позволяет работать с логами буквально через секунду после их включения.
Есть еще одна функциональность — почтовый прокси-сервер. Nginx разрабатывался без особенной привязки к http-протоколу. Можно писать модули для каких-то других протоколов, хотя, возможно, придется править что-то и в основных исходниках. В принципе, я постарался сделать их более-менее независимыми от протокола.
Для чего нужен почтовый прокси-сервер? Если у Вас тысяча аккаунтов, то он Вам не нужен, забудьте. Он нужен, когда почтовые аккаунты необходимо хранить на нескольких серверах, потому что они просто не помещаются на этих машинах, либо не хватает процессора и скорости диска. У POP3 и IMAP есть проблема, которая называется «одна точка входа». Если у Вас миллион пользователей, то всем им Вы говорите, что POP3-почту и IMAP-почту они могут читать с такой-то машины (pop3.rambler.ru, или imap.rambler.ru (хотя его сейчас нет)). Клиенты подсоединяются к этому серверу, и разбалансить это невозможно. Нужно узнать конкретный сервер, на котором хранятся данные этого аккаунта. Это делает nginx. Клиент коннектится к nginx, сообщает имя и пароль. Nginx идет к серверу авторизации, который работает по протоколу http (но он может быть урезанным, только заголовки). Сервер говорит, нравится ему этот пользователь или нет. Если да, то он говорит, на каком конкретно из backend живет данный аккаунт. Nginx переходит к этому backend, логинится туда. После этого просто идет проксирование между клиентом и backend.
Для SMTP такой проблемы нет — единой точки входа. Он масштабируется MX’ами. Но для клиентских SMTP МХ не подходит. Тем не менее, можно балансировать IP-адресами (с помощью DNS) или какими-то аппаратными балансировщиками. У нас в Рамблере возникла проблема: очень много соединений идут от вирусов, спама, которые не хотят аутентифицироваться, а просто запускают лишние процессы. Поэтому, была добавлена поддержка SMTP-авторизации. Точно также клиенты соединяются с nginx. Если клиент соблаговолил выдать какую-то информацию с авторизации, то все это уходит на сервер, который потом это все перенаправляет на какой-то из SMTP-серверов.
Методы аутентификации. В POP3: USER/PASS, APOP, AUTH LOGIN PLAIN CRAM-MD5. В IMAP поддерживается только LOGIN. В SMTP такие методы как AUTH LOGIN PLAIN CRAM-MD5. Поддерживается SSL и в IMAP STARTTLS, в POP3 STLS.
Что мы будем делать? · Кэширование всего, что только можно (perl-кэширование появится через месяц или два примерно). · Ограничение числа соединений с бэкендами. (Backend-alone: Если бэкенд не может обработать больше пяти параллельных запросов, а приходят пятьдесят, мы отправляем только пять. Остальные стоят в очереди. По мере освобождения бэкенда, ему передаются новые запросы. Если будет кэширование, то появится возможность отдавать устаревшие запросы, которые есть в кэше, несмотря на то, что они устарели. Это все будет конфигурироваться, все на усмотрение администратора). · Состояние сервера. (На данный момент статус сервера — то, сколько он обработал запросов и прочее, очень рудиментарное. Будет сделано надлежащим образом состояние сервера). · Развитие встроенного perl'а. · Неблокируемая работа с MySQL (Этот интерфейс будет вставлен в perl, то есть на perl'е можно будет ходить в MySQL, делать какие-то queryи выдавать клиенту). · Предполагается сделать фильтры тела запроса — то есть то, что нам клиент передает, чтобы это можно было парсить этими фильтрами и обрабатывать. Сейчас это бэкенду отдается в необработанном виде: как клиент прислал, так и ушло. · Замена rewrite-модуля на script-модуль. Я уже говорил, что rewrite-модуль мне не нравится. Это было идеологическое наследие Apache. Я хочу переделать, чтобы это было гибким. Все.
Вопрос: Какую нагрузку выдерживает Nginx?. Игорь: Статика у нас 3000 запросов в секунду — это статический сервер, который отдаёт картинки, например. www.rambler.ru — это работа трех машин. Каждая из них по 2500 запросов в секунду днем отдает. Это не предел, это только предел пользователей пока.
Вопрос: А геотаргетинг как работает? Как вы определяете, откуда пришёл запрос? Игорь: Есть база IP-адресов в формате CIDR, то есть можно создавать подсети. Каждому блоку соответствует какой-то номер.
Вопрос: Это текстовый файл? Игорь: Есть такая фирма MaxMind, которая бесплатно раздает такой файл с некоторыми ошибками. Кроме того, у них можно все это купить. Из МаxMind’а можно конвертировать в формат nginx’а. В Рамблере просто строится своя база.
Вопрос: А как происходит процесс? Игорь: Текстовый файл парсится на старте, строится Радикс3, похожий на Патрицию3 — дерево. По этому дереву ищется. В принципе, достаточно эффективно — на каждый запрос максимум около 16 cache-miss’ов .
Вопрос: Если сравнивать с другими быстрыми серверами (например, lighttpd), какие преимущества и недостатки? Игорь: Я не пользуюсь lighttpd (lighty), поэтому ничего о нем сказать не могу. Когда я начал разрабатывать nginx, то lighty и сherokee не было. Были tinyhttpd, mathopd, Boa. Их к тому времени даже научили пользоваться kqueue, send-файлом, но все эти три сервера не умели проксировать. У них была куцая конфигурация. У lighty есть определенные преимущества, которых нет в nginx, а у nginx есть какие-то возможности, которых нет в lighty. Я не могу сказать, насколько он удобен. Я могу процитировать одного американца, который написал примерно следующее. Он потратил на стройку lighty, по-моему, несколько часов, или около того, притом, что для lighty есть достаточно неплохая английская документация. На nginx на тот момент не было английской документации вообще, была только русская, и был пример (example). Вот по этому example он разобрался быстрее, чем настраивал lighty, причем по-русски он не понимает. Мне кажется, что lighty разрабатывался программистом для программиста, а я разрабатывал для администратора. В Apache его конфигурация достаточно прозрачна для администратора. Если люди с бэкграундом Apache приходят на nginx, то им проще его настраивать. Nginx поддерживает несколько рабочих процессов. У lighty есть такая возможность, но она менее стабильна по заверениям автора.