Problème avec multi threaded Python application et les connexions socket
Je suis étudier un problème avec un Python application qui s'exécute sur une machine Ubuntu avec 4G de RAM. L'outil sera utilisé pour la vérification des serveurs (nous préférons rouler nos propres outils). Il utilise des threads pour se connecter à de nombreux serveurs et de nombreuses connexions TCP échouer. Cependant, si j'ajoute un délai de 1 seconde entre le coup d'envoi de chaque fil, puis la plupart des connexions à réussir. J'ai utilisé ce script simple pour enquêter sur ce qui pourrait se passer:
#!/usr/bin/python
import sys
import socket
import threading
import time
class Scanner(threading.Thread):
def __init__(self, host, port):
threading.Thread.__init__(self)
self.host = host
self.port = port
self.status = ""
def run(self):
self.sk = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.sk.settimeout(20)
try:
self.sk.connect((self.host, self.port))
except Exception, err:
self.status = str(err)
else:
self.status = "connected"
finally:
self.sk.close()
def get_hostnames_list(filename):
return open(filename).read().splitlines()
if (__name__ == "__main__"):
hostnames_file = sys.argv[1]
hosts_list = get_hostnames_list(hostnames_file)
threads = []
for host in hosts_list:
#time.sleep(1)
thread = Scanner(host, 443)
threads.append(thread)
thread.start()
for thread in threads:
thread.join()
print "Host: ", thread.host, " : ", thread.status
Si je l'exécute avec le temps.sleep(1) a commenté contre, disons, 300 abrite de nombreuses connexions échouent avec une erreur de dépassement de délai, alors qu'ils n'ont pas de timeout si je mets le délai d'une seconde. Je l'ai fait essayer l'application sur une autre distro Linux en cours d'exécution sur une machine plus puissante et il n'y avait pas autant de connecter des erreurs? Est-ce dû à un noyau de limitation? Est-ce que je peux faire pour obtenir la connexion de travailler sans mettre en retard?
Mise à JOUR
J'ai aussi essayé un programme qui a limité le nombre de threads disponibles dans une piscine. En réduisant ce jusqu'à 20 je peux obtenir tous se connecte à travailler, mais il vérifie seulement environ 1 seconde. Donc, tout ce que j'ai essayer (à mettre dans un sleep(1) ou de limiter le nombre de threads simultanés) je ne semble pas en mesure de vérifier plus de 1 hôte à chaque seconde.
Mise à JOUR
Je viens de trouver cette question qui semble similaire à ce que je vois.
Mise à JOUR
Je me demande si l'écriture de cette aide tordu pourrait aider? Quelqu'un pourrait-il montrer ce que mon exemple ressemblerait écrite à l'aide de tordu?
netstat
)? stackoverflow.com/questions/410616/...L'accès au réseau n'est pas simultanée en Python lors de l'utilisation des threads, vous devez utiliser le multitraitement ou quelque chose comme gevent ou eventlet. Voir la réponse de J. F. Sebastian
Python comme une règle de communiqués de GIL tout faire des I/O de sorte que vous pouvez utiliser les threads, mais vous ne devriez pas créer des milliers d'entre eux juste pour vous connecter à des milliers d'hôtes.
OriginalL'auteur VacuumTube | 2011-01-24
Vous devez vous connecter pour publier un commentaire.
Vous pouvez essayer de
gevent
:Il peut traiter plus d'un hôte par seconde.
De sortie
OriginalL'auteur jfs
Cette variante est beaucoup plus rapide que le code qui utilise
gevent
:Voici une variante qui utilise
t.j'.d.inlineCallbacks
. Il nécessite Python 2.5 ou plus récente. Il permet d'écrire du code asynchrone en mode synchrone (blocage):OriginalL'auteur jfs
Comment un véritable pool de threads?
Exemple:
C'est en python 3, mais ne devrait pas être trop dur à se convertir à 2.x. Je ne suis pas surpris si cela résout votre problème.
remarque: il n'est
multiprocessing.ThreadPool
en Python 2+. Etconcurrent.futures.ThreadPoolExecutor
en Python 3.OriginalL'auteur orlp
Python 3.4 présente les nouvelles provisoire de l'API asynchrones IO --
asyncio
module.Cette approche est similaire à
twisted
de réponse:Ainsi que
twisted
variante il utiliseNoopProtocol
qui ne fait rien mais se déconnecte immédiatement lors de la connexion réussie.Nombre de connexions simultanées est limité à l'aide d'un sémaphore.
Le code est coroutine à base de.
Exemple
Pour savoir comment beaucoup de succès connexions ssl nous pouvons faire pour les 1000 premiers hôtes de haut millions Alexa liste:
Le résultat est moins de la moitié de toutes les connexions sont couronnées de succès. En moyenne, il vérifie ~20 hôtes par seconde. De nombreux sites expiré au bout d'une minute. Si l'hôte ne correspond pas à des noms d'hôtes à partir de certificat du serveur la connexion échoue également. Il comprend
example.com
vswww.example.com
-comme les comparaisons.OriginalL'auteur jfs
Tout d'abord, essayez d'utiliser les sockets nonblocking.
Une autre raison serait que vous consommez tous les ports éphémères.
Essayez de supprimer la limite.
OriginalL'auteur Ichabod Crane