Faible latence, mise en file d'attente de messages à grande échelle
je suis en train de repenser un peu les jeux multijoueurs à grande échelle à L'ère des applications Facebook et du cloud computing.
supposez que je construise quelque chose en plus des protocoles ouverts existants, et je veux servir 1.000.000 de joueurs simultanés, juste pour cerner le problème.
supposons que chaque joueur dispose d'une file d'attente de messages entrants (pour chat et autres), et en moyenne une file d'attente de messages entrants supplémentaire (Guildes, zones, instances, enchères, ...) nous avons donc 2 millions de files d'attente. Un joueur écoutera 1 à 10 files d'attente à la fois. Chaque file d'attente aura en moyenne un message par seconde, mais certaines Files d'attente auront un taux beaucoup plus élevé et un plus grand nombre d'auditeurs (par exemple, une file d'attente "entity location" pour une instance de niveau). Supposons qu'il n'y ait pas plus de 100 millisecondes de latence de la file d'attente du système, ce qui est acceptable pour les jeux légèrement orientés vers l'action (mais pas pour les jeux comme Quake ou Unreal Tournament).
D'autres systèmes, Je sais que servir 10.000 utilisateurs sur un 1U simple ou la boîte de lame est une attente raisonnable (en supposant qu'il n'y a rien d'autre coûteux sur, comme la simulation physique ou autre).
ainsi, avec un système de cluster crossbar, où les clients se connectent aux passerelles de connexion, qui à leur tour se connectent aux serveurs de file d'attente de messages, nous aurions 10.000 utilisateurs par passerelle avec 100 machines de passerelle, et 20.000 Files d'attente par serveur de file d'attente avec 100 machines de file d'attente. Encore une fois, juste pour l'établissement de la portée générale. Le nombre de connexions sur chaque machine MQ être minuscule: environ 100, pour parler à chacune des portes. Le nombre de connexions sur les passerelles serait beaucoup plus élevé: 10 100 pour les clients + connexions à tous les serveurs de file d'attente. (Sur le dessus de cela, ajouter un peu de connexions pour le monde du jeu de simulation de serveurs ou autres joyeusetés, mais j'essaie de la garder que de les séparer pour l'instant)
si Je ne voulais pas construire cela à partir de zéro, je devrais utiliser une infrastructure de messagerie et/ou de file d'attente qui existe. Les deux protocoles ouverts que je peux trouver sont AMQP et XMPP. L'utilisation prévue de XMPP est un peu plus proche de ce dont ce système de jeu aurait besoin, mais la charge est assez visible (XML, plus les données de présence verbeuses, plus divers autres canaux qui doivent être construits sur le dessus). Le modèle de données réel D'AMQP est plus proche de ce que je décris ci-dessus, mais tous les utilisateurs semblent être de grandes entreprises de type entreprise, et les charges de travail semblent être liées au flux de travail, pas à la mise à jour du jeu en temps réel.
est-ce que quelqu'un a une expérience de jour avec ces technologies, ou implémentations de celles-ci, que vous pouvez partager?
5 réponses
@MSalters
Re 'message de la file d'attente':
L'opération par défaut de RabbitMQ est exactement ce que vous décrivez: PubSub transitoire. Mais avec TCP au lieu de UDP.
si vous voulez une livraison finale garantie et d'autres fonctionnalités de persistance et de récupération, alors vous pouvez l'avoir aussi - c'est une option. C'est le but de RabbitMQ et AMQP -- vous pouvez avoir beaucoup de comportements avec un seul système de messagerie.
Le modèle que vous décrivez est l' Comportement par défaut, qui est transitoire, "fire and forget", et l'acheminement des messages à l'endroit où se trouvent les destinataires. Les gens utilisent RabbitMQ pour faire des découvertes multicast sur EC2 pour cette raison. Vous pouvez obtenir des comportements de type UDP sur unicast TCP pubsub. Pas mal, non?
Re UDP:
Je ne suis pas sûr que UDP serait utile ici. Si vous éteignez Nagling, la latence de roundtrip à message unique RabbitMQ (client-courtier-client) a été mesurée entre 250 et 300 microsecondes. Voir ici pour un la comparaison avec Windows latence (qui était un peu plus élevé) http://old.nabble.com/High%28er%29-latency-with-1.5.1--p21663105.html
Je ne peux pas penser à beaucoup de jeux multijoueurs qui ont besoin d'une latence inférieure à 300 microsecondes. Vous pouvez descendre en dessous de 300us avec TCP. TCP windowing plus cher que l'UDP brut, mais si vous utilisez UDP pour aller plus vite, et Ajouter un custom loss-recovery ou seqno/ack/resend manager alors qui peut vous ralentir à nouveau. Tout dépend de votre cas d'utilisation. Si vous avez vraiment vraiment besoin d'utiliser UDP et les acks paresseux et ainsi de suite, alors vous pouvez enlever le TCP de RabbitMQ et probablement tirer cela.
j'espère que cela aidera à clarifier pourquoi J'ai recommandé RabbitMQ pour le cas D'utilisation de Jon.
je construis un tel système maintenant, en fait.
j'ai fait une bonne évaluation de plusieurs qm, dont RabbitMQ, Qpid et ZeroMQ. La latence et le débit de l'une ou l'autre de ces solutions sont plus que suffisants pour ce type d'application. Ce qui n'est pas bon, cependant, est le temps de création de la file d'attente au milieu d'un demi-million de files d'attente ou plus. Qpid en particulier se dégrade assez sévèrement après quelques milliers de files d'attente. Pour contourner ce problème, vous devez créer votre propres mécanismes de routage (moins de files d'attente totales, et les consommateurs sur ces Files d'attente reçoivent des messages qui ne les intéressent pas).
Mon système actuel sera probablement utiliser ZeroMQ, mais de façon assez limitée, à l'intérieur le cluster. Les connexions des clients sont gérées avec un sim personnalisé. le démon que j'ai construit en utilisant libev et qui est entièrement monofiltre (et montre une très bonne mise à l'échelle-il devrait être capable de gérer 50 000 connexions sur une boîte sans aucune les problèmes ... notre sim. tique taux est assez faible, cependant, et il n'y a pas de physique).
XML (et donc XMPP) n'est pas du tout adapté à cela, car vous allez peg le traitement CPU XML bien avant que vous deveniez lié sur l'e/s, ce qui n'est pas ce que vous voulez. Nous utilisons des tampons de protocole Google, en ce moment, et ceux-ci semblent bien adaptés à nos besoins particuliers. Nous utilisons également TCP pour les connexions client. J'ai eu l'expérience d'utiliser à la fois UDP et TCP pour cela dans le passé, et comme indiqué par d'autres, UDP a un certain avantage, mais il est légèrement plus difficile de travailler avec.
J'espère que lorsque nous serons un peu plus près du lancement, je pourrai partager plus de détails.
Jon, cela ressemble à un cas d'utilisation idéal pour AMQP et RabbitMQ.
Je ne sais pas pourquoi vous dites que les utilisateurs D'AMQP sont tous de grandes entreprises. Plus de la moitié de nos clients sont dans l'espace " web " allant des grandes entreprises aux petites. De nombreux jeux, systèmes de Paris, systèmes de chat, systèmes de type twittery, et infras de cloud computing ont été construits à partir de RabbitMQ. Il y a même des applications de téléphonie mobile. Les flux de travail sont juste l'un des nombreux à utiliser cas.
Nous essayons de garder une trace de ce qui se passe ici:
http://www.rabbitmq.com/how.html (assurez-vous de cliquer à travers pour les listes de cas d'utilisation sur del.icio.nous aussi!)
s'il vous Plaît jeter un oeil. Nous sommes là pour vous aider. N'hésitez pas à nous envoyer un courriel à info@rabbitmq.com ou me frapper sur twitter (@monadic).
FWIW, pour les cas où les résultats intermédiaires ne sont pas importants (comme les informations de positionnement) Qpid a une "dernière file d'attente de valeur" qui ne peut fournir que la valeur la plus récente à un abonné.
mon expérience était avec une alternative non-ouverte, BizTalk. La leçon la plus douloureuse que nous avons apprise est que ces systèmes complexes ne sont pas rapides. Et comme vous l'avez compris à partir des exigences en matière de matériel, cela se traduit directement par des coûts importants.
pour cette raison, ne vous approchez même pas de XML pour les interfaces de base. Votre cluster de serveurs analysera 2 millions de messages par seconde. Cela pourrait facilement être 2-20 GB / sec de XML! Cependant, la plupart des messages seront pour quelques Files d'attente, tandis que la plupart les files d'attente sont en fait peu fréquentées.
par conséquent, concevez votre architecture de façon à ce qu'il soit facile de commencer avec des serveurs de file D'attente COTS et ensuite déplacer chaque file d'attente (type) vers un serveur de file d'attente personnalisé lorsqu'un goulot d'étranglement est identifié.
aussi, pour des raisons similaires, ne présumez pas qu'une architecture de file d'attente de messages est la meilleure pour tous les besoins de communication de votre application. Prenez votre "entité emplacement dans une instance" par exemple. C'est un cas classique où vous ne pas vous voulez livraison de messages garantie. La raison pour laquelle vous devez partager cette information est parce qu'elle change tout le temps. Donc, si un message est perdu, vous ne voulez pas passer de temps à le récupérer. Vous n'enverriez que l'ancienne localisation de l'entité affectée. Au lieu de cela, vous voudriez envoyer le localisation de cette entité. Du point de vue technologique, cela signifie que vous voulez UDP, pas TCP et un mécanisme personnalisé de récupération des pertes.