J'ai une salle de chat socket.io en cours d'exécution dont le trafic devient plus important car nous fonctionnons sur une machine. Nous avons exécuté des tests de performances à l'aide de la bibliothèque ws pour les sockets et ils fonctionnent beaucoup mieux, ce qui utiliserait mieux notre matériel. Cela entraînerait cependant un coût de réécriture de notre application.
Notre application socket.io permet aux utilisateurs de créer des salles de discussion privées qui sont implémentées à l'aide d'espaces de noms. Par exemple
localhost:8080/room/1
localhost:8080/room/2
localhost:8080/room/3
Lorsque tout est dans une seule instance, c'est assez facile, mais maintenant nous cherchons à étendre cette capacité à plusieurs nœuds.
Nous exécutons cette instance dans le cloud d'Amazon. Auparavant, il semblait que la mise à l'échelle des Websockets était un problème avec les ELB. Nous avons remarqué qu'Amazon prend désormais en charge et l'équilibreur de charge d'application qui prend en charge les websockets. Cela semble génial, mais après avoir lu la documentation, je dois admettre que je ne sais pas vraiment ce que cela signifie. Si j'utilise socket.io avec des milliers d'espaces de noms, dois-je simplement mettre des instances derrière cet ALB et tout fonctionnera? Mes principales questions sont les suivantes:
Si x nombre d'utilisateurs rejoignent un espace de noms, l'ALB redirigera-t-il automatiquement mes messages vers et depuis les utilisateurs appropriés? Supposons donc que 5 instances Vanilla socket.io soient exécutées derrière l'ALB. L'utilisateur 1 crée un espace de noms. Quelques heures plus tard, l'utilisateur 99999 arrive et veut rejoindre cet espace de noms, devra-t-il y avoir du code supplémentaire écrit pour cela ou l'alb redirigera-t-il tout où il devrait aller? Il en va de même pour l'envoi et la réception de messages?
Alors qu'ALB équilibrera correctement les utilisateurs, vous devrez adapter un peu votre code car les utilisateurs qui ont rejoint une salle spécifique seront dispersés sur différents serveurs.
Dans leur documentation socket.io fournit un moyen de le faire:
Maintenant que vous disposez de plusieurs nœuds Socket.IO acceptant les connexions, si vous souhaitez diffuser des événements à tout le monde (ou même à tout le monde dans une certaine salle), vous aurez besoin d'un moyen de transmettre des messages entre les processus ou les ordinateurs.
L'interface en charge du routage des messages est ce que nous appelons l'adaptateur. Vous pouvez implémenter le vôtre au-dessus de l'adaptateur socket.io (en héritant de celui-ci) ou vous pouvez utiliser celui que nous fournissons au-dessus de Redis: socket.io-redis:
var io = require('socket.io')(3000);
var redis = require('socket.io-redis');
io.adapter(redis({ Host: 'localhost', port: 6379 }));
Configuration ALB
Je recommanderais d'activer la session persistante dans votre ALB, sinon la prise de contact socket.io échouera lors de l'utilisation d'un transport non Websocket, tel qu'un long interrogation, car La tâche d'établissement de liaison à l'aide de ce transport nécessite plusieurs demandes, et vous devez exécuter toutes ces demandes sur le même serveur.
Si je voulais éviter d'avoir une base de données redis. Par exemple, si mes salles sont créées par des utilisateurs, si l'utilisateurA crée une salle sur l'instance 4, si un autre utilisateur veut rejoindre cette salle, comment sauraient-ils à quelle instance il se trouve? Aurais-je besoin de l'adaptateur ici aussi?
Le but de cette alternative est d'affecter chaque salle à une instance EC2 spécifique. Nous allons y parvenir en utilisant ALB Routing
N pièces> 1 instance.
Vous devrez changer l'URL de votre chambre en quelque chose comme:
/i1/room/550
/i1/room/20
/i2/room/5
/i5/room/492
étant:
/{instance-number}/room/{room-id}
Cela est nécessaire pour qu'ALB puisse router chaque salle vers une instance spécifique.
Créez N groupes cibles (N étant le nombre d'instances dont vous disposez actuellement)
Enregistrer chaque instance dans chaque groupe cible
Groupes cibles> Groupe cible Instance X> onglet Cible> Modifier> Choisir l'instance X> ajouter à enregistré
Target group X > EC2 Instance X
Target group Y > EC2 Instance Y
Modifier les règles cibles ALB
Équilibreurs de charge> Votre ALB> Écouteurs> Afficher/modifier les règles
Créez une règle par groupe cible/instance avec les paramètres suivants:
/iX/room/*
instanceX
Une fois que vous avez cette configuration lorsque vous entrez:
/i1/room/550
vous utiliserez l'instance EC2 1./i2/room/200
utilisera l'EC2 Instance 2etc.
Maintenant, vous devrez créer votre propre logique afin d'équilibrer les pièces dans vos instances. Vous ne voulez pas qu'une instance héberge presque tous les groupes.
Je recommande la première approche car elle peut être mise à l'échelle facilement.