41 votes

Thread Java par modèle de connexion vs NIO

Est le non-blocage de Java NIO encore plus lent que votre standard thread par connexion socket asynchrones?

En outre, si vous deviez utiliser un thread par connexion, serait-il vous suffit de créer de nouveaux threads ou vous utilisez un très grand pool de threads?

Je suis en train d'écrire un MMORPG serveur en Java, devrait être en mesure à l'échelle de 10000 clients facilement, étant donné assez puissant matériel, bien que le montant maximal de clients est de 24000 (qui je crois est impossible à atteindre pour le thread par connexion de modèle en raison de 15000 limite de thread en Java). D'un enfant de trois ans article, j'ai entendu dire que le blocage de IO avec un thread par connexion modèle était encore de 25% plus rapide que NIO (à savoir, le présent document http://www.mailinator.com/tymaPaulMultithreaded.pdf), mais peut même encore être réalisé à ce jour? Java a beaucoup changé depuis, et j'ai entendu dire que les résultats sont contestables lors de la comparaison des scénarios de vie réelle parce que la machine virtuelle utilisée n'a pas été Java de Sun. Aussi, parce que c'est un MMORPG serveur avec de nombreux simultanée utilisateurs en interaction les uns avec les autres, l'utilisation de la synchronisation et de la sécurité des threads pratiques baisse de la performance au point où un seul thread NIO sélecteur de servir de 10000 clients sera plus rapide? (tout le travail n'a pas forcément besoin d'être traitées sur le fil avec le sélecteur, il peut être traité sur les threads de travail, comme la façon dont MINA/Netty œuvres).

Merci!

23voto

irreputable Points 25577

NIO avantages doivent être pris avec un grain de sel.

Dans un serveur HTTP, la plupart des connexions sont les connexions persistantes, ils sont en veille la plupart du temps. Ce serait un gaspillage de ressources de pré-allouer un thread pour chaque.

Pour les MMORPG, les choses sont très différentes. Je suppose que les connexions sont constamment occupée à recevoir des instructions des utilisateurs et de l'envoi des dernières de l'état du système pour les utilisateurs. Un thread est nécessaire la plupart du temps, une connexion.

Si vous utilisez NIO, vous devrez constamment ré-allouer un fil de connexion. Il peut être une solution insuffisante, pour le fixe simple thread par connexion de la solution.

Par défaut la taille de la pile est assez grand, (1/4 de MO?) c'est la principale raison pourquoi il ne peut être limité que les threads. Essayez de le réduire et de voir si votre système peut prendre en charge plus.

Toutefois, si votre jeu est en effet très "occupé", c'est votre CPU que vous avez besoin de s'inquiéter le plus. NIO ou pas, il est vraiment difficile de gérer des milliers de hyper active joueurs sur une machine.

13voto

Jay Points 2003

Il y a en fait 3 solutions:

  1. Plusieurs threads
  2. Un thread et NIO
  3. Les deux solutions 1 et 2 à la même le temps

La meilleure chose à faire pour la performance est d'avoir un petit, nombre limité de fils et de réseau multiplex événements sur ces sujets avec NIO que des nouveaux messages arrivent sur le réseau.


À l'aide de NIO avec un thread est une mauvaise idée pour plusieurs raisons:

  • Si vous avez plusieurs Processeurs ou cœurs, vous serez la marche au ralenti des ressources puisque vous ne pouvez utiliser qu'un seul core à un moment si vous n'avez qu'un seul thread.
  • Si vous avez à bloc pour une raison quelconque (peut-être à faire un accès au disque), vous PROCESSEUR est inactif quand vous pourriez être la manipulation d'une autre connexion alors que vous êtes en attente pour le disque.

Un thread par connexion est une mauvaise idée, car il n'a pas d'échelle. Disons avoir:

  • 10 000 connexions
  • 2 Processeurs avec 2 cœurs de chaque
  • à seulement 100 threads de bloquer à un moment donné

Ensuite, vous pouvez découvrir que vous avez seulement besoin de 104 threads. Et vous êtes le gaspillage des ressources gestion des threads que vous n'avez pas besoin. Il y a beaucoup de tenue de la comptabilité sous le capot nécessaires pour gérer 10 000 threads. Cela va vous ralentir.


C'est pourquoi vous combiner les deux solutions. Aussi, assurez-vous que votre machine virtuelle à l'aide de la manière la plus rapide des appels système. Chaque OS a son propre système d'appels pour de hautes performances d'e / s réseau. Assurez-vous que votre machine virtuelle à l'aide de la plus récente et la plus. Je crois que c'est epoll() sous Linux.

En outre, si vous utilisez threads par connexion, seriez-vous tout créer de nouveaux threads ou utiliser un très grand pool de threads?

Ça dépend de combien de temps vous voulez passer de l'optimisation. La solution la plus rapide est de créer des ressources comme les fils et cordes en cas de besoin. Puis laissez-la collecte des ordures demande quand vous en avez terminé avec eux. Vous pouvez obtenir un gain de performances en avoir un pool de ressources. Au lieu de créer un nouvel objet, vous demandez à la piscine pour l'un, et de le retourner à la piscine lorsque vous avez terminé. Cela ajoute de la complexité du contrôle de la simultanéité. Cela peut être optimisée grâce à l'avance de la simultanéité des algorithmes tels que la non-blocage des algorithmes. De nouvelles versions de l'API Java ont quelques-uns de ces pour vous. Vous pouvez passer le reste de votre vie à faire ces optimisations sur un seul programme. Quelle est la meilleure solution pour votre application spécifique est probablement une question qui mérite son propre post.

9voto

Peter Lawrey Points 229686

Si vous prêt à dépenser une somme d'argent assez puissant matériel pourquoi vous limiter à un seul serveur. google n'utilisez pas un serveur, ils ne sont même pas utiliser un centre de données de serveurs.

Une idée fausse commune est que NIO permet à des non-blocage de IO à cet effet c'est le seul modèle qui mérite d'être de l'analyse comparative. Si vous référence blocage NIO vous pouvez obtenir 30% plus rapide que l'ancien IO. par exemple, si vous utilisez le même modèle de thread et de comparer simplement les IO modèles.

Pour un jeu sophistiqué, vous êtes beaucoup plus susceptibles de manquer de CPU avant de vous frapper 10K connexions. De nouveau, il est plus simple d'avoir une solution qui évolue horizontalement. Ensuite, vous n'avez pas besoin de vous soucier de combien de connexions que vous pouvez obtenir.

Combien d'utilisateurs peuvent raisonnablement interagir? 24? dans ce cas, vous avez 1000 groupes indépendants qui interagissent. Vous n'aurez pas ce nombre de noyaux dans un serveur.

Combien d'argent par les utilisateurs avez-vous l'intention de passer sur le serveur(s)? Vous pouvez acheter un 12 serveur de base avec 64 GO de mémoire pour moins de £5000. Si vous placez 2500 utilisateurs sur ce serveur, vous avez dépensé £2 par utilisateur.

EDIT: j'ai une référence http://vanillajava.blogspot.com/2010/07/java-nio-is-faster-than-java-io-for.html qui est le mien. ;) J'ai eu cette revue par quelqu'un qui est un expert de Java mise en Réseau et qu'il a largement d'accord avec ce qu'il avait trouvé.

2voto

Kevin Jin Points 433

Comme la plupart d'entre vous les gars sont en train de dire que le serveur est lié à être enfermé dans l'utilisation du PROCESSEUR avant de 10k d'utilisateurs simultanés atteint, je suppose que c'est mieux pour moi d'utiliser une tige de blocage (N)OI approche en considérant le fait que pour ce MMORPG, se plusieurs paquets par seconde pour chaque joueur n'est pas rare et peut ralentir un sélecteur si l'on devait être utilisé.

Pierre a soulevé un point intéressant que le blocage de NIO est plus rapide que les anciennes bibliothèques tout en irreputable mentionné que pour une longue MMORPG serveur, il serait préférable d'utiliser des threads en raison de combien d'instructions sont reçues par joueur. Je n'aurais pas compter sur de trop nombreux joueurs inactif sur ce jeu, donc il ne devrait pas être un problème pour moi d'avoir un tas de non-threads en cours d'exécution. Je me suis rendu compte que la synchronisation est toujours nécessaire, même lorsque l'utilisation d'un framework basé sur NIO, car ils utilisent plusieurs threads s'exécutent en même temps traiter les paquets reçus des clients. La commutation de contexte peut s'avérer être onéreux, mais je vais vous donner cette solution a essayer. Il est relativement facile de revoir mon code pour que je puisse utiliser un NIO cadre si je trouve qu'il y a un goulot d'étranglement.

Je crois que ma question a été répondue. Je vais juste attendre un peu plus afin de recevoir encore plus de perspicacité de plus de personnes. Merci pour toutes vos réponses!

EDIT: j'ai enfin choisi mon action. J'ai vraiment été indécis et a décidé d'utiliser JBoss Netty et permettre à l'utilisateur de basculer entre deux oio ou nio à l'aide des classes

org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;
org.jboss.netty.channel.socket.oio.OioServerSocketChannelFactory;

Très agréable que Netty prend en charge à la fois!

1voto

Vous pourriez vous inspirer de l'ancien projet parrainé par Sun, maintenant nommé: http://www.reddwarfserver.org/

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