Sessões Sticky com Apache APISIX - Teoria
July 27, 2023
Sessões aderentes, também conhecidas como afinidade de sessão, são um mecanismo pelo qual um componente de roteamento que atua como uma fachada sempre encaminha uma solicitação para o mesmo nó upstream subjacente. Neste post, vou descrever a razão por trás das sessões aderentes, as alternativas disponíveis e como implementá-las via Apache APISIX.
Por que Sessões Aderentes?
As sessões aderentes se tornaram populares quando armazenávamos o estado no nó upstream, e não no banco de dados. Vou usar o exemplo de uma loja de e-commerce simplificada para explicar melhor.
Os fundamentos básicos de um pequeno site de e-commerce podem consistir em uma aplicação web e um banco de dados.
Se o negócio for bem-sucedido, ele crescerá, e em algum momento você precisará escalar essa arquitetura. Quando não for mais possível escalar verticalmente (máquinas maiores), você terá que escalar horizontalmente (mais nós). Com nós adicionais de aplicação, você também precisará de um mecanismo de balanceamento de carga na frente dos nós da aplicação web para distribuir a carga entre eles.
Acessar o banco de dados toda vez é uma operação cara. É aceitável para dados que são acessados com pouca frequência. No entanto, queremos exibir o conteúdo do carrinho para cada solicitação. Algumas alternativas estão disponíveis para acelerar as coisas. Se assumirmos que a aplicação web usa Renderização no Lado do Servidor (Server-Side Rendering), a solução clássica é manter os dados relacionados ao carrinho na memória no nó da aplicação web.
No entanto, se armazenarmos o carrinho do usuário X no nó 1, precisamos garantir que encaminhemos todas as solicitações do usuário X para o mesmo nó. Caso contrário, ele sentirá como se tivesse perdido o conteúdo do carrinho. Sessões aderentes, ou afinidade de sessão, é o mecanismo que encaminha consistentemente o mesmo usuário para o mesmo nó.
Limitação das Sessões Aderentes
Antes de prosseguir, preciso explicar uma limitação significativa das sessões aderentes. Se o nó da aplicação web que armazena os dados cair por qualquer motivo, os dados serão irremediavelmente perdidos. Para o cenário de e-commerce acima, isso significa que os usuários perderão ocasionalmente o carrinho, o que é inaceitável do ponto de vista do negócio.
Por essa razão, as sessões aderentes devem andar de mãos dadas com a replicação de sessão: os dados armazenados em um nó devem ser copiados e mantidos sincronizados com todos os outros nós.
Embora a replicação de sessão exista em todas as pilhas tecnológicas, não há uma especificação relacionada. Estou familiarizado com a JVM, então aqui estão algumas opções:
- O Tomcat oferece replicação de sessão pronta para uso
- Hazelcast oferece uma solução de memória em cluster que você pode integrar em diferentes níveis
- Spring Session é uma camada de abstração sobre soluções específicas
Quando os dados são replicados em todos os nós (ou em um cluster remoto), você pode pensar que não precisa mais de sessões aderentes. Isso é verdade se considerarmos apenas a disponibilidade e não o desempenho. Trata-se de localidade de dados: buscar dados no nó atual é mais rápido do que buscá-los em outro lugar via rede.
Sessões Aderentes no Apache APISIX
Sessões aderentes são um recurso essencial para qualquer Balanceador de Carga, Proxy Reverso e Gateway de API que se preze. No entanto, devo admitir que a documentação do Apache APISIX precisa de um ponto de entrada fácil no assunto.
O Apache APISIX vincula uma rota a um upstream. Um upstream consiste em um ou mais nós. Quando uma solicitação corresponde à rota, o Apache APISIX deve escolher entre todos os nós disponíveis para encaminhar a solicitação. Por padrão, o algoritmo é o round-robin ponderado. O round-robin usa um nó após o outro e, após o último, volta ao primeiro. Com um round-robin ponderado, o peso afeta quantas solicitações o Apache APISIX encaminha para um nó antes de mudar para o próximo.
No entanto, outros algoritmos estão disponíveis:
- Hash consistente
- Gráfico de Média Móvel Ponderada Exponencial
- Menos conexões
- Um personalizado
O hash consistente permite encaminhar para o mesmo nó dependendo de algum valor: uma variável do NGINX, um cabeçalho HTTP, um cookie, etc.
Lembre-se de que o HTTP é um protocolo sem estado, então os servidores de aplicação definem um cookie na primeira resposta para rastrear o usuário entre as solicitações HTTP. É o que chamamos de "sessão". Precisamos saber o nome do cookie de sessão subjacente. Diferentes servidores de aplicação emitem cookies diferentes:
JSESSIONID
para servidores baseados em JVMPHPSESSID
para PHPASPSESSIONID
para ASP.Net- etc.
Vou usar um Tomcat regular, então o cookie de sessão é JSESSIONID
. Portanto, a documentação do Apache APISIX para dois nós é a seguinte:
routes:
- uri: /*
upstream:
nodes:
"tomcat1:8080": 1 #1
"tomcat2:8080": 1 #1
type: chash #2
hash_on: cookie #3
key: cookie_JSESSIONID #4
- Define os nós upstream
- Escolhe o algoritmo de hash consistente
- Hash no cookie
- Define qual cookie usar para o hash
Conclusão
Neste post, detalhamos as sessões aderentes, que você deve sempre usar replicação de sessão com sessões aderentes, e como implementar sessões aderentes no Apache APISIX.
Para ir mais longe: