2009-04-17 8 views
22

J'ai un programme très simple écrit en 5 min qui ouvre un socket sever et boucle la requête et affiche à l'écran les octets qui lui sont envoyés. J'ai ensuite essayé de comparer le nombre de connexions que je peux utiliser pour essayer de trouver le nombre d'utilisateurs simultanés que je peux supporter avec ce programme.Y at-il une limite sur le nombre de connexions tcp/ip entre les machines sur Linux?

Sur une autre machine (où le réseau entre eux n'est pas saturé), j'ai créé un simple programme qui se connecte à la machine du serveur et envoie les octets "hello world". Lorsque la boucle est comprise entre 1000 et 3000, le client se termine avec toutes les demandes envoyées. Lorsque la boucle dépasse 5000, il commence à avoir des temps morts après avoir fini le premier nombre de demandes. Pourquoi est-ce? Je me suis assuré de fermer ma prise dans la boucle.

Pouvez-vous créer autant de connexions dans un certain laps de temps?

Cette limite s'applique-t-elle uniquement entre les mêmes machines et je n'ai pas besoin de m'en préoccuper en production où plus de 5 000 demandes proviennent de machines différentes?

+0

vous pouvez contrôler vos prises en utilisant la commande art. Et suivez les étapes pour augmenter la limite de socket si nécessaire. – Antarus

+0

vous pouvez réutiliser les sockets TIMED_WAIT comme: 's = socket.socket (socket.AF_INET, socket.SOCK_STREAM, 0)' 's.setsockopt (socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) ' – knutole

Répondre

24

Il y a une limite, oui. Voir ulimit. Vous devez également prendre en compte l'état TIMED_WAIT. Une fois qu'un socket TCP est fermé (par défaut) le port reste occupé en TIMED_WAIT statut pendant 2 minutes. Cette valeur est réglable. Cela va également "vous sortir de vos orbites" même si elles sont fermées.

Exécutez netstat pour voir les choses TIMED_WAIT en action.

P.S. La raison pour TIMED_WAIT est de gérer le cas des paquets arrivant après la fermeture du socket. Cela peut arriver parce que les paquets sont retardés ou que l'autre côté ne sait pas que le socket a été fermé. Cela permet au système d'exploitation de laisser tomber silencieusement ces paquets sans risque "d'infecter" une autre connexion socket non liée.

+0

Je viens de vérifier avec netstat sur les deux machines, et il y a en effet une tonne de TIMED_WAIT côté client mais pas de TIMED_WAIT côté serveur. Est-ce le comportement que vous décrivez? En supposant que oui: En supposant oui: 1) Cela signifie-t-il que cela ne posera pas de problème en production car la limite semble provenir du côté client (en panne de socket) et pas du côté serveur (aucun socket n'est créé) 2) Y at-il un moyen de contourner ce problème afin que je puisse tester mon serveur avec une charge similaire à la production? – erotsppa

+0

Le comportement de TIMED_WAIT est spécifique au système d'exploitation. Oui, vous pouvez contourner le problème - il est possible de modifier le délai TIMED_WAIT, par exemple. de 120 secondes à 30 ou même moins. –

+0

ulimit me montre "unlimited" ... mais je ne pense vraiment pas qu'il est illimité ... – trillions

1

Vous pourriez vouloir vérifier /etc/security/limits.conf

8

Lorsque vous recherchez la performance maximale, vous rencontrez beaucoup de problèmes et de goulots d'étranglement potentiels. Exécuter un simple test de bonjour ne va pas nécessairement tous les trouver.

limitations possibles:

  • limitations socket du noyau: regarder dans /proc/sys/net pour beaucoup de tuning du noyau ..
  • limites de processus: consultez ulimit que d'autres ont déclaré ici
  • que votre application se développe dans complexité, il peut ne pas avoir assez de puissance CPU pour suivre le nombre de connexions entrant. Utilisez top pour voir si votre CPU est maxed
  • nombre de threads? Je n'ai pas l'expérience du filetage, mais cela peut entrer en jeu avec les éléments précédents.
2

Votre serveur est-il mono-thread? Si oui, quelle fonction d'interrogation/multiplexage utilisez-vous? L'utilisation de select() ne fonctionne pas au-delà de la limite de descripteur de fichier maximale codée en dur définie au moment de la compilation, ce qui est sans espoir (normalement 256 ou un peu plus). Poll() est meilleur mais vous vous retrouverez avec le problème d'évolutivité avec un grand nombre de FD qui repeuplent l'ensemble à chaque fois autour de la boucle. Epoll() devrait bien fonctionner jusqu'à une autre limite que vous avez atteinte.

Les connexions 10k devraient être assez faciles à réaliser. Utilisez un noyau récent (ish) 2.6.

Combien de machines client avez-vous utilisées? Êtes-vous sûr de ne pas avoir atteint une limite côté client?

+0

Sur mon système hardcoded select limit était 1024 et il est en effet impossible d'aller au-dessus (la limite est imposée par un type de données qui détient le carte des descripteurs de fichiers à surveiller). –

2

La réponse rapide est 2^16 ports TCP, 64K.

Les problèmes liés aux limites imposées par le système constituent un problème de configuration, déjà abordé dans les commentaires précédents.

Les implications internes à TCP ne sont pas si claires (pour moi). Chaque port nécessite de la mémoire pour son instanciation, va sur une liste et a besoin de tampons réseau pour les données en transit.

Compte tenu des sessions TCP de 64 Ko, la surcharge pour les instances des ports pourrait être un problème sur un noyau 32 bits, mais pas sur un noyau 64 bits (la correction est ici acceptée). Le processus de recherche avec des sessions 64K peut ralentir un peu les choses et chaque paquet touche les files d'attente du timer, ce qui peut aussi être problématique. Stockage pour les données en transit peut théoriquement gonfler aux ports de taille de la fenêtre (peut-être 8 GByte).

Le problème avec la vitesse de connexion (mentionné ci-dessus) est probablement ce que vous voyez. TCP prend généralement du temps pour faire les choses. Cependant, ce n'est pas obligatoire. Un TCP se connecter, transact et déconnecter peut être fait très efficacement (vérifiez pour voir comment les sessions TCP sont créées et fermées).

Il existe des systèmes qui transmettent des dizaines de gigabits par seconde, donc la mise à l'échelle du niveau de paquet devrait être OK.

Il existe des machines avec beaucoup de mémoire physique, ce qui semble correct.

Les performances du système, si elles sont correctement configurées, doivent être correctes.

Le côté serveur des choses devrait évoluer d'une manière similaire.

Je serais préoccupé par des choses comme la bande passante mémoire.

Considérez une expérience dans laquelle vous vous connectez à l'hôte local 10 000 fois. Puis tapez un caractère. La pile entière à travers l'espace utilisateur serait engagée sur chaque caractère. L'empreinte active dépasserait probablement la taille du cache de données. Courir à travers beaucoup de mémoire peut stresser le système VM. Le coût des commutateurs de contexte pourrait approcher une seconde!

Ceci est discuté d'une variété d'autres sujets: https://serverfault.com/questions/69524/im-designing-a-system-to-handle-10000-tcp-connections-per-second-what-problems

Questions connexes