Ограничение скорости в 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».