我们正在同时开发 Python Web 服务和客户端网站。当我们从客户端向服务发出 HTTP 请求时,一个调用会在 socket.py 中持续引发一个 socket.error,如下所示:
(104, 'Connection reset by peer')
当我用wireshark收听时,“好”和“坏”的 react 看起来非常相似:
- 由于 OAuth header 的大小,请求被分成两个数据包。服务使用 ACK 响应两者
- 服务发送响应,每个 header 一个数据包(HTTP/1.0 200 OK,然后是 Date header 等)。客户端用 ACK 响应每个。
- (Good request) 服务器发送一个 FIN, ACK。客户端以 FIN、ACK 响应。服务器响应 ACK。
- (错误请求)服务器发送 RST、ACK,客户端不发送 TCP 响应,客户端引发 socket.error。
Web 服务和客户端都在运行 glibc-2.6.1 的 Gentoo Linux x86-64 机器上运行。我们在同一个 virtual_env 中使用 Python 2.5.2。
客户端是一个 Django 1.0.2 应用程序,它调用 httplib2 0.4.0 来发出请求。我们使用 OAuth 签名算法对请求进行签名,OAuth token 始终设置为空字符串。
该服务正在运行 Werkzeug 0.3.1,它使用 Python 的 wsgiref.simple_server。我通过 wsgiref.validator 运行 WSGI 应用程序没有任何问题。
看起来这应该很容易调试,但是当我在服务端跟踪一个好的请求时,它看起来就像是错误的请求,在 socket._socketobject.close() 函数中,将委托方法变成了虚拟的方法。当send或sendto(不记得是哪个)方法被关闭时,发送FIN或RST,客户端开始处理。
“对等连接重置”似乎将责任归咎于服务,但我也不信任 httplib2。客户有错吗?
** 进一步调试 - 看起来像 Linux 上的服务器 **
我有一台 MacBook,所以我尝试在一台上运行服务,在另一台上运行客户端网站。 Linux 客户端调用 OS X 服务器时没有错误 (FIN ACK)。 OS X 客户端调用带有错误的 Linux 服务(RST ACK 和 (54, 'Connection reset by peer'))。因此,它看起来像是在 Linux 上运行的服务。是 x86_64 吗?一个糟糕的 glibc? wsgiref?还在找……
** 进一步测试 - wsgiref 看起来很不稳定 **
我们已经使用 Apache 和 mod_wsgi 投入生产,连接重置已经消失。请参阅下面的答案,但我的建议是记录连接重置并重试。这将使您的服务器在开发模式下运行良好,并在生产中稳定运行。
最佳答案
我遇到过这个问题。见 The Python "Connection Reset By Peer" Problem .
您(很可能)遇到了基于 Python 全局解释器锁的小时间问题。
您可以(有时)使用策略性放置的 time.sleep(0.01)
来纠正此问题。
“在哪里?”你问。打败我。这个想法是在客户端请求中和围绕客户端请求提供一些更好的线程并发性。尝试将它放在在发出请求之前,以便重置 GIL,Python 解释器可以清除所有待处理的线程。
关于python - 104, 'Connection reset by peer' 套接字错误,或何时关闭套接字会导致 RST 而不是 FIN?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/383738/