В этой статье погрузимся в основы конфигурации веб‑сервера Angie — директиву location. Она используется во всех конфигурациях при работе с HTTP‑модулем и отвечает за разделение настроек обработки запросов по URL. В том числе, с помощью location происходит разделение запросов на статические и динамические. Начнём с последнего: разберёмся, что такое динамические и статические запросы.
Навигация по циклу
-
Настройка location в Angie. Разделение динамических и статических запросов.
Видеоверсия
Для вашего удобства подготовлена видеоверсия этой статьи, доступна на Rutube, VKVideo и YouTube.
Динамические и статические запросы
Стандартная архитектура веб‑приложения на сегодня включает в себя схему с обратным прокси (может называться «фронт‑сервер») и сервером приложений («бэкенд»). Например, это может быть связка Angie и PHP‑FPM.
В такой схеме фронт‑сервер обслуживает статические запросы — отдаёт файлы с диска, а бэкенд исполняет серверный код (например, PHP) и передаёт результат фронту для ответа клиенту.
Выделение location для статики
Со стороны клиента отличить статические и динамические запросы с гарантированной точностью невозможно, но можно предположить, что к статическим запросам для большинства веб-приложений можно отнести:
-
CSS файлы;
-
JS файлы;
-
файлы подключаемых шрифтов;
-
изображения;
-
аудио- и видеофайлы;
-
статические текстовые файлы (txt, html, xml);
-
прочие файлы для скачивания (архивы, бинарные файлы и т. д.)
Соответственно, для корректной конфигурации веб‑приложения в Angie необходимо выделить для всех этих категорий свои location, в которых будут определены правила обработки таких запросов. Например, если в приложении есть каталог /js, который содержит JS‑ресурсы, то его конфигурация может выглядеть так:
location /js/ { root /var/www/html; }
Это так называемый префиксный location, то есть все запросы (если не будет более приоритетных location), адрес в которых начинается с /js/, будут обрабатываться с такой конфигурацией. Директива root здесь приведена для наглядности, на самом деле мы можем определить root на уровне сервера и оставить блок конфигурации пустым, так как значение директивы будет наследоваться с более высокого уровня.
В некоторых приложениях мы не можем полагаться на четкую структуру директорий и адресов ресурсов. Например, статические файлы могут находиться в любой точке адресной структуры приложения. В таком случае мы можем применить location на основе регулярных выражений (regex). Обычно определение статики работает на основе расширений файлов в URL:
location ~* \.(?:css|js|woff2?|jpe?g|gif|png|txt|pdf)$ { root /var/www/html; }
В этом примере мы сопоставляем адрес ресурса с регулярным выражением без учёта регистра (~*), ищем в окончании адреса ($) знак точки (\.) и одно из расширений. Напоминаю, что GET‑параметры запроса не входят в адрес, то есть запрос /1.css?test=2 также попадёт в этот location.
Основной недостаток такого подхода: нужно заранее предусмотреть все возможные расширения статических файлов.
Выделение location для динамики
Динамические запросы как правило определяются самым низкоприоритетным location /. Например:
location / { proxy_pass http://127.0.0.1:9090/; }
Мы описываем все статические запросы, а всё остальное отправляем на бэкенд. Второй вариант выделения динамических запросов — регулярные выражения на расширение файлов скриптов:
location ~ \.php$ { fastcgi_pass unix:/run/php/php7.4-fpm.sock; fastcgi_index index.php; include fastcgi_params; }
Попасть в такой location можно либо при прямом вызове скрипта (/info.php), либо при обработке запроса к директории (/shop/) с директивой index index.php. Однако в современных веб‑приложениях допустимы произвольные (человекочитаемые) URL, поэтому для них сложно составить правильный набор location, и становится сложно отличить статический запрос от динамического. Здесь на помощь приходит директива try_files, которая позволяет проверить наличие файлов на диске, соответствующих адресу в запросе и в случае их отсутствия отправить обработку в другой location или сразу на скрипт:
location / { try_files $uri $uri/ /index.php?$args; } location / { try_files $uri $uri/ @bitrix; } location @bitrix { fastcgi_pass 127.0.0.1:9001; include fastcgi.conf; }
В этих примерах запрос попадает в location /, там происходит попытка обработать запрос как URI, далее как директорию и дальше происходит внутреннее перенаправление на скрипт (/index.php?$args) или в именованный location (@bitrix).
Есть еще одна разновидность разделения динамических и статических запросов с использованием if. Использование блоков if в целом не рекомендуется из-за их непредсказуемого поведения в сочетании с директивами других модулей (не rewrite), но такая конструкция также возможна:
location / { root /var/www; index index.php; if (!-e $request_filename) { rewrite ^(.+)$ /index.php?q=$1 last; } }
В примере выше происходит проверка наличия файла через if. Если файл есть, то он будет обслужен как статический запрос. Если файла нет, то запрос будет перенаправлен на /index.php?q=$1.
Для создания корректной конфигурации необходимо разобрать приоритеты различных типов location. Перейдём к разбору этого аспекта.
Приоритеты location
Ранее мы уже использовали несколько типов location: префиксные и на основе регулярных выражений. Есть еще несколько вариантов определения location и они имеют различный приоритет. Понимание приоритетов необходимо корректной настройки Angie.
Типы location в Angie.
-
Точный:
location = /test/. -
Префиксный:
location /test/. -
Префиксный без проверки регулярок:
location ^~ /test/. -
Регулярное выражение без учета регистра:
location ~* /test/. -
Регулярное выражение с учетом регистра:
location ~ /test/. -
Именованный location:
location @fallback.
Общий алгоритм поиска location состоит из следующих шагов.
-
Поиск точного location (
=). -
Если не нашли, ищем совпадения в префиксных location. Выигрывает самое длинное совпадение.
-
Если не нашли или найденный location позволяет проверку регулярных выражений (то есть он не
=и не^~), проверяем регулярные выражения по очереди до первого совпадения. -
При совпадении используем найденный, иначе используем неявный location на текущем уровне.
Внутри регулярных выражений выигрывает первое совпадение, то есть важен порядок указания location в конфиге. В порядке приоритетов нет именованных location (@back), потому что в них попасть можно только в результате внутреннего перенаправления.
При выборе типов location нужно отдавать предпочтение префиксным location, так, как они более предсказуемы и проще проверяются процессором выражений. Если всё‑таки необходимо использовать регулярные выражения, то стоит добавить якори (^ — начало строки, $ — конец строки) для более точного поиска совпадений.
Конфигурация типичного веб‑приложения включает в себя множество location с одинаковой конфигурацией, посмотрим, как можно элегантно решить эту задачу.
Копирование конфигурации в location
Допустим, мы выбрали использование префиксных location для статики. Скорее всего в результате получим примерно следующее:
location /images/ { root /var/www; add_header Cache-Control "max-age=31536000, immutable"; } location /css/ { root /var/www; add_header Cache-Control "max-age=31536000, immutable"; } location /js/ { root /var/www; add_header Cache-Control "max-age=31536000, immutable"; } location /files/ { root /var/www; add_header Cache-Control "max-age=31536000, immutable"; }
Как видно, в каждом location есть одинаковые директивы. Если root имеет одинаковые значения в рамках всего server, можно вынести эту директиву на уровень выше. Заголовок кэширования нужен только в статических location, поэтому для удобства вынесем его в отдельный файл и подключим с помощью include. Оптимизируем конфигурацию.
location /images/ { include /etc/angie/static.conf; } location /css/ { include /etc/angie/static.conf; } location /js/ { include /etc/angie/static.conf; } location /files/ { include /etc/angie/static.conf; }
Теперь можно вспомнить, что мы используем Angie, что позволяет нам сделать комбинированный location, сразу определив несколько location в одном блоке. Результат получается более удобочитаемым:
location /files/ /css/ /js/ /images/ { include /etc/angie/static.conf; }
В этой конфигурации для изменения заголовка кэширования достаточно отредактировать файл /etc/angie/static.conf и обновить конфигурацию. При этом файл с заголовком можно использовать и в других блоках server.
Таким образом, мы разобрали несколько способов разделения статических и динамических запросов в Angie, изучили типы location, а также их приоритеты.
ссылка на оригинал статьи https://habr.com/ru/articles/914408/
Добавить комментарий