Q104,“通过对等端重置连接”套接字错误,或者何时关闭套接字会导致RST而不是FIN?

我们正在并行开发一个python web服务和一个客户端web站点。当我们从客户机向服务发出http请求时,一个调用始终会在socket.py中引发一个socket.error,在read:

(104,“通过对等方重置连接”)

当我收听Wireshark时,“好”和“坏”的回答看起来非常相似:

  • 由于oauth报头的大小,请求被分成两个包。服务用ack响应这两个值
  • 服务发送响应,每个报头一个包(http/1.0 200 ok,然后是日期报头,等等)。客户机用ack响应每一个。
  • (好的请求)服务器发送fin,ack。客户的回答是fin,ack。服务器响应ack。
  • (错误请求)服务器发送RST、ACK,客户端不发送TCP响应,在客户端引发socket.error。

Web服务和客户端都运行在运行glibc-2.6.1的Gentoo Linux x86-64机器上。我们在同一虚拟机中使用Python 2.5.2。< /P>

客户端是一个django 1.0.2应用程序,它正在调用httplib2 0.4.0来发出请求。我们用OAuthBooT算法签名请求,OAuthTog总是设置为空字符串。

该服务运行的是werkzeug 0.3.1,它使用的是python的wsgiref.simple_服务器。我通过wsgiref.validator运行了wsgi应用程序,没有问题。

这看起来应该很容易调试,但是当我在服务端跟踪一个好的请求时,它看起来就像套接字中的坏请求。_socketobject.close()函数,将委托方法转换为伪方法。当发送或SDETO(不记得哪一个)方法被关闭时,发送FIN或RST,客户端开始处理。

“由对等方重置连接”似乎把责任推到了服务上,但我也不信任httplib2。客户会有过错吗?

**进一步调试-看起来像Linux上的服务器**

我有一个MacBook,所以我试着在一个上运行服务,在另一个上运行客户网站。Linux客户机在没有bug的情况下调用OSX服务器(fin-ack)。os x客户机使用错误(rst ack和a(54,connection reset by peer'))调用linux服务。所以,看起来它是运行在Linux上的服务。是x86*64吗?口齿不清?威斯吉夫?仍在寻找…

**进一步测试-wsgiref看起来很脆弱**

我们已经使用apache和mod_wsgi投入生产,并且连接重置已经消失。请参阅下面的答案,但我的建议是记录连接重置并重试。这将使您的服务器在开发模式下正常运行,并在生产环境中稳定运行。

2009-01-27 00:40:48  jwhitlock
  • 问题是服务器为什么发送rst请求。客户端必须重置连接并通知对等方重置连接消息。所以我认为你是在正确的轨道上 – Igal Serban Dec 20 '08 at 22:45

A回答

  • 1

    我有这个问题。请参见pythonconnection reset by peer问题。

    您(很可能)遇到了基于python全局解释器锁的小时间问题。

    你可以(有时)用一个time.sleep(0.01)策略性的位置来纠正这个问题。

    在哪里?你问。打败我。其思想是在客户机请求内部和周围提供一些更好的线程并发性。试着在发出请求之前把它放在位置,这样gil就可以重置,python解释器可以清除所有挂起的线程。

    2013-10-01 03:05:57  Jordan S.Lott
    • 1
      在链接中,问题似乎是在同一进程中运行服务器和客户端。因此,它们受到gil的约束。 – Igal Serban Dec 20 '08 at 22:42
    • 是的,但是……即使在不同的客户机-服务器主机中,您也会看到相同的连接重置。我仍然认为你应该到处睡觉,看看线程调度的改变是否有帮助。 – S.Lott Dec 20 '08 at 22:57
  • 2

    不要将wsgiref用于生产。使用apache和mod_wsgi或其他工具。

    我们继续使用WSGIRF(WERKZUG测试服务器使用的后端,可能还有其他类似Django测试服务器)来查看这些连接重置,有时是频繁的。我们的解决方案是记录错误,在循环中重试调用,并在十次失败后放弃。httplib2尝试了两次,但我们还需要更多。他们似乎也聚在一起,加上1秒的睡眠可能会消除这个问题。

    在运行apache和mod_wsgi时,我们从未见过连接重置。我不知道他们做了什么不同的事(也许他们只是掩饰自己),但他们并没有出现。

    当我们向本地开发人员社区寻求帮助时,有人确认他们看到许多与wsgiref的连接重置在生产服务器上消失。那里有一个bug,但很难找到它。

    2009-01-27 00:37:29  jwhitlock
  • 3

    我知道您正在使用python,但我发现这篇java文章非常有用。

    http://java.sun.com/javase/6/docs/technotes/guides/net/articles/connection_release.html

    2009-07-28 21:35:46  Sean McCauliff
  • 4

    通常情况下,如果执行不延迟的关闭操作(即,如果数据未被发送和确认,堆栈可以丢弃数据),则会得到RST;如果允许延迟关闭操作,则会得到正常FIN(即,关闭操作等待传输中的数据被确认)。

    也许您需要做的只是将套接字设置为延迟,以便消除套接字上完成的非延迟关闭和acks到达之间的竞争条件?

    2008-12-21 12:44:18  Len Holgate
  • 5

    不过,我在使用python请求客户端将非常大的文件上传到nginx+uwsgi后端时也遇到了同样的问题。

    最终的原因是后端对上传的最大文件大小的限制低于客户端试图发送的文件大小。

    这个错误从未出现在我们的uwsgi日志中,因为这个限制实际上是nginx强加的。

    在nginx中提高限制消除了错误。

    2018-10-15 23:52:03  David Simic