34

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

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测试过,有时成功,有时不成功,就像我的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
4

2 回答 2

50

问题

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

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

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

在上下文中

也就是说,这可能不是您的脚本中的问题,而是远程站点上的问题。如果偶尔出现,则表明其他站点有负载问题或到其他站点的网络路径不可靠。

此外,由于是网络问题,您无法判断另一端发生了什么。数据包有可能在一个方向上正常传输,但在另一个方向上被丢弃(或错误路由)。

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

调试这个

正如另一个答案中所建议的,使用数据包分析器可以帮助调试问题。但是,除了准确反映错误消息内容的数据包外,您不会看到太多。

要排除网络拥塞是一个问题,您可以使用类似或什至查看数据包是否丢失到远程站点的工具mtrtracerouteping下文)。

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

解释 traceroute 结果

这需要一些练习,因为中间跃点的高延迟或丢失可能意味着一切或什么都没有。

中间跃点通常是 Internet 中的大型路由器或处理大量数据包的 ISP 网络。他们可能比回复你的 traceroute 有更好的事情要做,所以如果他们目前非常忙,他们可能会选择只回复 10% 的请求。或者选择完全不回复。如果您在最后一跳没有看到损失,那么您可能在损失方面还不错。

但是,如果您确实在最后一跳看到丢失,则无法确定数据包在最后一跳真的丢失了。任何中间跃点都可能负责。通常,您还会在较早的跃点看到损失,这可能表明真正的来源。

雪上加霜的是,您看到的路由可能不是真正的路由:真正的路由可能是不对称的,这意味着您的目的地(这是您在 traceroute 中看到的)采用与回复不同的路径(由于它的工作原理,您在 traceroute 中看不到)。

总结一下:

  • 在 traceroute 中观察到的丢失只能由等于或在您看到的跃点之前的跃点引起。
  • 中间跳的丢失,没有端到端的丢失,可能只是意味着该跳不费心回复。
  • 正向路径(你在 traceroute 中看到的)可能不等于反向路径;反向路径可能会发生丢失和延迟。
  • 从路由中间开始(并影响所有后续跃点)的部分丢失 (1%-90%) 通常表明网络拥塞。通常,您将无能为力。
于 2012-08-27T16:23:26.917 回答
1

使用数据包分析器截获发往/来自 的数据包somewhere.com。研究这些数据包应该会告诉你发生了什么。

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

于 2012-08-27T16:16:34.750 回答