Pense duas vezes antes de utilizar Sessions

Session é um recurso utilizado em inúmeras situações no ASP.NET, porém já faz algum tempo que seu uso não é mais recomendado, conheça os principais motivos e como você pode substituir as sessions em seu projeto.

Session é um assunto muito abordado em inúmeros fóruns de discussões em todo mundo. Foi introduzido no ASP clássico e sua utilização está presente até os dias de hoje no ASP.NET.

ASP.NET Sessions

Armazenar informações de usuário logado no sistema, itens do carrinho de compras, resultado de uma pesquisa em banco de dados e demais cenários geralmente são resolvidos através do armazenamento em sessions. Por que isso não é recomendado?

O conceito de Web é Stateless

Uma aplicação web não deve manter estado, uma aplicação web deve usar sempre que possível recursos assíncronos no client-side e server-side, isso proporcionará performance pois não satura o pipeline da aplicação e escalabilidade pois não depende de recursos disponíveis em um determinado servidor.

Sessions utilizam a memória do pool do IIS

Por padrão as sessions são armazenadas no pool do IIS e isso é uma péssima opção para armazenar dados de usuários, pois o pool do IIS recicla constantemente e isto está fora do controle do desenvolvedor, por diversos motivos o pool pode ser reciclado e todos os usuários perderão as informações armazenadas, isso é muito frustrante para o usuário da aplicação e nunca deveria acontecer.

Uma solução para isso seria utilizar sessions out-of-proc (armazenando as sessions em um SQL Server ou outro State Server), mas não significa que que é uma boa alternativa, existem alguns problemas nessa abordagem:

  1. Irá custar 2 requisições extras de rede, uma para carregar a session antes do request ser processado e outra para armazenar novamente o estado da session após o request. E isso irá ocorrer a cada request mesmo que não esteja utilizando a session em determinada página.
  2. Não é performático, a cada request a session precisa ser serializada e deserializada, isso irá custar mais recursos de CPU e memória.
  3. Bancos de dados relacionais não são mais rápidos que o acesso de memória, não é performático realizar 2 hits no banco a cada request de cada usuário.
  4. Poderá saturar o pipeline da aplicação, uma vez que um request depende da leitura de um banco de dados para finalizar seu ciclo de vida.

Sessions são de acesso exclusivo

Sessions irão prejudicar a performance de requests concorrentes. Suponha que uma página via AJAX dispare 2 requests para o mesmo usuário, o acesso de leitura da session é exclusivo, logo o ASP.NET irá forçar que o segundo request aguarde enquanto o primeiro faz a leitura da session, isso implica na escalabilidade da aplicação.
Recursos do HTML 5 permitem conexões permanentes (Server Sent Events, WebSockets) isso significa que problemas podem ocorrer no caso de requests concorrentes.

Sessions não são escaláveis

Sessions trabalhando no modo in-proc (habilitado por padrão) irão prejudicar a escalabilidade da aplicação, uma vez que a memória utilizada pela session é de um servidor específico. Suponha que existam N servidores da mesma aplicação que estejam sendo suportados por um load balancing, uma vez que a session foi criada no servidorX a aplicação só funcionará se todos os requests forem redirecionados para o servidorX, existem meios de realizar isto, porém essa abordagem desconfigura o conceito de escalabilidade.

Sessions degradam a performance da aplicação

Em muitas aplicações é possível notar o IIS batendo o topo de utilização de memória, muitas vezes a utilização da memória não é causada pelos recursos do IIS e sim de alocação de dados via sessions. Desenvolvedores realizam uma pesquisa no banco e guardam o resultado numa session para poder reaproveitar a pesquisa, porém quase sempre esquecem de destruir aquela sessão. Essa facilidade que as sessions proveem acaba sendo uma armadilha para boa performance da aplicação uma vez que a memória disponível para rodar a aplicação é dividida e consumida pelas sessions.

Sessions não são necessárias? Como posso substituí-las? Quais recursos utilizar?

Com certeza as sessions não são necessárias e obviamente não devem ser utilizadas pelos motivos apresentados acima. Porém a abordagem para substituir as sessions depende do cenário. Apresentarei algumas possibilidades.

  • Controle de usuários logados, armazenamento de informações de usuários.
    A utilização de Cookies é uma excelente alternativa para persistência de usuários logados, a informação fica no client-side e permite escalabilidade e ao mesmo tempo segurança. Grandes sites como Facebook utilizam Cookies para persistência de usuários.
    Caso queira armazenar informações de usuários no Cookie é possível porém existe uma limitação de tamanho (4K), talvez seja interessante armazenar uma chave no Cookie onde através dela seja possível localizar mais informações em outro recurso de armazenamento.
    O ASP.NET Identity é uma ótima alternativa para esse cenário, ele trabalha com Cookies para persistência do usuário e também com Claims para armazenamento de dados (nome, e-mail, permissões e etc…).

  • Controle de carrinho de compras.
    Carrinho de compras requerem um tratamento especial, pois não importa se a compra foi concluída ou não é sempre importante obter informações sobre carrinhos abandonados para trabalhar na analise dessas informações.
    Minha recomendação é armazenar no banco, em uma tabela destinada para esse tipo de controle, uma vez que o usuário logado retorna ao site é possível oferecer que ele restaure o carrinho abandonado, entre outras possibilidades.
    É possível também controlar o carrinho de usuários não logados através do recurso Anonymous Identification Module do ASP.NET onde é criado um Cookie com um ID único e pode ser recuperado através do Request.AnonymousID.

  • Armazenamento de objetos complexos.
    A solução para isto é cache. Existem diversas soluções para trabalhar com Cache (ASP.NET Data Cache, NCache, Memcached, Redis Cache), um destaque especial para o Redis Cache que se demonstrou uma solução muito eficiente, performática e fácil de implementar, inclusive existe recursos no Azure e AWS para utilização desta ferramenta para cache distribuído e etc.
    O recurso de Cache sempre esteve presente no ASP.NET, sua utilização requer um pouco mais de esforço de implementação do que no uso das sessions, porém convenhamos, programar é um exercício intelectual, pratique isto!

Outras soluções para considerar

Existem outras soluções a serem consideradas, algumas muito simples como Hidden Fields e QueryStrings, onde muitas vezes são o suficiente para resolver o problema.

Outra ótima alternativa no ASP.NET MVC é utilizar ViewData, ViewBag e TempData

Existe uma espécie de armazenamento local (muito maior que um Cookie) chamado WebStorage onde é possível trabalhar com sessionStorage e localStorage, é muito interessante conhecer esse recurso, recomendo a todos que pesquisem sobre o assunto.

Para finalizar…

Elimine a possibilidade de utilizar sessions em sua aplicação, a Web está cada vez mais moderna, escalável e responsiva e é importante tomar decisões que não nos façam andar na contra-mão da Web.

Eu me reuni com outros colegas para bater um papo sobre esse assunto, confira como foi o bate papo.

* Assine meu canal no Youtube 🙂

Vamos continuar com a troca de conhecimentos, utilize o formulário abaixo para postar sua opinião, crítica e lógico seu feedback (adoramos feedback 🙂 ).

Referência