47 votes

Sessions PHP dans un cluster d'équilibrage de charge - comment ?

OK, alors j'ai ce scénario totalement rare et unique d'un site PHP à charge équilibrée. Le problème, c'est qu'il n'était pas équilibré en charge avant. Maintenant nous commençons à avoir des problèmes...

Actuellement, le seul problème concerne les sessions PHP. Naturellement, personne n'a pensé à ce problème au départ et la configuration des sessions PHP a été laissée à ses valeurs par défaut. Ainsi, les deux serveurs ont leurs propres fichiers de session, et malheur à l'utilisateur qui voit sa prochaine requête envoyée à l'autre serveur, parce que celui-ci n'a pas la session qu'il a créée sur le premier.

J'ai lu le manuel de PHP pour savoir comment résoudre cette situation. J'y ai trouvé la belle fonction de session_set_save_handler() . (Et, par coïncidence, ce sujet sur SO) Neat. Sauf que je vais devoir appeler cette fonction dans toutes les pages du site. Et les développeurs des futures pages devront se souvenir de l'appeler tout le temps également. C'est un peu maladroit, sans compter que cela viole probablement une douzaine de bonnes pratiques de codage. Ce serait beaucoup plus agréable si je pouvais simplement retourner une option de configuration globale et Voilà - les sessions sont toutes magiquement stockées dans une base de données ou un cache mémoire ou quelque chose comme ça.

Avez-vous des idées sur la manière de procéder ?


Ajouté : Pour clarifier - je m'attends à ce que ce soit une situation standard avec une solution standard. Pour information, je dispose d'une base de données MySQL. Il doit bien exister un code prêt à l'emploi pour résoudre ce problème ? Je peux, bien sûr, écrire mon propre système de sauvegarde de session et auto_prepend option signalée par Greg semble prometteur - mais cela reviendrait à réinventer la roue :P

Ajouté 2 : L'équilibrage de la charge est basé sur le DNS. Je ne suis pas sûr de savoir comment cela fonctionne, mais je suppose que cela devrait être quelque chose comme este .

Ajouté 3 : OK, je vois qu'une solution consiste à utiliser auto_prepend pour insérer un appel à session_set_save_handler() dans chaque script et écrire mon propre persister DB, peut-être en jetant des appels à memcached pour de meilleures performances. C'est normal.

Existe-t-il également un moyen d'éviter de coder tout cela moi-même ? Comme un plugin PHP célèbre et bien testé ?

Ajouté beaucoup, beaucoup plus tard : C'est ce que j'ai fait à la fin : Comment implémenter correctement un persister de session personnalisé en PHP + MySQL ?

De plus, j'ai simplement inclus manuellement le gestionnaire de session dans toutes les pages.

33voto

BeowulfOF Points 3737

Vous pouvez configurer PHP pour qu'il gère les sessions dans la base de données, afin que tous vos serveurs partagent les mêmes informations de session, car tous les serveurs utilisent la même base de données pour cela.

Un bon tutoriel pour cela peut être trouvé ici .

20voto

Doug Johnson Points 128

La façon dont nous gérons cela est à travers memcached. Il suffit de modifier le php.ini de la manière suivante :

session.save_handler = memcache
session.save_path = "tcp://path.to.memcached.server:11211"

Nous utilisons AWS ElastiCache, donc le chemin du serveur est un domaine, mais je suis sûr que ce serait similaire pour le memcached local aussi.

Cette méthode ne nécessite aucune modification du code de l'application.

8voto

iAn Points 3090

Vous n'avez pas mentionné la technologie que vous utilisez pour l'équilibrage de charge (logiciel, matériel, etc.) ; mais dans tous les cas, la solution à votre problème est d'employer des "sessions collantes" sur l'équilibreur de charge.

En résumé, cela signifie qu'à la première demande d'un "nouveau" visiteur, un serveur spécifique du cluster lui est attribué : toutes les demandes futures pendant la durée de sa session sont alors dirigées vers ce serveur. En pratique, cela signifie que les applications écrites pour fonctionner sur un seul serveur peuvent être étendues à un environnement équilibré avec zéro ou peu de changements de code.

Si vous utilisez un équilibreur matériel, tel qu'un dispositif Radware, les sessions collantes sont configurées dans le cadre de la configuration du cluster. Les dispositifs matériels vous offrent généralement un contrôle plus fin : par exemple, le serveur auquel un nouvel utilisateur est affecté (il peut vérifier l'état de santé, etc. et choisir le serveur le plus sain / le moins utilisé), et un meilleur contrôle de ce qui se passe lorsqu'un serveur tombe en panne et quitte le cluster. L'inconvénient des équilibreurs matériels est leur coût, mais ils en valent la peine, selon moi.

Quant aux équilibreurs logiciels, tout dépend de ce que vous utilisez. Pour Apache, il y a la propriété stickysession sur mod_proxy - et de nombreux articles via google pour faire fonctionner cela avec la session php ( par exemple )


Edit : D'après d'autres commentaires postés après la question originale, il semble que votre "équilibrage" soit effectué via le DNS Round Robin, donc ce qui précède ne s'applique probablement pas. Je vais m'abstenir de commenter davantage et de lancer une flamme contre les DNS à la ronde.

4voto

Greg Points 132247

La chose la plus simple à faire est de configurer votre équilibreur de charge pour qu'il envoie toujours la même session au même serveur.

Si vous voulez toujours utiliser session_set_save_handler alors peut-être jeter un coup d'oeil à auto_prepend.

2voto

PaulJWilliams Points 11641

Lorsque nous avons eu cette situation, nous avons implémenté du code qui vit dans un en-tête commun.

Essentiellement, pour chaque page, nous vérifions si nous connaissons l'ID de la session. Si ce n'est pas le cas, nous vérifions si nous nous trouvons dans la situation que vous décrivez, en vérifiant si nous avons stocké des données de session dans la base de données, sinon nous démarrons une nouvelle session.

Évidemment, cela exige que toutes les données pertinentes soient copiées dans la base de données, mais si vous encapsulez vos données de session dans une classe distincte, cela fonctionne bien.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X