【问题标题】:How can I debug what is causing a connection refused or a connection time out?如何调试导致连接被拒绝或连接超时的原因?
【发布时间】:2012-08-22 03:37:21
【问题描述】:

我有以下代码已经运行了大约一年:

import urllib2

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

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

  • urllib2.URLError: &lt;urlopen error [Errno 111] Connection refused&gt;
  • &lt;urlopen error [Errno 110] Connection timed out&gt;

失败的痕迹是:

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

【问题讨论】:

  • 在 linux 终端上尝试 telnet somewhere.com 443 并检查其名称解析失败或连接失败的位置。
  • 使用 try 和 catch 语句,然后在 catch 语句中打印错误可能会显示更多信息。
  • telnet 告诉你的 IP 地址总是一样吗?
  • 是的,每个telnet请求的IP地址都是一样的
  • Server Fault 有一个关于 Connection Refused 的规范问题。

标签: python networking


【解决方案1】:

问题

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

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

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

在上下文中

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

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

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

调试这个

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

要排除网络拥塞问题,您可以使用mtrtraceroute 甚至ping 之类的工具来查看数据包是否会丢失到远程站点(见下文)。

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

解释traceroute结果

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

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

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

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

总结一下:

  • 在 traceroute 中观察到的丢失只能由等于或早于您看到的跃点的跃点引起。
  • 中间跃点的丢失,没有端到端的损耗,可能只是意味着该跃点懒得回复。
  • 正向路径(您在 traceroute 中看到的)可能不等于反向路径;反向路径可能会发生丢失和延迟。
  • 在路由中间开始的部分丢失 (1%-90%)(并影响所有后续跃点)通常表明网络拥塞。通常,您将无能为力。

【讨论】:

  • 我正在运行 mtr 并且在特定主机上,大约 10% 的数据包丢失。这是否意味着这个特定的主机有问题?
  • 取决于数据包丢失的何处。请参阅我回答的mtr 段落中添加的文本。
  • “重负载”是指内存还是 CPU?
【解决方案2】:

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-20
    • 1970-01-01
    • 2017-08-08
    • 2012-03-04
    • 2014-11-30
    相关资源
    最近更新 更多