Fundo
Eu tenho a seguinte configuração do Nginx que é o balanceamento de carga de 2 servidores Tomcat em execução em 2 servidores diferentes:
### http://nginx.org/en/docs/http/ngx_http_upstream_module.html#hash
upstream backend_w_affinity {
hash $request_uri consistent;
server 192.168.110.11:8080;
server 192.168.110.12:8080;
}
server {
listen 80 default_server;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
location ~ ^/path/to/rest/endpoint$ { proxy_pass http://backend_w_affinity; }
}
Quando uso o seguinte curl
comando para direcionar o tráfego no Nginx, parece bom.
$ watch "curl -iI http://10.128.13.153/path/to/rest/endpoint"
HTTP/1.1 401 Unauthorized
Server: nginx/1.8.0
Date: Tue, 09 Jun 2015 01:31:13 GMT
Content-Type: application/xml;charset=ISO-8859-1
Content-Length: 231
Connection: keep-alive
OBSERVAÇÃO: percebo que estou obtendo 401 acima. Definitivamente, o Tomcat está ativo e, se eu alterar o caminho para que ele aponte para uma página estática no Tomcat, para que eu obtenha 200, ele ainda se comporta da mesma maneira, então isso não parece ser um problema no momento.
Inicialmente parece bem
Com o curl
comando acima em execução, todo o meu tráfego é direcionado para o primeiro servidor Tomcat. Se eu parar o Tomcat, todo o tráfego falhará no segundo servidor Tomcat.
Meu problema
Quando coloco o primeiro servidor Tomcat de volta, espero que todo o tráfego permaneça no segundo servidor agora. No entanto, assim que eu o recupero, o tráfego é direcionado de volta para o primeiro servidor Tomcat.
Como posso obter o Nginx, deixar o tráfego no segundo servidor e não redirecioná-lo de volta?
Você precisa usar sessões "adesivas" se quiser que o tráfego permaneça em um servidor mesmo diante de alterações na associação do grupo upstream. O hash consistente escolhe o mesmo servidor, desde que esteja disponível, o que não é o que você parece querer.
No seu caso, você está fazendo o hash do URI, o que é bom para "localidade do cache" se estiver usando proxy_cache no nginx. No entanto, hash consistente significa que um servidor sempre será a "primeira escolha" para um determinado URI, portanto, assim que ele voltar a ficar online, o nginx voltará para ele.
Existem módulos de sticky session disponíveis para nginx de código aberto de terceiros ou há uma opção de sticky session nativa no "NGINX Plus" comercial .
É possível fazer sticky sessions sem módulos adicionais ou assinatura nginx comercial, mas é um pouco feio. Você pode usar uma combinação de mapa, proxy_pass com um nome de host variável no destation e um local de fallback. Você também precisa definir um cabeçalho exclusivo em cada um dos seus servidores de back-end identificando-os (para que eles enviem um cabeçalho "X-Loadbalace-ID". Isso pode ser parte de um cookie de sessão, como uma rota Tomcat JVM. Na verdade, ainda executamos isso configuração em produção, pois é anterior à disponibilidade de sticky sessions no nginx.
Algo assim pode funcionar para você (simplificação não testada do que fazemos):