01
O que a afinidade de sessão realmente promete e o que ela não promete
A afinidade de sessão é um mecanismo simples: o balanceador escolhe uma instância na primeira requisição de um cliente e passa a mandar todas as requisições seguintes daquele cliente para a mesma instância. A implementação varia, mas o efeito é sempre o mesmo, e a promessa também: se o processo guardou algo na memória durante a primeira requisição, esse algo continua disponível na segunda. É isso, e só isso, que a afinidade entrega.
O que ela não entrega é a parte que quebra em produção. Ela não garante que a instância continue existindo, e num ambiente com escala automática, implantação contínua e verificação de saúde, a instância deixa de existir várias vezes por dia. Ela não garante que o cliente continue sendo reconhecido, porque a identificação depende de um cookie que o cliente pode não aceitar ou de um endereço de origem que muda quando o usuário troca de rede. E ela não garante distribuição, que é justamente o motivo pelo qual o balanceador existe.
A confusão mais cara nesse assunto é tratar afinidade como um ajuste de desempenho. Ela não é. Afinidade é uma restrição de roteamento adotada para compensar estado que ficou no lugar errado, e toda vez que ela é ligada por conveniência sem que ninguém escreva o motivo, o sistema ganha uma dependência invisível entre o cliente e um processo específico. A pergunta que separa uso legítimo de dívida é objetiva: se essa instância for reiniciada agora, o que o usuário perde. Se a resposta for nada, a afinidade está sobrando. Se for alguma coisa, o problema é o estado, não o roteamento.
| Mecanismo de afinidade | Como identifica o cliente | Onde quebra na prática | Sobrevive a reinício da instância |
|---|---|---|---|
| Cookie emitido pelo balanceador | Cookie próprio, opaco para a aplicação | Cliente que bloqueia cookie, chamada de API sem navegador | Não, o cliente é remanejado sem aviso |
| Cookie da aplicação usado como chave | Valor de um cookie que a aplicação já define | Renovação do cookie no login troca a instância no meio do fluxo | Não, e ainda pode trocar sem que a instância caia |
| Hash do endereço de origem | Endereço IP do cliente | Rede móvel, saída NAT corporativa, proxy compartilhado | Não, e distribui muito mal atrás de NAT |
| Hash consistente por chave de aplicação | Identificador de usuário ou de tenant enviado na requisição | Exige que a chave venha em toda requisição, inclusive nas anônimas | Parcialmente, remaneja só a fatia da instância removida |
| Sem afinidade, estado externo | Não precisa identificar, qualquer instância serve | Custo de latência da leitura de estado a cada requisição | Sim, é o único que sobrevive por construção |
A quarta linha é a que costuma ser esquecida nas discussões, e é a mais útil quando existe uma razão legítima para manter localidade, como um cache local caro de aquecer. Hash consistente por chave de aplicação não amarra o usuário a uma instância pela ordem de chegada, e sim por uma função determinística: quando uma instância sai do conjunto, apenas a fatia dela é redistribuída, e as demais chaves continuam onde estavam. É a diferença entre remanejar cem por cento dos clientes de uma instância que caiu e remanejar exatamente os clientes que estavam nela.