我们正在并行开发 Python Web 服务和客户端网站。当我们从客户端向服务发出 HTTP 请求时,一个调用会在 socket.py 中持续引发一个 socket.error,如下所示:
(104,'对等方重置连接')
当我用wireshark收听时,“好”和“坏”的反应看起来非常相似:
- 由于 OAuth 标头的大小,请求被分成两个数据包。该服务使用 ACK 响应两者
- 服务发送响应,每个标头一个数据包(HTTP/1.0 200 OK,然后是 Date 标头等)。客户端用 ACK 响应每个。
- (好请求)服务器发送一个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 令牌始终设置为空字符串。
该服务正在运行 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 投入生产,并且连接重置已经消失。请参阅下面的答案,但我的建议是记录连接重置并重试。这将使您的服务器在开发模式下运行良好,并在生产中稳定运行。