web-dev-qa-db-fra.com

Application avec état vs application sans état

J'ai appris sur les applications avec état vs non-état, mais je suis toujours un peu confus sur ce sujet.

Par exemple, supposons que j'ai une application qui s'exécute sur Node où les utilisateurs sont affectés à des salles aléatoires dès qu'ils se connectent via socket.io. Ce sont des salles de 4 et qui ne persistent en aucune façon, mais ils sont stockés dans une variable globale comme une carte de hachage. Je n'utilise pas de db (trop de requêtes) ni de redis (c'est trop cher).

Est-ce un exemple d'application avec état ou non?

9
heyal

Dans le contexte des applications Web, nous appelons le serveur avec état s'il maintient un état transitoire en mémoire, plutôt que de stocker des données en externe (par exemple dans une base de données).

Les applications avec état présentent un certain nombre de problèmes, par exemple:

  • vous ne pouvez pas avoir plus d'un serveur en cours d'exécution sans épingler des sessions à un serveur particulier
  • l'état est perdu au redémarrage du serveur

Il est donc recommandé d'éviter les états côté serveur (encore une fois: à moins qu'il ne soit stocké en externe dans une base de données).

Les backends d'application Web n'ont généralement pas besoin de stocker un état de session car ils peuvent utiliser REST: l'état est transféré entre le client et le serveur. Cet état est représenté par URL, cookies, corps HTTP, etc. Ceci est nécessaire car HTTP est un protocole sans état (sémantiquement, pas nécessairement dans ses fondements techniques).

Avec les sockets Web, ces principes se brisent un peu car le client maintient une session/connexion de longue durée avec le serveur - et cette connexion implique un état. Ceci est inévitable, mais vous contrôlez si et dans quelle mesure l'utilisation de websockets doit compromettre une conception de backend par ailleurs sans état.

  • Il est tout à fait correct de maintenir des structures de données en mémoire qui contrôlent quelle connexion est abonnée à quels événements.

  • Il est problématique que cette structure de données en mémoire soit la "source de vérité" pour ces informations.

    • Si les abonnements sont censés être transitoires, tout va bien.
    • Si vous souhaitez rétablir les mêmes abonnements lorsqu'un client se reconnecte, vous devez stocker cet état ailleurs. Par exemple côté serveur dans une base de données, ou côté client via les cookies ou LocalStorage.

En général, le maintien de l'état du serveur interne est correct lorsque l'une des conditions suivantes s'applique

  • l'état est stocké en externe
  • l'état n'est pas partagé entre les demandes
  • l'État n'est que l'acquisition d'une ressource coûteuse qui peut être réutilisée, par ex. connexions à la base de données
  • l'état est un cache pour une source de données faisant autorité, bien que cela pose des problèmes difficiles tels que l'invalidation du cache et la cohérence éventuelle
17
amon

Si vous stockez l'état sur le serveur qui est nécessaire pour traiter une demande entrante du client, le serveur est avec état. Dit autrement, il a déclaré qu'il stocke et doit accéder afin de traiter les demandes des clients. Ainsi, votre hashmap est state, donc votre serveur est stateful.

Maintenant, il y a très peu d'applications Web réelles qui font des choses riches qui ne sont pas du tout avec état. Après tout, si vous allez avoir une connexion utilisateur, puis traiter les demandes à la demande d'un client connecté, alors, par définition, vous stockez un état sur le serveur qui se rapporte à un client particulier et le serveur est avec état , même si ce n'est que pour les informations de connexion.

Donc, je ne serais pas trop accroché à ce qu'il y ait un état zéro sur le serveur. Ce qui importe, c'est combien il y a d'état sur le serveur, combien coûte (en termes de traitement, de stockage, etc.) le stockage et l'accès à cet état et pouvez-vous toujours faire évoluer votre application horizontalement avec cet état. Et, dans la mesure du possible, conservez l'état dans le client, pas sur le serveur. À titre d'exemple trivial, supposons que vous ayez une application cliente dotée d'un bouton "page suivante". Vous pouvez implémenter la "page suivante" avec un état côté client ou un état côté serveur.

Si vous aviez un état côté serveur pour la page actuelle du client, vous pouvez simplement envoyer une commande au serveur dont vous souhaitez afficher la page "suivante". Le serveur examine son état pour ce client, incrémente la page, puis renvoie les données de la page suivante.

Ou, vous pouvez stocker la page actuelle sur le client. Lorsque le client souhaite la page suivante, il prend son numéro de page actuel, l'incrémente d'une unité et fait une demande générique pour le numéro de page spécifique qu'il souhaite afficher ensuite.

Selon vous, laquelle de ces implémentations évolue mieux? Laquelle est plus simple à mettre en œuvre lorsque l'utilisateur ouvre un deuxième onglet affichant une page différente? Ce qui est plus simple à l'échelle horizontale. La réponse à toutes ces questions est celle qui ne stocke pas la page actuelle sur le serveur, mais la conserve dans le client et fait simplement des demandes génériques de page N au serveur. Le maintien de cet état côté client facilite la mise à l'échelle individuelle et horizontale et prend en charge plusieurs vues pour le même client.

6
jfriend00