Aplicativo com e sem estado [fechado]

9

Eu tenho aprendido sobre aplicativos stateful vs non stateful, mas ainda estou um pouco confuso sobre esse tópico.

Por exemplo, digamos que eu tenha um aplicativo em execução no Node, onde os usuários são atribuídos a salas aleatórias assim que se conectam por meio do socket.io. Estes são quartos de 4 e não são persistentes de forma alguma, mas são armazenados em uma variável global como um mapa de hash. Eu não estou usando um banco de dados (muitas consultas) nem redis (é muito caro).

Este é um exemplo de aplicativo com estado ou não?

heyal
fonte
5
Se fosse apátrida, não haveria nada para armazenar no hashmap.
candied_orange

Respostas:

17

No contexto de aplicativos da web, chamamos o servidor com estado se ele mantiver um estado transitório na memória , em vez de armazenar dados externamente (por exemplo, em um banco de dados).

Os aplicativos com estado têm vários problemas, por exemplo:

  • você não pode ter mais de um servidor em execução sem fixar sessões em um servidor específico
  • o estado é perdido quando o servidor é reiniciado

Portanto, é uma prática recomendada evitar o estado do servidor (novamente: a menos que esteja armazenado externamente em um banco de dados).

Os back-ends de aplicativos da Web geralmente não precisam armazenar nenhum estado da sessão porque eles podem usar os princípios REST: o estado é transferido entre o cliente e o servidor. Esse estado é representado por URLs, cookies, corpos HTTP e assim por diante. Isso é necessário porque o HTTP é um protocolo sem estado (semanticamente, não necessariamente em seus fundamentos técnicos).

Com os soquetes da Web, esses princípios quebram um pouco porque o cliente mantém uma sessão / conexão de longa duração com o servidor - e essa conexão envolve estado. Isso é inevitável, mas você controla se e em que grau o uso de websockets comprometerá um design de back-end sem estado.

  • É muito bom manter estruturas de dados na memória que controlam qual conexão é assinada e quais eventos.

  • É problemático se essa estrutura de dados na memória é a "fonte da verdade" para essas informações.

    • Se as assinaturas devem ser transitórias, está tudo bem.
    • Se você deseja restabelecer as mesmas assinaturas quando um cliente se reconectar, será necessário armazenar esse estado em outro lugar. Por exemplo, do lado do servidor em um banco de dados ou do lado do cliente, através de cookies ou LocalStorage.

Em geral, manter o estado interno do servidor é bom quando um dos seguintes itens se aplica

  • o estado é armazenado externamente
  • o estado não é compartilhado entre solicitações
  • o estado é apenas a aquisição de um recurso caro que pode ser reutilizado, por exemplo, conexões de banco de dados
  • o estado é um cache para alguma fonte de dados autorizada, embora isso cause problemas difíceis, como invalidação de cache e eventual consistência
amon
fonte
1
Eu não acho que estar na memória seja necessário, pois "transitório" aqui é mais um conceito do que uma implementação. Existem muitas implementações de sessão que usam banco de dados ou sistema de arquivos para armazenar dados da sessão, mas ainda não podemos chamá-lo sem estado.
tia
"Portanto, é uma prática recomendada evitar o estado do lado do servidor (novamente: a menos que seja armazenado externamente em um banco de dados)" - eu reconsideraria o termo "prática recomendada" aqui. Talvez haja situações em que a empresa prefere a conexão perdida do que a manutenção do estado, etc. Isso realmente depende dos prós e contras de cada caso.
Ron Klein
6

Se você estiver armazenando o estado no servidor necessário para processar uma solicitação de entrada do cliente, o servidor estará com estado. Dito de outra maneira, ele afirma que armazena e precisa acessar para processar solicitações de clientes. Portanto, seu hashmap é state e seu servidor é stateful.

Agora, existem muito poucos aplicativos da Web reais que fazem coisas ricas que não são de estado algum. Afinal, se você deseja ter um login de usuário e depois processar solicitações a pedido de um cliente conectado, então, por definição, você está armazenando o estado no servidor que pertence a um cliente específico e o servidor é estável , mesmo que seja apenas para as informações de login.

Portanto, eu não ficaria muito desconfortável com o estado zero no servidor. O que importa é quanto estado existe no servidor, qual o custo (em termos de processamento, armazenamento, etc ...) é armazenar e acessar esse estado e você ainda pode dimensionar seu aplicativo horizontalmente com esse estado. E, sempre que possível, mantenha o estado no cliente, não no servidor. Como um exemplo trivial, suponha que você tenha um aplicativo cliente com um botão "próxima página". Você pode implementar a "página seguinte" com o estado do lado do cliente ou do lado do servidor.

Se você tivesse o estado do lado do servidor para a página atual do cliente, basta enviar um comando ao servidor que gostaria de exibir na página "próxima". O servidor examinaria seu estado para esse cliente, incrementaria a página e retornaria os dados para a próxima página.

Ou você pode armazenar a página atual no cliente. Quando o cliente deseja a próxima página, ele pega seu número de página atual, incrementa-o em um e faz uma solicitação genérica para o número de página específico que deseja visualizar a seguir.

Qual dessas implementações você acha que escala melhor? O que é mais simples de implementar quando o usuário abre uma segunda guia exibindo uma página diferente? O que é mais simples de dimensionar horizontalmente. A resposta para todos é a que não armazena a página atual no servidor, mas a mantém no cliente e apenas faz solicitações genéricas da página N ao servidor. Manter esse estado no lado do cliente facilita o dimensionamento individual e horizontal e oferece suporte a várias visualizações para o mesmo cliente.

jfriend00
fonte