web-dev-qa-db-fra.com

Comment puis-je déboguer la cause d'un refus de connexion ou d'un délai de connexion?

J'ai le code suivant qui fonctionne depuis environ un an:

import urllib2

req = urllib2.Request('https://somewhere.com','<Request></Request>')
data = urllib2.urlopen(req)
print data.read()

Dernièrement, il y a eu quelques erreurs aléatoires:

  • urllib2.URLError: <urlopen error [Errno 111] Connection refused>
  • <urlopen error [Errno 110] Connection timed out>

La trace de l'échec est:

Traceback (most recent call last):
  File "test.py", line 4, in <module>
    data = urllib2.urlopen(req).read()
  File "/usr/lib/python2.7/urllib2.py", line 126, in urlopen
    return _opener.open(url, data, timeout)
  File "/usr/lib/python2.7/urllib2.py", line 400, in open
    response = self._open(req, data)
  File "/usr/lib/python2.7/urllib2.py", line 418, in _open
    '_open', req)
  File "/usr/lib/python2.7/urllib2.py", line 378, in _call_chain
    result = func(*args)
  File "/usr/lib/python2.7/urllib2.py", line 1215, in https_open
    return self.do_open(httplib.HTTPSConnection, req)
  File "/usr/lib/python2.7/urllib2.py", line 1177, in do_open
    raise URLError(err)
urllib2.URLError: <urlopen error [Errno 111] Connection refused>

Les erreurs ci-dessus se produisent de manière aléatoire, le script peut s'exécuter avec succès la première fois, mais échoue lors de la deuxième exécution et vice versa.

Que dois-je faire pour déboguer et comprendre d'où vient le problème? Comment puis-je savoir si le point de terminaison a consommé ma demande et renvoyé une réponse mais ne m'a jamais atteint?

Avec telnet

Je viens de tester avec telnet, parfois ça réussit, parfois non, tout comme mon Python.

En cas de succès:

$ telnet somewhere.com 443
Trying XXX.YY.ZZZ.WWW...
Connected to somewhere.com.
Escape character is '^]'.
Connection closed by foreign Host.

Sur une connexion refusée:

$ telnet somewhere.com 443
Trying XXX.YY.ZZZ.WWW...
telnet: Unable to connect to remote Host: Connection refused

Sur un timeout:

$ telnet somewhere.com 443
Trying XXX.YY.ZZZ.WWW...
telnet: Unable to connect to remote Host: Connection timed out
28
Thierry Lam

Le problème

Le problème est dans la couche réseau. Voici les codes d'état expliqués:

  • Connection refused: L'homologue n'écoute pas sur le port résea auquel vous essayez de vous connecter. Cela signifie généralement qu'un pare-feu refuse activement la connexion ou que le service correspondant n'est pas démarré sur l'autre site ou est surchargé.

  • Connection timed out: Pendant la tentative d'établissement de la connexion TCP, aucune réponse n'est venue de l'autre côté dans un délai donné. Dans le contexte d'urllib, cela peut signifie également que la réponse HTTP n'est pas arrivée à temps, parfois aussi à cause de pare-feu, parfois à cause de l'encombrement du réseau ou d'une forte charge sur le site distant (ou même local).

Dans le contexte

Cela dit, ce n'est probablement pas un problème dans votre script, mais sur le site distant. Si cela se produit occasionnellement, cela indique que l'autre site a des problèmes de chargement ou que le chemin réseau vers l'autre site n'est pas fiable.

De plus, comme c'est un problème avec le réseau, vous ne pouvez pas dire ce qui s'est passé de l'autre côté. Il est possible que les paquets voyagent bien dans un sens mais soient abandonnés (ou mal acheminés) dans l'autre.

Ce n'est pas non plus un problème DNS (direct), qui provoquerait une autre erreur ( Nom ou service inconnu ou quelque chose de similaire). Il peut cependant arriver que le DNS soit configuré pour renvoyer des adresses IP différentes à chaque demande, ce qui vous connecterait (mise en cache DNS laissée de côté) à différentes adresses hôtes à chaque tentative de connexion. Il se pourrait à son tour que certains de ces hôtes soient mal configurés ou surchargés et provoquent ainsi les problèmes susmentionnés.

Déboguer ceci

Comme suggéré dans une autre réponse, l'utilisation d'un analyseur de paquets peut aider à déboguer le problème. Cependant, vous ne verrez pas grand-chose sauf les paquets reflétant exactement ce que dit le message d'erreur.

Pour exclure la congestion du réseau en tant que problème, vous pouvez utiliser un outil comme mtr ou traceroute ou même ping pour voir si les paquets sont perdus sur le site distant. Notez que, si vous voyez une perte dans mtr (et n'importe quel outil traceroute d'ailleurs), vous devez toujours considérer le premier hôte où la perte se produit (dans la route de la vôtre vers la télécommande) comme celui qui abandonne les paquets, en raison de la façon - ICMP fonctionne. Si les paquets ne sont perdus qu'au dernier saut sur une longue période (disons 100 paquets), cet hôte a définitivement un problème. Si vous voyez que ce comportement est persistant (sur plusieurs jours), vous souhaiterez peut-être contacter l'administrateur.

La perte au milieu de la route correspond généralement à la congestion du réseau (peut-être en raison de la maintenance), et vous ne pouvez rien y faire (sauf pleurnicher auprès du FAI au sujet de la redondance manquante).

Si la congestion du réseau n'est pas un problème (c'est-à-dire pas plus de, disons, 5% des paquets sont perdus), vous devez contacter l'administrateur du serveur distant pour déterminer ce qui ne va pas. Il peut être en mesure de voir les informations pertinentes dans les journaux système. L'exécution d'un analyseur de paquets sur le site distant peut également être plus révélatrice que sur le site local. Vérification de l'ouverture du port à l'aide de netstat -tlp est alors définitivement recommandé.

47
Jonas Schäfer

Utilisez un analyseur de paquets pour intercepter les paquets vers/depuis somewhere.com. L'étude de ces paquets devrait vous dire ce qui se passe.

Les délais d'attente ou les connexions refusées peuvent signifier que l'hôte distant est trop occupé.

1
Roland Smith