Глава 3. Управление обменом
Содержание
NGINX и NGINX Plus также относятся и к контроллерам веб обмена. Вы можете применять NGINX для умной маршрутизации обмена и контролировать поток основываясь на большом числе параметров. Данная глава рассматривает возможность NGINX расщеплять запросы клиентов на базе процентных соотношений, применения географического местоположения клиентов, а также управления самим потоком обмена в виде ограничений скорости, подключений и полосы пропускания. Знакомясь с данной главой имейте в виду что у вас есть возможность смешивать и устанавливать соответствия этих функций для допуска разнообразных вариантов.
Задача
Вам требуется расщеплять клиентов между двумя или более версиями некого файла или приложения для проверки приемлемости.
Решение
Воспользуйтесь модулем split_clients
для предписания процентного соотношения
вашим клиентам на различные восходящие пулы:
split_clients "${remote_addr}AAA" $variant {
20.0% "backendv2";
* "backendv1";
}
Эта директива split_clients
хэширует значение передаваемого вами первым параметром
строки и проводит деление этого хэша в заданном процентном соотношении для установления соответствия со значением
второго параметра. Значением третьего параметра является некий содержащий пару ключ- значение объект, в котором ключ
выступает процентным весом, а его значение это назначаемое значение. Значением ключа может быть либо процентное соотношение,
либо сивмол звёздочки. Передаваемая звёздочка означает что передаётся вся остающаяся после всех процентных соотношений часть.
Задаваемым значением для нашей переменной $variant
будет
backendv2
для 20% адресов клиентов, а для остающихся 80% остаётся
backendv1
.
В нашем примере backendv1
и backendv2
представляют пулы серверов восходящего потока и могут применяться с директивой
proxy_pass
, подобной следующей:
location / {
proxy_pass http://$variant
}
При помощи переменной $variant
наш обмен будет расщепляться на два различных
пула серверов.
Обсуждение
Данный вид проверки A/B полезен при тестировании различных видов свойств торговли и интерфейса для пересмотра соотношений
в сайтах электронной коммерции. Для прикладных задач распространено применение типа разработки с названием канареечного
выпуска. При таком типе разработки обмен слегка отключается для данной новой версии. Расщепление ваших клиентов между
различными версиями вашего приложения может оказаться полезным при раскрутке новой версии кода для для ограничения
радиуса поражения в случае некой ошибки. Всякий раз когда возникает причина для разделения клиентов между двумя различными
наборами приложений NGINX запросто делает это при помощи рассмотренного модуля
split_clients
.
Также ознакомьтесь
Задача
Вам требуется установить базу данных GeoIP и разрешить её встроенные переменные внутри NGINX для регистрации и определения в вашем приложении значения местоположения ваших клиентов.
Решение
Официальный репозиторий пакета Открытого исходного кода NGINX, который вы настраивали при установке NGINX в Главе 1, предоставляет пакет с названием
nginx-module-geoip
. При применении репозитория пакетов NGINX Plus, такой пакет
именуется nginx-plus-module-geoip
. Эти пактеы устанавливают имеющуюся динамическую
версию модуля GeoIP.
Открытый исходный код NGINX RHEL/ CentOS:
# yum install nginx-module-geoip
Открытый исходный код NGINX Debian/ Ubuntu:
# apt-get install nginx-module-geoip
Открытый исходный код NGINX Plus RHEL/ CentOS:
# yum install nginx-plus-module-geoip
Открытый исходный код NGINX Plus Debian/ Ubuntu:
# apt-get install nginx-plus-module-geoip
Выгрузите базу данных стран и городов GeoIP и разархивируйте её:
# mkdir /etc/nginx/geoip
# cd /etc/nginx/geoip
# wget "http://geolite.maxmind.com/\
download/geoip/database/GeoLiteCountry/GeoIP.dat.gz"
# gunzip GeoIP.dat.gz
# wget "http://geolite.maxmind.com/\
download/geoip/database/GeoLiteCity.dat.gz"
# gunzip GeoLiteCity.dat.gz
Этот набор команд создаёт некий каталог geoip
в уже имеющемся каталоге
/etc/nginx
, переходит в этот новый каталог, а таже выгружает необходимые
пакеты и выполняет их разархивацию.
Имея на своём локальном диске базу данных GeoIP для стран и городов вы теперь можете выдать инструкции для модуля GeoIP NGINX на её применение для выставления встроенных переменных на основе получаемого адреса IP клиента:
load_module "/usr/lib64/nginx/modules/ngx_http_geoip_module.so";
http {
geoip_country /etc/nginx/geoip/GeoIP.dat;
geoip_city /etc/nginx/geoip/GeoLiteCity.dat;
...
}
Указанная директива load_module
динамически загружает передаваемый ей модуль из
пути вашей файловой системы. Данная директива load_module
допустима только в
основном контексте. Следующая директива geoip_country
получает некий путь к файлу
GeoIP.dat
, который содержит значения соответствий IP адресов базы данных
кодам стран и допустима лишь в контексте обозначенного HTTP.
Обсуждение
Рассматриваемые директивы geoip_country
и
geoip_city
выставляют ряд доступных в этом модуле встроенных переменных. Первая
директива geoip_country
включает переменные, которые позволяют вам отличать
значение страны происхождения вашего клиента. Эти переменные содержат в своём составе $geoip_country_code
,
$geoip_country_code3
и $geoip_country_name
.
Первая переменная кода страны возвращает значение двухбуквенного кода страны, а переменная с
3
в конце возвращает значение трёхбуквенного кода страны. Переменная названия
страны возвращает полное название страны.
Директива geoip_city
возвращает приличное число переменных. Эта директива
geoip_city
возвращает аналогичные директиве
$geoip_country
переменные со слегка иными названиями, такие как
$geoip_city_country_code
,
$geoip_city_country_code3
и
$geoip_city_country_name
. Прочие переменные включают в свой состав
$geoip_city
, $geoip_city_continent_code
,
$geoip_latitude
, $geoip_longitude
и
$geoip_postal_code
, которые имеют достаточно описательные названия для возвращаемых ими
значений. $geoip_region
и $geoip_region_name
описывают значения региона, территории, штата, провинции, федеральной земли и им подобное. Регион является двухбуквенным кодом,
в то время как назавние региона представляет его полное название. $geoip_area_code
,
которая допустима лишь в пределах US, возвращает значение из трёх цифр для телефонного кода области.
Обладая данными переменными вы имеете возможность регистрации информации о своём клиенте. В качестве опции вы также можете передавать эту информацию в своё приложение в качестве некого заголовка или переменной, либо применять NGINX для маршрутизации своего обмена определёнными путями.
Также ознакомьтесь
Задача
Вам требуется ограничить доступ для определённых стран в соответствии с требованиями контрактов или приложения.
Решение
Установите соответствие тем странам, которые вы намерены блокировать:
load_module
"/usr/lib64/nginx/modules/ngx_http_geoip_module.so";
http {
map $geoip_country_code $country_access {
"US" 0;
"RU" 0;
default 1;
}
...
}
Это соответствие устанавливает некую переменную $country_access
в значение
1
или 0
. Если полученный IP адрес
имеет местом происходжения США или Россию, значение переменной будет установлено в
0
. Для всех прочих стран значение этой переменной устанавливается равным
1
.
Теперь внутри своего блока server
мы будем применять оператор
if
для запрета всем тем, кто имеет местом происхождения США или Россию:
server {
if ($country_access = '1') {
return 403;
}
...
}
Данный оператор if
будет вычислять True
когда значение переменной $country_access
установлено в
1
. В случае True
наш сервер будет
возвращать 403 без авторизации. В противном случае все операции нашего сервера будут обычными. Тем самым данный блок
if
присутствует только для запрета тех людей, которые происходят из США или
России.
Обсуждение
Это короткий, но простой пример того как разрешать доступ всего из пары стран. Даный образец может быть расширен с тем, чтобы соответствовать вашим потребностям. Вы можете применять те же самые приёмы чтобы выполнять разрешения или блокировки на основе любых встроенных переменных, которые вам предоставляет описанный модуль GeoIP.
Задача
Вам требуется выяснить IP адрес первоначального клиента, поскольку перед самим сервером NGINX имеется ряд посредников (прокси).
Решение
Воспользуйтесь директивой geoip_proxy
для выявления диапазона IP адреса вашего
посредника и соответствующей директивой geoip_proxy_recursive
для поиска значения
первоначального IP:
load_module "/usr/lib64/nginx/modules/ngx_http_geoip_module.so";
http {
geoip_country /etc/nginx/geoip/GeoIP.dat;
geoip_city /etc/nginx/geoip/GeoLiteCity.dat;
geoip_proxy 10.0.16.0/26;
geoip_proxy_recursive on;
...
}
Директива geoip_proxy
определяет некий диапазон CIDR, в котором обитают наши
серверы посредников и указывают NGINX на необходимость применять для поиска требуемых адресов своего клиента заголовка
X-Forwarded-For
. Последняя директива geoip_proxy_recursive
иструктирует NGINX о необходимости рекурсивного поиска через все заголовки X-Forwarded-For
на предмет самого последнего известного IP клиента.
Обсуждение
Вы можете обнаружить, что когда вы применяете перед NGINX некого посредника (прокси), NGINX будет подхватывать вместо
IP адреса такого клиента адрес применяемого посредника. По этой причине вы можете применять директиву
geoip_proxy
для того чтобы указывать NGINX на применение имеющегося заголовка
X-Forwarded-For
когда подключения открываются из заданного диапазона. Эта директива
geoip_proxy
принимает некий адрес либо диапазон CIDR. Когда перед NGINX присутствует
множество передающих обмен посредников, вы можете применять для рекурсивного поиска через адреса
X-Forwarded-For
необходимого клиента директиву
geoip_proxy_recursive
. Вы можете пожелать применять нечто подобное этому при
использовании перед NGINX такого балансировщика нагрузки, как AWS ELB, балансировщик нагрузки Google или Azure.
Задача
Вам требуется ограничить общее число подключений на основе некого предварительно заданного ключа , такого как значение IP адреса клиента.
Решение
Для удержания замеров подключений постройте некую зону совместной памяти и воспользуйтесь директивой
limit_conn
для ограничения открытых подключений:
http {
limit_conn_zone $binary_remote_addr zone=limitbyaddr:10m;
limit_conn_status 429;
...
server {
...
limit_conn limitbyaddr 40;
...
}
}
Эта конфигурация создаёт некую зону совместной памяти с названием limitbyaddr
.
Применяемым предварительно определённым ключом является значение IP адреса клиента в двичной форме. Величина размера
зоны совместной памяти установлена в значение 10 Мегабайт. Последняя директива limit_conn
получает два параметра: некое название limit_conn_zone
и общее число допускаемых
подключений. Параметр limit_conn_status
устанавливает значение отклика при достижении
предела имеющихся подключений в состояние 429, что указывает на слишком большое число подключений. Обсуждаемые директивы
limit_conn
и limit_conn_status
допустимы
в соотвествующих контекстах HTTP, сервера и местоположения.
Обсуждение
Ограничение общего числа подключений основывается на неком ключе, который может применяться для определения злоупотреблений
и разделения ваших ресурсов справедливым образом по всем вашим клиентам. Важно быть осмотрительным в выборе вашего предварительно
заданного ключа. Может быть опасным применение некого IP адреса, как мы это длали в своём предыдущем примере, когда многие
пользователи применяют одну и ту же сетевую среду, которая происходит из одного и того же IP, например когда они расположены
за Network Address Translation (NAT). Мы способны ограничить определённую группу
клиентов целиком. Директива limit_conn_zone
допустима лишь в соответствующем контексте
HTTP. Вы можете применять любое число доступных NGINX переменных внутри своего контекста HTTP для определения конкретного
пользователя на уровне своего приложения , например куки сеанса, может быть более чётким решением в зависимости от варианта
применения. Значением по умолчанию для limit_conn_status
является 503, то есть
данная служба недоступна, а отклик уровня 500 указывает на ошибку сервера, в то время как отклики уровня 400
указывают на ошибку клиента.
Задача
Вам требуется ограничить значение скорости запросов по некому предварительно заданному ключу, такому как значение IP адреса клиента.
Решение
Для ограничения скорости запросов воспользуйтесь модулем ограничения скорости:
http {
limit_req_zone $binary_remote_addr
zone=limitbyaddr:10m rate=1r/s;
limit_req_status 429;
...
server {
...
limit_req zone=limitbyaddr burst=10 nodelay;
...
}
}
Данный пример настройки создаёт некую зону совместной памяти с названием limitbyaddr
.
Применяемым значением заранее определённого ключа является значение IP адреса клиента в двоичном виде. Величина размера
совместной зоны памяти установлена в 10 Мегабайт. Данная зона устанавливает значение скорости при помощи некого аргумента
ключевого слова. Приведённая директива limit_req
получает два необязательных аргумента
с ключевым словом: zone
и burst
.
zone
требуется для указания данной директиве какую именно применять зону предела
запросов совместной памяти. Когда исчерпана скорость запросов для данной зоны, запросы откладываются пока не будет достигнуто
их максимальный размер burst
, обозначенный в аргументе ключевого слова
burst
. Значением по умолчанию для ключевого слова burst
является ноль. limit_req
также получает некий третий необязательный параметр с
ключевым словом nodelay
. Этот параметр позволяет конкретному клиенту применять его
burst
без задержки прежде чем получить ограничение.
limit_req_status
устанавливает значение состояния, возвращаемого определённому клиенту
неким индивидуальным кодом состояния HTTP; по умолчанию он равен 503. limit_req_status
и limit_req
допустимы в контексте HTTP, сервера и местоположения.
limit_req_zone
допустим лишь в контексте HTTP. В NGINX Plus ограничение скорости
осведомлено о кластере, что является новинкой в R16.
Обсуждение
Обсуждаемый модуль ограничения скорости является очень мощным для защиты против злоупотребления частотой запросов
и в то же самое время предоставляет всем некий уровень качества услуг. Имеется множество причин для ограничения скорости
запросов, причём одной из них является безопасность. Вы можете препятствовать силовым атакам помещая на свою страницу
регистрации очень строгое ограничение. Вы можете установить некий санитарный предел для всех запросов, тем самым запрещая
соответствующие планы злонамерненным пользователям, которые могут пытаться запретить обслуживание вашего приложения или
впустую тратить ваши ресурсы. Настройка модуля ограничения скорости во многом аналогична предыдущему описанному в
рецепте модуле ограничения подключений. Вы можете определить
значение скорости в их числе в секунду или в минуту, которой ограничены запросы в обращениях. При достижении установленного
предела скорости это происшествие регистрируется. Также имеется отсутствующая в нашем примере директива
limit_req_log_level
, которая по умолчанию установлена в значение error, но также
может быть установлена в info, notice или warn. Что является новым в NGINX Plus с версии R16, так это то, что ограничение
скорости теперь осведомлено о кластере (обратитесь к соответствующему рецепту за получением примера синхронизации зон).
Задача
Вам необходимо ограничить полосу пропускания выгрузки для клиента к вашим ресурсам.
Решение
Для ограничения частоты откликов к клиенту воспользуйтесь директивами
limit_rate
и limit_rate_after
:
location /download/ {
limit_rate_after 10m;
limit_rate 1m;
}
Приведённые настройки данного блока местоположения определяет что для URI со значением префикса
download
значение частоты с которой этот отклик будет обслуживаться для
данного клиента будет ограничено после 10 Мегабайт до скорости 1 Мегабайт в секунду. Значение предела полосы пропускания
устанавливается для каждого подключения, а следовательно вы можете пожелать установить некий предел подключений а также
какой- то предел полосы пропускания, где это приемлемо.
Обсуждение
Ограничивая значение полосы пропускания для определённых подключений позволяет NGINX разделять его полосу пропускания
по всем своим клиентам тем образом как вы его определяете. Всё это делают две директивы: limit_rate
и limit_rate_after
. Первая директива limit_rate_after
может быть установлена практически во всех контекстах: HTTP, сервера, местоположения и if
когда if
расположен внутри местоположения. Следующая директива limit_rate
применяется в тех же самых контекстах, что и limit_rate_after
; тем не менее
она может быть альтернативно настроена установкой некой переменной с именем $limit_rate
.
Эта директива limit_rate_after
указывает что данное подключение не должно быть ограничено в
скорости до тех пока не будет передан определённый объём данных. Данная директива limit_rate
определяет значение ограничения скорости для данного контекста по умолчанию в байтах в секунду. Однако вы можете
определять m
для Мегабайт или g
для Гигабайт. Обе директивы имеют по умолчанию значение 0. Значение величины 0 подразумевает что предела для скоростей
выгрузки нет вовсе. Данный модуль позволяет вам программируемым образом изменять значение ограничения скорости клиентов.