Aplicación con estado frente a no con estado [cerrado]

9

He estado aprendiendo sobre aplicaciones con estado frente a aplicaciones con estado, pero todavía estoy un poco confundido sobre este tema.

Por ejemplo, supongamos que tengo una aplicación ejecutándose en Node donde los usuarios son asignados a salas aleatorias tan pronto como se conectan a través de socket.io. Estas son habitaciones de 4 y no son persistentes de ninguna manera, pero se almacenan en una variable global como un mapa hash. No estoy usando un db (demasiadas consultas) ni redis (es demasiado caro).

¿Es este un ejemplo de una aplicación con estado o no?

heyal
fuente
55
Si no tuviera estado, no habría nada que almacenar en el hashmap.
candied_orange

Respuestas:

17

En el contexto de las aplicaciones web, llamamos al servidor con estado si mantiene un estado transitorio en la memoria , en lugar de almacenar cualquier información externamente (por ejemplo, en una base de datos).

Las aplicaciones con estado tienen varios problemas, por ejemplo:

  • no puede tener más de un servidor ejecutándose sin anclar sesiones a un servidor en particular
  • el estado se pierde cuando se reinicia el servidor

Por lo tanto, es una buena práctica evitar el estado del lado del servidor (nuevamente: a menos que se almacene externamente en una base de datos).

Los backends de aplicaciones web generalmente no necesitan almacenar ningún estado de sesión porque pueden usar los principios REST: el estado se transfiere entre el cliente y el servidor. Este estado está representado por URL, cookies, cuerpos HTTP, etc. Esto es necesario porque HTTP es un protocolo sin estado (semánticamente, no necesariamente en sus bases técnicas).

Con los sockets web, estos principios se rompen un poco porque el cliente mantiene una sesión / conexión de larga duración con el servidor, y esa conexión implica un estado. Esto es inevitable, pero usted controla si y en qué medida el uso de websockets comprometerá un diseño backend sin estado.

  • Está totalmente bien mantener estructuras de datos en memoria que controlen qué conexión está suscrita a qué eventos.

  • Es problemático si esa estructura de datos en memoria es la "fuente de verdad" para esa información.

    • Si se supone que las suscripciones son transitorias, todo está bien.
    • Si desea restablecer las mismas suscripciones cuando un cliente se vuelve a conectar, debe almacenar este estado en otro lugar. Por ejemplo, del lado del servidor en una base de datos, o del lado del cliente a través de cookies o LocalStorage.

En general, mantener el estado interno del servidor está bien cuando se aplica uno de los siguientes

  • el estado se almacena externamente
  • el estado no se comparte entre solicitudes
  • el estado es solo la adquisición de un recurso costoso que puede reutilizarse, por ejemplo, conexiones de bases de datos
  • el estado es un caché para alguna fuente de datos autorizada, aunque esto genera problemas difíciles como la invalidación del caché y la consistencia eventual
amon
fuente
1
No creo que sea necesario estar en la memoria, ya que "transitorio" aquí se parece más a un concepto que a la implementación. Hay muchas implementaciones de sesión que usan una base de datos o un sistema de archivos para almacenar datos de la sesión, pero aún no podemos llamarlo sin estado.
tia
"Por lo tanto, es una buena práctica evitar el estado del lado del servidor (de nuevo: a menos que esté almacenado externamente en una base de datos)", reconsideraría el término "mejor práctica" aquí. Tal vez hay situaciones en las que la empresa prefiere la conexión perdida sobre el costo de mantener el estado, etc. Realmente depende de los pros y los contras por caso.
Ron Klein
6

Si está almacenando el estado en el servidor que se necesita para procesar una solicitud entrante del cliente, entonces el servidor tiene estado. Dicho de otra manera, ha declarado que almacena y necesita acceder para procesar las solicitudes de los clientes. Entonces, su hashmap es estado, por lo que su servidor tiene estado.

Ahora, hay muy pocas aplicaciones web reales que hagan cosas ricas que no tengan estado en absoluto. Después de todo, si va a tener un inicio de sesión de usuario y luego procesar solicitudes a instancias de un cliente conectado, entonces, por definición, está almacenando el estado en el servidor que pertenece a un cliente en particular y el servidor tiene estado , aunque solo sea para la información de inicio de sesión.

Por lo tanto, no me obsesionaría demasiado con que haya un estado cero en el servidor. Lo que importa es cuánto estado hay en el servidor, qué tan costoso (en términos de procesamiento, almacenamiento, etc.) es almacenar y acceder a este estado y aún puede escalar su aplicación horizontalmente con este estado. Y, siempre que sea práctico, mantenga el estado en el cliente, no en el servidor. Como ejemplo trivial, suponga que tiene una aplicación cliente que tiene un botón de "página siguiente". Puede implementar la "página siguiente" con el estado del lado del cliente o del lado del servidor.

Si tenía el estado del lado del servidor para la página actual del cliente, podría enviar un comando al servidor que le gustaría ver la página "siguiente". El servidor miraría su estado para ese cliente, incrementaría la página y luego devolvería los datos para la página siguiente.

O bien, puede almacenar la página actual en el cliente. Cuando el cliente desea la siguiente página, toma su número de página actual, la incrementa en uno y realiza una solicitud genérica para el número de página específico que desea ver a continuación.

¿Cuál de estas implementaciones crees que escala mejor? ¿Qué es más sencillo de implementar cuando el usuario abre una segunda pestaña para ver una página diferente? Lo cual es más sencillo de escalar horizontalmente. La respuesta a todas esas preguntas es la que no almacena la página actual en el servidor, sino que la mantiene en el cliente y solo realiza solicitudes genéricas para la página N al servidor. Mantener ese estado del lado del cliente hace que sea más fácil escalar individualmente y horizontalmente y admite múltiples vistas para el mismo cliente.

jfriend00
fuente