我们正在并行开发Python Web服务和客户端Web站点.当我们从客户端向服务发出HTTP请求时,一次调用始终在socket.py中引发socket.error,在read中:
(104, 'Connection reset by peer')
当我使用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和a(54,'由peer重置连接')).所以,看起来它是在Linux上运行的服务.是x86_64吗?一个坏的glibc?的wsgiref?还在寻找...
**进一步测试 - wsgiref看起来很脆弱**
我们已经使用Apache和mod_wsgi进行生产,连接重置已经消失.请参阅下面的答案,但我的建议是记录连接重置并重试.这将使您的服务器在开发模式下运行正常,并且可以稳定地投入生产.
我有这个问题.请参阅Python"通过对等连接重置"问题.
您(很可能)与基于Python全局解释器锁的小时序问题相冲突.
您可以(有时)通过time.sleep(0.01)
策略性地进行纠正.
"哪里?" 你问.甘拜下风.我们的想法是在客户端请求中及其周围提供更好的线程并发性.尝试在发出请求之前放置它,以便重置GIL并且Python解释器可以清除任何挂起的线程.
不要使用wsgiref进行生产.使用Apache和mod_wsgi,或其他.
我们继续看到这些连接重置,有时经常与wsgiref(werkzeug测试服务器使用的后端,以及可能的其他类似Django测试服务器)重置.我们的解决方案是记录错误,在循环中重试呼叫,并在十次失败后放弃.httplib2尝试了两次,但我们需要更多.他们似乎也成群结队 - 增加一秒睡眠可能会解决这个问题.
在通过Apache和mod_wsgi运行时,我们从未见过重置连接.我不知道他们做了什么不同的事情(也许他们只是掩盖了他们),但他们没有出现.
当我们向当地开发社区寻求帮助时,有人确认他们看到很多连接重置与生产服务器上消失的wsgiref.那里有一个bug,但很难找到它.
我意识到你正在使用python,但我发现这篇Java文章很有用.
http://java.sun.com/javase/6/docs/technotes/guides/net/articles/connection_release.html