Иногда случаются ситуации, когда на новую версию веб-сервиса по тем или иным причинам нежелательно пускать всех пользователей сервиса сразу.
В этом посте я напишу, как реализовать подобное распределение пользователей по разным версиям проекта средставми nginx.
Определимся с условиями нашей задачи:
Итак, первый блок (geo) описывает как раз распределение пользователей по апстримам.
В этом посте я напишу, как реализовать подобное распределение пользователей по разным версиям проекта средставми nginx.
Определимся с условиями нашей задачи:
- На новую версию сервиса мы должны направить ≈20% всех пользователей
- Есть ip-адреса клиентов, которые должны всенепременно попадать на старую версию
- То же самое, но – всенепременно на новую.
Далее я приведу конфигурационный файл целиком, а после опишу принцип его действия.
geo $mytest_participant {
default 1;
10.1.1.1 0;
192.168.45.2 2;
}
map $mytest_participant $resulting_upstream_name {
0 "old_version_upstream";
1 "distributed_upstream";
2 "new_version_upstream";
}
upstream distributed_upstream {
ip_hash;
server 1.1.1.1 weight=8; # Old version server, 80% of clients
server 2.2.2.2; # New version server
}
upstream old_version_upstream {
server 1.1.1.1;
}
upstream new_version_upstream {
server 2.2.2.2;
}
server {
listen 80;
server_name example.com;
location / {
proxy_pass http://$resulting_upstream_name;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
Итак, первый блок (geo) описывает как раз распределение пользователей по апстримам.
ip-адреса (можно использовать CIDR-нотацию, разумеется), для которых выставлено значение 0, будут направляться на старую версию принудительно, 1 - распределяться по вышеуказанному алгоритму (80% – на старую, 20% – на новую версию), ну и 2 - принудительно на новую.
Именно в зависимости от этого значения и присваивается имя апстрима в следующем блоке (map).
Далее все просто: описываются апстримы для старой и новых версий, а также наш распределенный апстрим. Для последнего используется алгоритм балансировки ip_hash, благодаря которому одни и те же ip-адреса будут попадать строго на тот апстрим, на который попали впервые. Если нам нужно изменить процентное соотношение распределения по старой и новым версиям, то правим соответствующим образом параметр weight для старого апстрима.
Вот, собственно, и всё.
Нужно, однако, помнить, что ip_hash использует только первые три октета ip-адреса клиента, т.е. на ту или иную версию попадет сразу весь /24 сегмент. Однако обычно это не является чем-то критичным, тем более, что в блоке geo можно подкорректировать ситуацию для отдельных ip-адресов, при наличии необходимости.