Sessions persistantes avec Apache APISIX - Théorie

Nicolas Fränkel

Nicolas Fränkel

July 27, 2023

Technology

Les sessions persistantes, également connues sous le nom d'affinité de session, sont un mécanisme par lequel un composant de routage agissant comme une façade route toujours une requête vers le même nœud en amont sous-jacent. Dans cet article, je vais expliquer la raison derrière les sessions persistantes, les alternatives disponibles, et comment les implémenter via Apache APISIX.

Pourquoi les sessions persistantes ?

Les sessions persistantes sont devenues populaires lorsque nous stockions l'état sur le nœud en amont, et non dans la base de données. Je vais utiliser l'exemple d'une boutique en ligne simplifiée pour expliquer plus en détail.

Les fondations de base d'un petit site e-commerce peuvent se composer d'une application web et d'une base de données.

Architecture de base d'une application e-commerce

Si l'entreprise réussit, elle va croître, et vous devrez à un moment donné mettre à l'échelle cette architecture. Une fois que vous ne pouvez plus mettre à l'échelle verticalement (des machines plus puissantes), vous devez mettre à l'échelle horizontalement (plus de nœuds). Avec des nœuds d'application supplémentaires, vous aurez également besoin d'un mécanisme de répartition de charge devant les nœuds de l'application web pour distribuer la charge entre eux.

Architecture de répartition de charge pour des nœuds supplémentaires

Accéder à la base de données à chaque fois est une opération coûteuse. C'est acceptable pour les données qui sont rarement consultées. Cependant, nous voulons afficher le contenu du panier pour chaque requête. Plusieurs alternatives sont disponibles pour accélérer les choses. Si nous supposons que l'application web utilise le rendu côté serveur, la solution classique consiste à conserver les données liées au panier en mémoire sur le nœud de l'application web.

Cependant, si nous stockons le panier de l'utilisateur X sur le nœud 1, nous devons nous assurer que nous redirigeons chaque requête de l'utilisateur X vers le même nœud. Sinon, il aura l'impression d'avoir perdu le contenu de son panier. Les sessions persistantes, ou l'affinité de session, est le mécanisme qui route systématiquement le même utilisateur vers le même nœud.

Limitation des sessions persistantes

Avant d'aller plus loin, je dois expliquer une limitation importante des sessions persistantes. Si le nœud de l'application web qui stocke les données tombe en panne pour une raison quelconque, les données sont irrémédiablement perdues. Pour le scénario e-commerce ci-dessus, cela signifie que les utilisateurs perdront occasionnellement leur panier, ce qui est inacceptable d'un point de vue commercial.

Pour cette raison, les sessions persistantes doivent aller de pair avec la réplication de session : les données stockées sur un nœud doivent être copiées et maintenues synchronisées avec tous les autres nœuds.

Bien que la réplication de session existe dans toutes les piles technologiques, il n'y a pas de spécification associée. Je suis familier avec la JVM, voici donc quelques options :

  • Tomcat offre la réplication de session prête à l'emploi
  • Hazelcast propose une solution en mémoire clusterisée que vous pouvez intégrer à différents niveaux
  • Spring Session est une couche d'abstraction au-dessus de solutions spécifiques

Lorsque les données sont répliquées sur tous les nœuds (ou un cluster distant), vous pourriez penser que vous n'avez plus besoin de sessions persistantes. C'est vrai si l'on ne tient compte que de la disponibilité et non des performances. Il s'agit de la localité des données : récupérer les données sur le nœud actuel plutôt que depuis un autre endroit via le réseau est plus rapide.

Sessions persistantes sur Apache APISIX

Les sessions persistantes sont un must-have pour tout équilibreur de charge, proxy inverse et passerelle API qui se respecte. Cependant, je dois admettre que la documentation d'Apache APISIX manque d'un point d'entrée facile sur le sujet.

Apache APISIX lie une route à un upstream. Un upstream est composé d'un ou plusieurs nœuds. Lorsqu'une requête correspond à la route, Apache APISIX doit choisir parmi tous les nœuds disponibles pour transférer la requête. Par défaut, l'algorithme est le round-robin pondéré. Le round-robin utilise un nœud après l'autre, et après le dernier, revient au premier. Avec un round-robin pondéré, le poids affecte le nombre de requêtes qu'Apache APISIX transfère à un nœud avant de passer au suivant.

Cependant, d'autres algorithmes sont disponibles :

Le hachage cohérent permet de transférer vers le même nœud en fonction d'une certaine valeur : une variable NGINX, un en-tête HTTP, un cookie, etc.

Rappelez-vous que HTTP est un protocole sans état, donc les serveurs d'applications définissent un cookie sur la première réponse pour suivre l'utilisateur à travers les requêtes HTTP. C'est ce que nous appelons une "session". Nous devons connaître le nom du cookie de session sous-jacent. Différents serveurs d'applications attribuent différents cookies :

  • JSESSIONID pour les serveurs basés sur la JVM
  • PHPSESSID pour PHP
  • ASPSESSIONID pour ASP.Net
  • etc.

Je vais utiliser un Tomcat standard, donc le cookie de session est JSESSIONID. Par conséquent, la documentation d'Apache APISIX pour deux nœuds est la suivante :

routes:
  - uri: /*
    upstream:
      nodes:
        "tomcat1:8080": 1            #1
        "tomcat2:8080": 1            #1
      type: chash                    #2
      hash_on: cookie                #3
      key: cookie_JSESSIONID         #4
  1. Définir les nœuds en amont
  2. Choisir l'algorithme de hachage cohérent
  3. Hacher sur le cookie
  4. Définir sur quel cookie hacher

Conclusion

Dans cet article, nous avons détaillé les sessions persistantes, que vous devriez toujours utiliser la réplication de session avec les sessions persistantes, et comment implémenter les sessions persistantes sur Apache APISIX.

Pour aller plus loin :

Tags: