Видео с доклада Игоря Сысоева на конференции DevPoint.ru в ноябре 2010.
Игорь Сысоев масштабируемая конфигурация nginx видео
Игорь Сысоев рассказывал:
(0-5 минута).
В Интернетах вы можете прочитать, что nginx - это очень быстрый веб-сервер, но я так не считаю. Я думаю, что он примерно сравним с lighttpd, apache в плане быстроты.
"Что именно отличает nginx от апачА?", - это масштабируемость. Масштабируемость отзначает, что он может обрабатывать десятки тысяч соединений с минимальными ресурсами, там где апачУ потребуется мегабайты, а то и гигабайты памяти, ну и процессор.
Но, сегодня я бы хотел поговорить не о масштабируемости в плане нагрузки, а о масштабируемости конфигурации. Что это означает? Это означает то, что с ростом функциональности конфигурации, с ростом функциональности сайта, конфигурация остаётся управляемая. В её легко добавлять новые возможности, удалять что то старое. И при этом влияние на уже существующую функциональность будет минимальна или вообще никакой.
Для того, чтобы понять сегодняшний доклад, вы должны знать, что такое location в nginx. Если вы не знаете, то смысла слушать дальше нету.
Итак, location в nginx делятся на 3 группы.
# (1) location /dir/ #1a location = /dir/ #1b location ^~ /dir/ #1c # (2) location ~ \.php$ #2a location ~* \.php$ #2b # (3) location @php
Первые 3 location`а (1) задаются обычными строками.
1a - Nginx ищет максимально возможное совпадение запроса с location, т.е. это префикс. 2-ое 2a - это полное совпадение. 3-е 3a - это аналог первого, только после удачного совпадения запрещён поиск регулярных выражений. Два других location`а (2) - это регулярные выражения с учётом регистра (2a) и без учёта регистра (2b). 3-й вид (3) location`а - это именованные location`ы. Мы сегодня будем говорить только о двух первых категориях.
Locations (1), заданные обычными строками, в nginx реализованы с помощью, своего рода, сбалансированного бинарного дерева. По нему делается достаточно быстрый поиск. Регулярные выражения (2) проверяются в порядке их появления в конфигурационном файле, работают по-медленнее. Насколько медленнее, я не знаю, но сегодня нас интерисует не это (насколько медленне или быстрее работает то или другое), а насколько проще конфигурировать. Статические location (1) вы можете писать в абсолютно любом порядке в файле. Поскольку nginx строит из них дерево, ему всё равно, в каком виде это лежало изначально, он всегда будет находить максимально возможное совпадение и выбирать именно этот location для работы.
Регулярные выражения проверяются в порядке их выполнения. Первое совпавшее регулярное выражение выбирает location, и всё. После этого все остальные не проверяются.
/admin/login.php location / location /admin/ ############################ location /admin/ location /
"Что это означает?", - Это означает, что, если мы, допустим, запишем это, используя только статические строки, то порядок расположения этих location в файле никакой роли не сыграет, будет выбран именно тот запрос. Там будет проверяться пароль и всё остальное прочее, уйдёт это на нужный бэкэнд и т.д.
/admin/login.php location ~* \.php$ location ~* ^/admin/.+\.php$ ############################ location ~* ^/admin/.+\.php$ location ~* \.php$
Если мы возьмём такую конфигурацию, то в первом случае /admin/login.php будет обработан первым регулярным выражением, поскольку оно идёт в первом файле. И результаты будут непредсказуемы.
(5-10 минута).
Моя рекомендация.
Если есть такая возможность, использовать только статические location. Если у вас есть какое то регулярное выражение, вы можете описать несколько location с помощью одного регулярного выражения. Вам кажется, что так будет удобней: вам меньше писать, потом меньше редактировать. Вы ошибаетесь. Чуть позже я расскажу, почему вы ошибаетесь. Если вы, например, одно регулярное выражение замените пятью статическими, со знаком равно или просто префиксами, то жизнь ваша потом намного упроститься.
#configuration1 location ~* \.(gif|jpe?g|png)$ { root /data } location ~* \.php$ { fastcgi_pass ... } ############################ #configuration2 location /i/ { root /data/ } location /scripts/ { fastcgi_pass ... }
Здесь приводится пример конфигурации только на регулярных выражениях и ниже, как это можно было бы сделать локейшенами. К сожалению, если у вас есть существующий сайт, у которого всё навешано, т.е. в одних и тех же каталогах лежать и скрипты, и графики, и ещё что-то. То понятно, что всё это будет работать только с первой #configuration1 конфигурацией. Поэтому очень важно с самого начала рассчитывать не на расширение и что-нибудь ещё, а рассчитывать именно на префиксы. Т.е. если структура вашего сайта будет основана на префиксах, то вам будет проще его конфигурировать. В качестве примера:
"Почему статические строки (1) проще, чем регулярные (2)?", - когда вы только-только создаёте сайт, у вас помещается конфигурация на один экран. И вам кажется, ну чё я буду тут париться: писать кучу location, когда вот у меня тут регулярное выражение, я его вижу, всё прекрасно, я понимаю как оно работает, всё хорошо, мне потом будет легко редактировать. Если, например, смениться бэкэнд, я в одном месте изменю порт, или сменю имя хоста, и всё. Это обычнй аргумент: зачем мне делать эту работу?! Человек - существо ленивое, предпочитает сделать по-меньше, и редко думает о том, что будет потом. А потом будет следующее.
Как правило, сайты начинают расти. И у вас появляются какие то ещё регулярные выражения. При каждом добавлении нового location, новой функциональности, вам нужно просчитывать, а как этот location будет влиять на предудыщий. Если мы поставим его в начало, он может перекрыть уже существующие location`ы. Если мы поставим его в конец, то какие то уже существующие location`ы могут перекрыть его полностью или частично.
Если вы когда-нибудь программировали в .htaccess. Это называется именно как "программировали", то вы, наверное, знаете, что там куча всяких исключений делается. Если то, то то. Если то, то это. А потом вот так проверим. А вот это не трогаем. Рассматривать этот конфиг просто тяжело. Если же вы делаете это всё статическими location`ами, то вы, просто, тупо, добавляете в конец файла, например, статический location. И если он совпадёт с уже существующими, то nginx сообщит. Я хочу сообщить, что всё, что я здесь рассказываю, относится к последней ветке nginx, восьмёрке, которая на днях стала stable. Nginx об этом сообщит и вы увидете. Конфликтов при этом быть не может. Вы просто либо добавляете новую функциональность, либо убираете старую. Дела в том, когда location помещаются на один экран, пусть даже он многострочный, тем не менее вы можете понять, что он делает. Если же у вас конфигурация уже на 50 экранов, то вам придётся при добавлении всё это просматривать, как это повлияет.
(10-15 минута).
В качестве примера я могу привести пример, есть у нас на рамблере 2 сайта. Один www.rambler.ru, второй не буду называть. rambler.ru конфигурирую я. Там сейчас больше сотни location, все статические. Когда нужно что-то добавить, я просто ищу близкий смысловой, помещаю location`ы с близкой функциональностю рядом. Хотя я могу поставить его куда угодно, например, в конец, и никаких проблем не будет. На втором сайте, так исторически сложилось, используются регулярные выражения, rewrit`ы. И что-то добавить новое, изменить - получается кошмар.
Теперь об аргументе, что мне нужно редактироть только в одном месте, а тут мне придётся, допустим, если я напишу backend из 50 статических location, мне придётся редактировать в каждом из 50 мест. Но мы живём не в 70-ых годах, к счастью, есть хорошие редакторы - search / replace. Всё, что вам нужно сделать в этих 50-ти поисках и заменах, просто, визуально оценить, нужно тут менять, или не нужно. Вам не нужно проходить по 50-ти location, как в случае с регулярными выражениями, и обдумывать каждое регулярное выражение, как оно повлияет. Причём нужно заметить, что регулярные выражения, если вы не пишете их по 50 штук в день, воспринимаются очень тяжело, в отличие от статических строк.
Я бы хотел поговорить о способах... Бывают ситуации, когда от регулярных выражений не уйти. Т.е. нам нужно что выделить и поменять. Как быть в этом случае? Нужно локализовывать регулярное выражение внутри статического. Вот, допустим, мы сделали по уму. У нас есть префикс для чего то - буковка /i/. И нам нужно заменить, сделать хэширование файла.
Это, вот, вариант, плохо масштабируемый. Там есть регулярное выражение. И нам придётся его учитывать. Вариант №2. Мы описываем location статической строкой. А внутри его вложенный location уже с регулярным выражением, которое это всё делает. В этом случае мы локализовали область действия этого регулярного выражения. Как правило, оно будет на одном экране. Ещё какие то странные манипуляции. Ну, там, 2-3 location. Всё это обозримо. Всё, что не начинается на буковку i, никогда сюда не попадёт. Соответственно, эти регулярные выражения на всё остальное влиять не будут.
Теперь бы я хотел поговорить о том, как nginx умеет отображать запросы браузера на различные ресурсы. В данном случае это файловая система. В Nginx есть 2 типа отображения:
- семантика root, смысл у неё root;
- семантика alias.
root - это, просто, мы добавляем к запросу какой то префикс. А alias - это мы, просто, делаем замену этого location на тот alias, который описан в директиве. Ну вот, тут всё просто, а здесь мы видим, что dir заменяется на весь этот path/to/data. Т.е. dir вырезается и вместо него ставится эта штука. Прошу обратить внимание, что, если в alias конечный слэш очень важен, т.е. он может быть, может не быть, в зависимости от вашей конфигурации. То в root`е вы его можете писать, можете не писать, nginx его все равно убирает, потому что у каждого запроса есть свой начальник и всё нормально выглядит. Это, что касается root и alias при работе с обычным статическим location.
P.S. По-моему мнению, Игорь молодец! Написал классный легкий веб-сервер. Синтаксис конфигурационных файлов намного приятнее и понятнее, чем .htaccess у apache. Все проекты на моей работе крутятся именно на nginx. При этом nginx абсолютно бесплатный веб-сервер, в отличие от того же IIS. Если в тексте вы заметили ошибки, недочёты - сообщите мне. :)
UPD: 2015г. видео с конференции более не доступно на яндексе. Не смог найти это видео еще где либо. Если у кого то имеется это видео 2010 года с Игорем Сысоевым или ссылка, то очень прошу сообщить мне.