Pull to refresh

«Правильное» ограничение скорости в Nginx. Миф или реальность?

Reading time3 min
Views35K


Вот уже много лет пользователей Nginx мучает один и тот же вопрос: «Как можно ограничить скорость в целом для IP адреса независимо от числа сессий (соединений)? Почему Nginx этого не умеет? Почему разработчики Nginx так упорно не хотят реализовать этот простой функционал?» И ответить мне им нечего, о чём думают разработчики Nginx — не понятно и известно, наверное, только господу богу.

Бороться с этим можно по разному, кто-то использует скрипты на подобие htb.init, кто-то пишет скрипты шейпинга самостоятельно и делится удачным опытом на Хабре, а некоторые и вовсе используют PHP для ограничения скорости отдачи файлов. Только представьте себе, каким будет оверхед и расход памяти, при использовании PHP в подобных целях.

На данный момент Nginx не умеет ограничивать скорость для IP и делает это только в рамках отдельных сессий. Что это означает? Если администратор установил в конфиге ограничение скорости в 100 Кбайт/сек, то создав 10 соединений с сервером можно получить скорость в 1 Мбайт/сек, что никак не вписывается в планы администратора. Достичь желаемого средствами самого Nginx можно лишь установив лимит, например

http {
    limit_conn_zone  $binary_remote_addr  zone=perip:10m;
    server {
        location /download/ {
            limit_conn  perip  1;
        }
    }
}

который не даст создать более 1-го соединения с отдельно взятого IP адреса. Однако на практике использование такого ограничения на сервере имеет мало смысла, ведь за одним IP адресом могут скрываться тысячи пользователей, а при нестабильном сетевом подключении пользователь вообще рискует не получить доступ к файлу.

Но, как оказалось, не всё так мрачно и выход из ситуации есть. Это простой маленький модуль от yaoweibin под названием nginx_limit_speed_module. Давайте рассмотрим как работает этот модуль:

http {
    limit_speed_zone  one  $binary_remote_addr  10m;
    server {
        location /download/ {
            limit_speed  one  100k;
        }
    }
}

Директива limit_speed задаёт суммарную скорость для всех подключений с одного IP адреса. Например, если установлен лимит скорости в 100 Кбайт/сек, а пользователь при этом качает файл в 10 потоков, то скорость скачивания для каждого отдельно взятого потока составит 10 Кбайт/сек (100k/10). Заметьте, это без всяких танцев с шейпингом в Linux и извращений с использованием PHP. Удобно, просто и понятно. На мой взгляд именно так и должно быть, но почему-то этого до сих порт нет в Nginx «из коробки» за что мне хотелось бы кинуть большой такой камешек в огород Nginx.

Для сборки Nginx с этим замечательным модулем достаточно добавить в параметры ./configure такую запись:

--add-module=/путь до папки с модулем/nginx_limit_speed_module

Например:

./configure --prefix=/etc/nginx --sbin-path=/usr/sbin/nginx --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --pid-path=/var/run/nginx.pid --lock-path=/var/run/nginx.lock --http-client-body-temp-path=/var/cache/nginx/client_temp --http-proxy-temp-path=/var/cache/nginx/proxy_temp --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp --http-scgi-temp-path=/var/cache/nginx/scgi_temp --user=nginx --group=nginx --with-http_ssl_module --with-http_realip_module --with-http_addition_module --with-http_sub_module --with-http_dav_module --with-http_flv_module --with-http_mp4_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_random_index_module --with-http_secure_link_module --with-http_stub_status_module --with-http_auth_request_module --with-file-aio --with-ipv6 --with-http_spdy_module --add-module=/root/nginx_limit_speed_module --with-cc-opt='-O2 -g -pipe -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -m64 -mtune=generic'

Подробно останавливаться на сборке Nginx я не буду, на этому тему уже написано немало статей. В качестве краткого руководства по сборке можно использовать эту инструкцию.

Страница модуля на GitHub: https://github.com/yaoweibin/nginx_limit_speed_module
Tags:
Hubs:
Total votes 51: ↑45 and ↓6+39
Comments60

Articles