Ответ
Для маршрутизации трафика от конкретного клиента к выделенному бэкенду я настраиваю условное проксирование в Nginx. Чаще всего это требуется для канареечных развертываний, тестирования новых версий или обслуживания VIP-клиентов.
Основной подход — использование директивы map и переменных:
# Определяем правило маршрутизации на основе IP-адреса клиента
map $remote_addr $backend_pool {
"192.168.1.100" "backend_special";
"10.20.30.40" "backend_canary";
default "backend_default";
}
upstream backend_special {
server 10.0.0.1:8080;
}
upstream backend_canary {
server 10.0.0.2:8080;
}
upstream backend_default {
server 10.0.0.3:8080;
server 10.0.0.4:8080;
}
server {
listen 80;
server_name api.example.com;
location / {
# Динамическое проксирование на основе вычисленной переменной
proxy_pass http://$backend_pool;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
Альтернативные критерии маршрутизации, которые я использовал:
-
По заголовку User-Agent или кастомному заголовку:
map $http_user_agent $backend_pool { ~*mobile "backend_mobile_optimized"; default "backend_default"; } -
По cookie (например, для A/B-тестирования):
map $cookie_experiment_group $backend_pool { "group_b" "backend_experiment"; default "backend_default"; } -
По части пути URL:
location ~ ^/api/v2/(.*)$ { # Все запросы к v2 API идут на новый бэкенд proxy_pass http://backend_v2/$1; }
Ключевые моменты:
- Использование
mapпредпочтительнее цепочкиif, так как оно эффективнее и безопаснее. - Для сложной логики можно использовать переменную
$request_idили вычислять хэш от определенных параметров запроса. - Важно настроить корректную передачу заголовков (особенно
X-Forwarded-For) и таймауты (proxy_connect_timeout,proxy_read_timeout).