Ограничение скорости в Nginx для сложных конфигураций: HTTP/2, API и видеостриминг

от автора

Привет, Хабр!

Сегодня рассмотрим, как настроить полноценный traffic shaping в Nginx для сложных случаев, включая HTTP/2.

С появлением HTTP/2 управление трафиком стало ещё сложнее из-за его особенностей:

  • Мультиплексирование: Несколько запросов могут выполняться по одному соединению одновременно.

  • Сжатие заголовков: Использование HPACK для сжатия заголовков может влиять на скорость передачи.

  • Приоритизация потоков: Клиенты могут устанавливать приоритеты для разных потоков.

Директивы Traffic Shaping в Nginx

Директива limit_rate

Ограничивает скорость передачи ответа клиенту.

limit_rate rate;
location /downloads/ {     limit_rate 100k; # Ограничиваем скорость до 100 кБ/с }

Эта директива устанавливает максимальную скорость передачи данных клиенту. Полезно для ограничения скорости загрузки больших файлов.

Директива limit_rate_after

Начинает ограничивать скорость после передачи определённого объёма данных.

limit_rate_after size;
location /videos/ {     limit_rate_after 5m; # Начинаем ограничивать после 5 МБ     limit_rate 500k;     # Ограничиваем скорость до 500 кБ/с }

Можно использовать, когда нужно дать пользователю быстро начать загрузку, а затем ограничить скорость, чтобы не перегружать канал.

Модуль ngx_http_limit_req_module

Ограничивает количество запросов в секунду от одного клиента.

limit_req_zone key zone=name:size rate=rate;
  • key: Уникальный идентификатор клиента (обычно IP-адрес).

  • zone: Имя и размер памяти для хранения данных.

  • rate: Скорость запросов (например, 10r/s для 10 запросов в секунду).

Пример настройки:

http {     limit_req_zone $binary_remote_addr zone=mylimit:10m rate=5r/s;      server {         location /api/ {             limit_req zone=mylimit burst=10 nodelay;             # burst=10 позволяет временно превышать лимит на 10 запросов             # nodelay немедленно отклоняет лишние запросы         }     } }

Эта настройка позволяет защитить API от перегрузки.

Модуль ngx_http_limit_conn_module

Ограничивает количество одновременных соединений с одним клиентом.

limit_conn_zone key zone=name:size;
http {     limit_conn_zone $binary_remote_addr zone=addr:10m;      server {         location /download/ {             limit_conn addr 1; # Разрешаем только 1 соединение с одного IP         }     } }

Хорошо для предотвращения одновременной загрузки нескольких файлов одним пользователем.

Примеры использования

Ограничение скорости для HTTP/2

В HTTP/2 все запросы идут по одному соединению, поэтому limit_rate будет применяться ко всем потокам сразу.

Будем использовать директиву limit_rate внутри location или применять динамическое ограничение с помощью переменных.

map $http_host $limit_rate {     default 100k; # Устанавливаем ограничение по умолчанию }  server {     listen 443 ssl http2;      location / {         limit_rate $limit_rate; # Применяем ограничение скорости     } }

С переменной можно гибко управлять ограничением скорости.

Ограничение количества запросов для API с аутентификацией

Допустим, есть API, защищённый токенами, и нужно ограничить количество запросов для каждого пользователя.

http {     limit_req_zone $http_authorization zone=api_limit:10m rate=10r/s;      server {         location /api/ {             limit_req zone=api_limit burst=20 nodelay;         }     } }

Используем заголовок Authorization в качестве ключа для идентификации пользователя.

Управление трафиком для стриминговых сервисов

Необходимо оптимизировать передачу больших файлов (видео, аудио) без потери качества.

Используем модуль slice:

location /video/ {     slice 1m; # Разбиваем файл на куски по 1 МБ     proxy_pass http://backend;     proxy_set_header Range $slice_range;      limit_rate_after 10m; # Ограничиваем скорость после 10 МБ     limit_rate 1m;        # Ограничиваем скорость до 1 МБ/с }

Разбивка на куски позволяет лучше использовать кэш и управлять передачей данных.

Ограничение на основе геолокации

Нужно установить разные ограничения скорости для пользователей из разных стран.

Настройка с использованием модуля geo:

geo $limit_rate {     default         500k;    # Ограничение по умолчанию     192.168.1.0/24  1m;      # Для определённой подсети увеличиваем лимит     203.0.113.0/24  100k;    # Для другой подсети уменьшаем лимит }  server {     location / {         limit_rate $limit_rate;     } }

Оптимизация и мониторинг

Включение статуса сервера

Позволяет получить информацию о текущем состоянии Nginx:

server {     location /nginx_status {         stub_status;         allow 127.0.0.1; # Разрешаем доступ только с localhost         deny all;     } }

Доступ к этой странице поможет мониторить активные соединения и обрабатывать данные в системах мониторинга.

Настройка логирования

Добавляем информацию о лимитировании в логи:

log_format custom '$remote_addr - $remote_user [$time_local] '                   '"$request" $status $body_bytes_sent '                   '"$http_referer" "$http_user_agent" '                   '$limit_req_status';  access_log /var/log/nginx/access.log custom;

Поле $limit_req_status покажет статус ограничения PASSED, DELAYED, REJECTED.


Заключение

Настройка полноценного traffic shaping в Nginx — задача непростая, но крайне важная. Она требует внимания к деталям и понимания особенностей каждого случая.

Также, пользуясь случаем, напоминаю про открытый урок по основам балансировки нагрузки в Angie и Nginx, который пройдет сегодня (16 сентября) в 19:00.

На занятии познакомимся с архитектурой балансировки нагрузки в веб-приложениях, рассмотрим различные методы балансировки нагрузки в Nginx и Angie, различия в этих продуктах. А также поговорим об отказоустойчивости. Записаться на урок можно на странице курса «Администрирование Nginx/Angie».


ссылка на оригинал статьи https://habr.com/ru/articles/843424/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *