web-dev-qa-db-fra.com

Équilibreur de charge d'application AWS et socket.io

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?

12
user2924127

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.

enter image description hereenter image description here


Alternative utilisant le routage ALB sans adaptateur socket.io.

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.

Étape 1:

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.

Étape 2:

Créez N groupes cibles (N étant le nombre d'instances dont vous disposez actuellement)

Image

Étape 3:

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

enter image description here

Étape 4:

Modifier les règles cibles ALB

Équilibreurs de charge> Votre ALB> Écouteurs> Afficher/modifier les règles

enter image description here

Étape 5:

Créez une règle par groupe cible/instance avec les paramètres suivants:

  • IF> Chemin: /iX/room/*
  • ALORS> transmettre à: instanceX

enter image description here


enter image description here

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 2

etc.

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.

22