Предикатная маршрутизация NGINX: как направлять API-трафик без скриптов
В сентябре 2026 года вышел NGINX 1.31.5 - версия, в которой несколько заметных изменений объединены общей задачей: сделать маршрутизацию современного API более гибкой и при этом избавить разработчиков от необходимости писать отдельные скрипты для каждого сценария.
Главным нововведением стали так называемые предикатные блоки `location`. Они позволяют принимать решение о маршруте не только на основании URI, но и по значению любой переменной NGINX. Это существенно расширяет возможности, которые предлагает стандартная NGINX маршрутизация API-трафика.
Почему одной маршрутизации по URL уже недостаточно
В классическом HTTP запрос обычно описывается достаточно прозрачно: метод определяет действие, URL указывает на ресурс, заголовки передают параметры взаимодействия, а тело содержит полезную нагрузку. Поэтому большинство прокси-серверов и балансировщиков традиционно строят правила маршрутизации вокруг URI и HTTP-метода.
Однако современные приложения нередко помещают управляющие параметры в заголовки или тело запроса. Например, версия API, тип операции, идентификатор клиента или признак срочности могут находиться не в URL, а в JSON-документе. В результате промежуточному серверу становится сложнее определить, куда направлять запрос.
Именно здесь проявляется ограниченность традиционного подхода: NGINX изначально проектировался преимущественно для работы с URI. Новая модель снимает это ограничение и позволяет использовать любую переменную в качестве условия выбора конкретного `location`.
Подробное описание концепции и примеры конфигурации доступны в материале о [предикатной маршрутизации NGINX для API](https://habr.com/ru/articles/1080058/?utm_campaign=1080058&utm_source=habrahabr&utm_medium=rss).
Классические и предикатные location
Блоки `location` остаются фундаментом конфигурации NGINX. В них можно задавать upstream-группы, лимиты частоты запросов, правила изменения заголовков, параметры аутентификации, WAF и другие настройки. Для каждого участка маршрутизации эти политики могут действовать независимо.
Предикатные блоки не заменяют существующую модель, а расширяют её. Теперь условием попадания в `location` может быть вычисляемая переменная. Если её значение не равно пустой строке или нулю, NGINX считает условие истинным и применяет соответствующие директивы.
Условие можно сформировать с помощью модуля `map`. Он преобразует входное значение в заранее заданный результат, например `1` для подходящих запросов и `0` для остальных. Это особенно удобно при фильтрации HTTP-методов:
```nginx
map $request_method $restricted_methods {
default 0;
POST 1;
PUT 1;
DELETE 1;
}
```
После этого переменную `$restricted_methods` можно применять в других частях конфигурации. Значение по умолчанию необязательно указывать: пустая строка также интерпретируется как ложное условие. Но явный `0` зачастую упрощает диагностику и чтение правил.
Такой подход лежит в основе сценариев, где требуется настройка NGINX для API с разными политиками доступа. Например, GET-запросы можно отправлять в один upstream, операции изменения данных - в другой, а запросы с определённым методом дополнительно проверять через систему авторизации.
Вложенные предикаты и комбинирование условий
Предикатные `location` можно комбинировать с обычными URI-блоками. Сначала NGINX определяет участок пути, а затем выполняет дополнительное разделение по переменной или нескольким переменным.
Например, для `/api/v1/` можно отдельно обрабатывать чтение, изменение данных и административные операции. Внутри основного URI-блока правила могут учитывать метод, заголовок клиента, наличие токена или результат предварительного вычисления через `map`.
Такая схема делает NGINX роутинг запросов без скриптов более структурированным. Логика остаётся в конфигурации, но при этом не превращается в набор разрозненных обработчиков на JavaScript или другом языке.
Вложенность следует проектировать с учётом реальной модели приложения. Если сначала фильтровать трафик по заголовкам, а затем по URI, конфигурация будет отличаться от варианта, в котором главным критерием является путь, а дополнительные признаки используются только внутри конкретного API-раздела.
Маршрутизация по телу запроса и JSON
Наиболее интересный сценарий - принятие решения по содержимому тела HTTP-запроса. Например, разные типы событий могут передаваться на один endpoint, но обрабатываться разными микросервисами. В JSON могут находиться поля `action`, `event_type`, `priority` или `tenant_id`.
Если эти данные удаётся извлечь в переменную, её можно использовать как предикат для выбора upstream. Это открывает новые возможности для конфигурации NGINX для микросервисов, где единая точка входа распределяет нагрузку между специализированными сервисами.
При этом необходимо учитывать стоимость обработки. Чтение тела запроса и разбор JSON требуют больше ресурсов, чем проверка URI или заголовка. Для небольших запросов разница может быть незаметной, но при большом потоке или крупных payload она способна повлиять на задержку и пропускную способность.
Поэтому тяжёлые вычисления лучше выполнять только там, где они действительно нужны. Не стоит заставлять NGINX анализировать тело каждого запроса, если большую часть трафика можно распределить по пути, методу или простому заголовку.
Когда нужны NJS и сложная логика
Предикатная модель хорошо подходит для заранее определённых правил: сопоставления значений, комбинации простых условий, фильтрации по методам и заголовкам. Но иногда требуется полноценная логика - сложный разбор структуры JSON, несколько последовательных проверок или нестандартные преобразования.
В таких случаях может понадобиться NJS. Скрипты дают больше свободы, но одновременно повышают сложность эксплуатации: их нужно тестировать, сопровождать, контролировать производительность и учитывать возможные ошибки выполнения.
Поэтому практичный подход заключается в разделении задач. Простые и часто повторяющиеся правила следует реализовывать средствами конфигурации, а действительно сложную бизнес-логику оставлять приложениям или специализированным обработчикам. Такой баланс позволяет использовать NGINX балансировку API без чрезмерного усложнения инфраструктуры.
Производительность и безопасность
Предикаты особенно полезны на границе между клиентом и внутренними сервисами. До передачи запроса в upstream можно проверить метод, заголовки, признаки авторизации и другие параметры. Это помогает отсеивать нежелательный трафик раньше, чем он попадёт во внутреннюю сеть.
Однако любое дополнительное условие влияет на обработку запроса. При проектировании правил важно оценивать порядок проверок: сначала должны выполняться дешёвые операции, а ресурсоёмкие - только для уже отфильтрованного набора запросов.
Нужно также избегать слишком большого количества пересекающихся правил. Сложная конфигурация может быть формально корректной, но при этом трудной для аудита. Для критичных API полезно документировать назначение переменных, явно задавать значения по умолчанию и проверять поведение на пограничных случаях.
Итог
Предикатные `location` расширяют традиционную модель NGINX: маршрутизировать запрос теперь можно не только по URL, но и по вычисляемым значениям, заголовкам, методам и другим признакам. Это делает прокси более подходящим для микросервисных платформ и сложных API-шлюзов.
Главное преимущество подхода - возможность реализовать гибкую NGINX маршрутизация API-трафика непосредственно в конфигурации, без обязательного привлечения скриптов. При грамотном использовании `map`, вложенных условий и upstream-групп можно построить понятную систему распределения запросов, сохранив контроль над производительностью и безопасностью.


