Stateless vs Stateful

Matheus Luis
6 min readApr 19, 2022

--

Em um post anterior, eu falei um pouco sobre a base comunicativa entre as entidades receptoras e emissoras que compõem a web. Lá vimos que essa comunicação é regrada através de normas conjuntas chamadas de Protocolos. A comunicação web também pode possuir estados, e quando digo ‘estado’ estou me referindo ao modo, posição ou condição de alguma fonte de informação em um determinado momento presente, ou seja, quais são “as condições de existência de xpto” no “agora”.

O estado de uma aplicação web é categorizado basicamente através de dois fatores referente à comunicação do cliente com o servidor:

  • O tempo de interação
  • Armazenamento informacional de interações anteriores

As “categorias” citadas acima, são chamadas de: Stateless e Stateful.

Stateless

A comunicação Stateless tem um tempo de interação curto e uma comunicação sem estado, ou seja, cada interação é tratada como inédita, de forma que as informações da interação anterior não sejam armazenadas. Resumidamente, uma interação não tem conhecimento da outra, mesmo que ambas sejam realizadas pelo mesmo cliente.

De cara, é uma brisa um tanto complexa de entender mas quando partimos para os exemplos práticos fica um pouco mais fácil. Bom, um ótimo exemplo de aplicações Stateless são as APIs RESTful, que exigem que cada requisição contenha todas as informações necessárias para o servidor conseguir processar aquele pedido como esperado, ou seja:

  1. Temos o Felipe
  2. Temos uma API em um determinado servidor web que recebe um CEP e devolve uma temperatura
  3. Felipe passa um CEP válido, juntamente com cabeçalho da requisição devidamente preenchido.
  4. A aplicação devolve o valor da temperatura para o Felipe
  5. Assim que Felipe recebe a resposta ele esbarra no Alt + F4 e fecha o seu API Client (ex: postman)
  6. Se Felipe ainda quiser saber qual a temperatura do CEP informado, ele precisa realizar uma nova requisição passando todos os parâmetros necessários novamente, dados do cabeçalho, DNS do servidor, endpoint correto juntamente com o valor do CEP e etc…

O servidor em si não tem conhecimento do que foi solicitado pelo cliente à um segundo atrás, as informações não são guardadas, se Felipe quisesse realizar uma nova requisição só passando o endereço correto e sem preencher o cabeçalho da requisição por exemplo, o servidor não iria processar essa solicitação com sucesso, já que o servidor não sabe que Felipe tinha informado esses dados corretamente em um passado muito recente.

Poder tratar de formar singular cada requisição feita ao servidor parece ser desvantagem logo de cara, porque poxa… Toda vez que o usuário precisar realizar uma nova requisição ele precisa informar todos os dados novamente, e se for um endpoint que possui um cabeçalho com 10 propriedades que precisam ser obrigatoriamente preenchidas ? Muita calma, geralmente essa regra é abstraída para o usuário final, e muitas das vezes também, essas aplicações são microserviços que funcionam em conjunto por debaixo dos panos, ou seja dentro da arquitetura de uma aplicação principal (ou core), não sendo acessada diretamente pelo usuário.

Uma aplicação Stateless tem o objetivo de ser performática e facilmente escalável, visando o constante pedido/reposta de forma dinâmica e sem depender de sessões. Permitindo que um usuário x realize n requisições, sendo cada uma dessas requisições tratadas em uma instância diferente do servidor. Exemplo:

  1. Temos uma aplicação x que é hospedada na nuvem
  2. Os servidores estão de pé em containers nessa mesma nuvem, chamamos esses containers de instâncias
  3. Esse servidor tem uma política que: sempre que uma instância chega no limite de uso dos seus recurso (ex: memória) é criada então uma nova instância (auto scaling).
  4. Vamos supor que o Felipe precisou fazer 40 requisições iguais nesses mesmo servidor
  5. Supondo que quando chegou na 39ª requisição, a instância no qual estava sendo realizada as requisições acabou topando os seus recursos

Ao invés do Felipe ficar aguardando a instância liberar recursos para que sua última requisição seja processada pelo servidor, em um intervalo de milésimo de segundos é instanciado um novo container para atender de prontidão o pedido do Felipe.

Stateful

Agora que compreendemos a motivação e objetivo da comunicação sem estado, fica até mais fácil entender o conceito de Stateful, no grosso do grosso é basicamente o inverso do que é uma comunicação Stateless. Nesse modelo o tempo de interação é mais longo e as informações das interações anteriores são armazenadas, servindo para montar um estado atual sempre que o cliente realizar uma nova interação dentro de um intervalo de tempo delimitado.

Acho que o exemplo mais usado, mais comum e mais fácil de entender é: “Um carrinho de produtos em um site de compra”, ou, “Serviço de banco virtual”. Imagina se cada vez que o usuário recarregasse a página ele tivesse que colocar todos os seus 90 produtos no carrinho novamente ? Seria totalmente maluquice, né ?

O comportamento de uma aplicação Stateful gira em torno disso: Guardar o estado da interação anterior de forma que isso impacte diretamente nas diferentes requisições subsequentes.

Os estados da interação são aglomerados e organizados em espaços chamados de Sessões. As sessões armazenam transações realizadas anteriormente e utilizam as informações dessas transações antigas para ‘montar’ o estado atual. Portanto se uma comunicação for repentinamente encerrada, o servidor consegue recuperar através da sessão qual era o estado da transação xyz do cliente Fulano antes da comunicação ser interrompida, montando o estado da interação atual com base nessas informações anteriores.

Mas po, se a gente for levar essa lógica ao pé da letra, então meu pai que montou um carrinho com produtos no mercado livre em 2012 tem o carrinho no seu mesmo estado até hoje ? Diretamente a resposta é: “não, cowboy”. Para sanar esse problema, as sessões possuem uma espécie de vida útil ou prazo, você já deve ter visto em alguma lugar alguma mensagem do tipo: “A sessão foi expirada, faça o login novamente para acessar a sua conta”.

Para o servidor saber qual sessão pertence a quem, geralmente os navegadores armazenam uma espécie de chave ou identificador de sessão, e sempre que o usuário realiza um novo pedido no mesmo servidor, o navegador informa qual o identificador da sessão daquele usuário para o servidor, e então o servidor responde: “Opa, essa sessão existe, toma aqui a sua transação exatamente do mesmo estado que você deixou”, ou em caso de expiração: “Xiii, essa sessão aqui morreu já, se identifique de novo ai”.

É tipo comprar um ingresso para um show de rock, sair do show para ir comer uma pizza, voltar duas horas depois e o segurança falar: “Epa amigo, quem é você ? ”, daí é necessário mostrar novamente o seu passe para ter acesso aquele show… Se esse mesmo camarada, saísse e voltasse em 5 minutos no máximo, talvez aquele mesmo segurança ainda se lembrasse dele e nem fosse necessário se identificar novamente. É mais ou menos assim que as sessões se comportam.

Essa é a vantagem do Stateful, tornar a comunicação mais intuitiva para o usuário mantendo-o no controle da interação durante o tempo de vida da sua sessão. Como o Stateful é totalmente o oposto da comunicação Stateless, a principal desvantagem está no custo dos recursos do servidor que são necessários para manter essas sessões de pé, por isso é crucial que aplicações nesse modelo tratem as sessões de forma eficiente para que não haja uma deterioração eminente do desempenho do servidor, em por exemplo dias de pico, onde temos milhares de sessões ativas.

Referências

--

--

Matheus Luis

Engenheiro de Software na Stone Co. | Entusiasta linux | Microsserviços | .NET | New Relic