我们正在并行开发 Python Web 服务和客户端网站。当我们从客户端向服务发出 HTTP 请求时,一次调用会在 socket.py 的 read 中持续引发一个 socket.error:
(104, 'Connection reset by peer')
当我用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 机器上。我们在同一个 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,“连接由对等方重置”))。所以,看起来它是在 Linux 上运行的服务。是 x86_64 吗?一个糟糕的 glibc? wsgiref?还在寻找...
** 进一步测试 - wsgiref 看起来不稳定 **
我们已经使用 Apache 和 mod_wsgi 投入生产,并且连接重置已经消失。请参阅下面的答案,但我的建议是记录连接重置并重试。这将使您的服务器在开发模式下运行正常,并在生产模式下稳定运行。