Blog
Domine a plataforma e otimize seus gastos!
Azure Front Door - Erro de Afinidade de Sessão
Trabalhando com aplicações legadas e afinidade de sessão, nem sempre as configurações são o que parece.
Ola pessoALL,
Estamos implantando o Azure Front Door em um cliente junto do WAF o que até então seria uma tarefa normal acabou se desdobrando em uma longa sessão de troubleshooting comigo quase perdendo as esperanças por um simples detalhe.
Para o Azure Front Door a diretiva Cache-Control: no-cache significa cache.
Para termos um pouco mais de contexto, estamos falando de uma aplicação legada escrita há +/- 20 anos, e roda bem até hoje. Ela está em fase de atualização, mas boa parte do sistema ainda roda no legado e por ser escrita em ASP Clássico temos uma hard rule que as requisições uma vez estabelecidas precisam ficar sempre no mesmo servidor, o que é tarefa simples para qualquer load balancer.
Gravei até um vídeo para explicar em mais detalhes o problema e a solução caso voce prefira uma explicação mais detalhada.
Uma nota, para mim mesmo, tudo isso teria sido facilmente resolvido se ao invés de confiar na experiência eu tivesse lido a documentação com mais cuidado!
Como falei anteriormente, a aplicação necessita de um cookie para manter a afinidade da sessão, garantindo que uma vez que minha requisição seja respondida por um servidor, todas as próximas requisições ficarão sempre no mesmo servidor.
No Azure Front Door isso é definido pela propriedade "Session Affinity" nos grupos de Origem.

Como podemos observar na imagem anterior, a propriedade está corretamente configurada, mas, na prática, a configuração não estava sendo respeitada.

Após bater um pouco a cabeça entre habilitar e desabilitar algumas configurações, recorri à documentação que é clara em dizer que os cookies precisam estar presentes para que a configuração funcione e para minha surpresa em alguns casos eu via o cookie presente e em outros não.
To protect against this, session affinity will not be established if the origin sends a cacheable response when this is attempted. If the session has already been established, it does not matter if the response from the origin is cacheable.

Ok, aqui eu pensei deixa eu validar se a requisição está retornando algum header Cache-Control e após validar estava sendo retornado "Cache-Control: no-cache". Esse ponto em particular que me quebrou, a princípio você imagina que a instrução seja justamente para a requisição não ser "cacheada". O que na minha cabeça se encaixa nessa parte da documentação:
Session affinity will be established in the following circumstances beyond the standard non-cacheable scenarios.
Depois de muito quebrar a cabeça achei um artigo que relatava um problema parecido

No artigo, o autor pontua que a especificação HTTP define que a diretiva no-cache não deve ser usada para cache, mas sim como indicativo que uma revalidação deve ser feita.
The "no-cache" response directive indicates that the response MUST NOT be used to satisfy a subsequent request without successful validation on the origin server

no-cache The response may be stored by any cache, even if the response is normally non-cacheable. However, the stored response MUST always go through validation with the origin server first before using it.

Após entendido e voltando na documentação do Front Door, trocamos a diretiva de cache de "no-cache" para no-store e tudo funcionou como esperado.
app.MapGet("/ping", () => Environment.MachineName);
app.MapGet("/no-cache", (HttpContext context) =>
{
context.Response.Headers.CacheControl = "no-cache";
return Environment.MachineName;
});
app.MapGet("/no-store", (HttpContext context) =>
{
context.Response.Headers.CacheControl = "no-store";
return Environment.MachineName;
});

Pronto, com o cabeçalho correto, as configurações de sessão são respeitadas e o sistema funciona como esperado.
Espero que vocês tenham gostado desse relato e deixem nos comentários se vocês já se depararam com situações parecidas lidando com aplicações legadas.