如何调试导致连接被拒绝或连接超时的原因?

时间:2012-08-27 16:07:58

标签: python networking

我有以下代码已经工作了大约一年:

import urllib2

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

最近,出现了一些随机错误:

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

失败的痕迹是:

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>

上述错误是随机发生的,脚本可以在第一次成功运行,但在第二次运行时失败,反之亦然。

我应该怎么做才能调试并找出问题的来源?如何判断端点是否已经消耗了我的请求并返回了响应但从未接触过我?

使用telnet

我刚刚使用telnet测试过,有时它会成功,有时它不会,就像我的Python一样。

成功:

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

拒绝连接:

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

超时:

$ telnet somewhere.com 443
Trying XXX.YY.ZZZ.WWW...
telnet: Unable to connect to remote host: Connection timed out

2 个答案:

答案 0 :(得分:47)

问题

问题出在网络层。以下是解释的状态代码:

  • Connection refused:对等方没有收听您尝试连接的相应network port。这通常意味着防火墙正在主动拒绝连接,或者相应的服务未在其他站点上启动或过载。

  • Connection timed out:在尝试建立TCP连接期间,在给定的时间限制内没有来自另一方的响应。在urllib的上下文中,可能也意味着HTTP响应没有及时到达。这有时也是由防火墙引起的,有时是由于网络拥塞或远程(甚至是本地)站点的负载过重造成的。

在上下文中

也就是说,它可能不是您脚本中的问题,而是在远程站点上。如果偶尔发生,则表示其他站点存在负载问题,或者指向其他站点的网络路径不可靠。

此外,由于网络存在问题,您无法分辨对方发生的情况。数据包可能在一个方向上移动得很好,但在另一个方向上丢失(或错误路由)。

它也不是(直接)DNS问题,会导致另一个错误(名称或服务未知或类似的东西)。但是,可能会将DNS配置为在每个请求上返回不同的IP地址,这会在每次连接尝试时将您(左侧的DNS缓存)连接到不同的地址主机。反过来可能是这些主机中的一些主机配置错误或过载,从而导致上述问题。

调试此

正如另一个答案中所建议的那样,使用数据包分析器可以帮助调试问题。然而,除了反映错误消息所说的数据包之外,您不会看到太多。

要排除网络拥塞问题,您可以使用mtrtraceroute甚至ping等工具查看数据包是否丢失到远程站点。请注意,如果您看到mtr中的丢失(以及任何跟踪路由工具),您必须始终考虑第一个发生丢失的主机(在从您的路由到远程的路由中)作为丢弃数据包的那个,因为{{{ 3}}有效。如果数据包仅在很长一段时间内的最后一跳(例如,100个数据包)丢失,那么该主机肯定存在问题。如果您发现此行为持续存在(持续数天),则可能需要与管理员联系。

路线中间的损失通常对应于网络拥塞(可能是由于维护),并且你无能为力(除了在ISP上抱怨缺少冗余)。

如果网络拥塞不是问题(即不超过5%的数据包丢失),您应该联系远程服务器管理员以找出问题所在。他可能能够在系统日志中看到相关的信息。在远程站点上运行数据包分析器可能比在本地站点上更具启发性。现在肯定建议使用netstat -tlp检查端口是否打开。

答案 1 :(得分:1)

使用packet analyzer拦截来自somewhere.com的数据包。研究这些数据包应该告诉你发生了什么。

超时或连接被拒绝可能意味着远程主机太忙了。