当我尝试按照pyzmq 官方文档中的描述组合 Tornado 和 pyzmq ioloops 时,我遇到了一个烦人的(虽然不是关键的)问题。
我有一个运行龙卷风(T)服务器的进程,它接受来自客户端(C)的 REST API 请求,并通过 ZMQ 传输到另一个真正工作的进程(Z)代理它们。
C <-> T <-> Z
如果 C 在 Z 回复 T之前关闭连接,则 Z(龙卷风)会输出一长串异常跟踪(见底部)。想象以下示例:
import tornado.ioloop
from tornado.web import Application, RequestHandler, asynchronous
from zmq.eventloop import ioloop
import time
def time_consuming_task():
time.sleep(5)
class TestHandler(RequestHandler):
def get(self, arg):
print "Test arg", arg
time_consuming_task()
print "Ok, time to reply"
self.write("Reply")
if __name__ == "__main__":
app = tornado.web.Application(
[
(r"/test/([0-9]+)", TestHandler)
])
ioloop.install()
app.listen(8080)
tornado.ioloop.IOLoop.instance().start()
这个例子实际上并没有与任何 ZMQ 对等体对话,它只是将 pyzmq ioloop 附加到 tornado 的 ioloop。不过,足以说明问题。
从控制台一台运行服务器:
% python example.py
从控制台二运行客户端并在服务器回复之前中断它(即在 5 秒内):
% curl -is http://localhost:8080/test/1
^C
服务器的输出是:
测试参数 1 好的,到时候回复 WARNING:root:Read error on 24: [Errno 54] Connection reset by peer 错误:根:未捕获的异常 GET /test/1 (::1) HTTPRequest(protocol='http', host='localhost:8080', method='GET', uri='/test/1', version='HTTP/1.1', remote_ip='::1', body=' ', headers={'Host': 'localhost:8080', 'Accept': '*/*', 'User-Agent': 'curl/7.21.4 (universal-apple-darwin11.0) libcurl/7.21. 4 OpenSSL/0.9.8r zlib/1.2.5'}) 回溯(最近一次通话最后): _execute 中的文件“/Library/Python/2.7/site-packages/tornado/web.py”,第 1023 行 self.finish() 文件“/Library/Python/2.7/site-packages/tornado/web.py”,第 701 行,完成 self.request.finish() 文件“/Library/Python/2.7/site-packages/tornado/httpserver.py”,第 433 行,完成 self.connection.finish() 文件“/Library/Python/2.7/site-packages/tornado/httpserver.py”,第 187 行,完成 self._finish_request() _finish_request 中的文件“/Library/Python/2.7/site-packages/tornado/httpserver.py”,第 223 行 self.stream.read_until(b("\r\n\r\n"), self._header_callback) 文件“/Library/Python/2.7/site-packages/tornado/iostream.py”,第 153 行,在 read_until self._try_inline_read() _try_inline_read 中的文件“/Library/Python/2.7/site-packages/tornado/iostream.py”,第 386 行 如果 self._read_to_buffer() == 0: _read_to_buffer 中的文件“/Library/Python/2.7/site-packages/tornado/iostream.py”,第 421 行 块 = self._read_from_socket() _read_from_socket 中的文件“/Library/Python/2.7/site-packages/tornado/iostream.py”,第 402 行 块 = self.socket.recv(self.read_chunk_size) 错误:[Errno 54] 对等方重置连接 错误:root:写入标头后无法发送错误响应 错误:根:未捕获的异常,正在关闭连接。 回溯(最近一次通话最后): 包装器中的文件“/Library/Python/2.7/site-packages/tornado/iostream.py”,第 304 行 回调(*args) _on_headers 中的文件“/Library/Python/2.7/site-packages/tornado/httpserver.py”,第 262 行 self.request_callback(self._request) __call__ 中的文件“/Library/Python/2.7/site-packages/tornado/web.py”,第 1412 行 handler._execute(变换,*args,**kwargs) _execute 中的文件“/Library/Python/2.7/site-packages/tornado/web.py”,第 1025 行 self._handle_request_exception(e) _handle_request_exception 中的文件“/Library/Python/2.7/site-packages/tornado/web.py”,第 1065 行 self.send_error(500, exc_info=sys.exc_info()) 文件“/Library/Python/2.7/site-packages/tornado/web.py”,第 720 行,在 send_error self.finish() 文件“/Library/Python/2.7/site-packages/tornado/web.py”,第 700 行,完成 self.flush(include_footers=True) 文件“/Library/Python/2.7/site-packages/tornado/web.py”,第 660 行,齐平 self.request.write(headers + chunk, callback=callback) 文件“/Library/Python/2.7/site-packages/tornado/httpserver.py”,第 429 行,写入 self.connection.write(块,回调=回调) 文件“/Library/Python/2.7/site-packages/tornado/httpserver.py”,第 177 行,写入 断言 self._request, "请求关闭" AssertionError:请求已关闭 错误:root:回调中的异常 回溯(最近一次通话最后): _run_callback 中的文件“/Library/Python/2.7/site-packages/pyzmq-2.2.0-py2.7-macosx-10.7-intel.egg/zmq/eventloop/ioloop.py”,第 434 行 打回来() 包装器中的文件“/Library/Python/2.7/site-packages/tornado/iostream.py”,第 304 行 回调(*args) _on_headers 中的文件“/Library/Python/2.7/site-packages/tornado/httpserver.py”,第 262 行 self.request_callback(self._request) __call__ 中的文件“/Library/Python/2.7/site-packages/tornado/web.py”,第 1412 行 handler._execute(变换,*args,**kwargs) _execute 中的文件“/Library/Python/2.7/site-packages/tornado/web.py”,第 1025 行 self._handle_request_exception(e) _handle_request_exception 中的文件“/Library/Python/2.7/site-packages/tornado/web.py”,第 1065 行 self.send_error(500, exc_info=sys.exc_info()) 文件“/Library/Python/2.7/site-packages/tornado/web.py”,第 720 行,在 send_error self.finish() 文件“/Library/Python/2.7/site-packages/tornado/web.py”,第 700 行,完成 self.flush(include_footers=True) 文件“/Library/Python/2.7/site-packages/tornado/web.py”,第 660 行,齐平 self.request.write(headers + chunk, callback=callback) 文件“/Library/Python/2.7/site-packages/tornado/httpserver.py”,第 429 行,写入 self.connection.write(块,回调=回调) 文件“/Library/Python/2.7/site-packages/tornado/httpserver.py”,第 177 行,写入 断言 self._request, "请求关闭" AssertionError:请求已关闭
注意:这似乎是与 pyzmq 相关的问题,因为在排除 pyzmq ioloop 后消失了。
服务器不会死,它可以被其他客户端使用,所以问题并不严重。但是,在日志文件中找到这些巨大的令人困惑的痕迹是非常烦人的。
那么,有没有什么众所周知的方法可以解决这个问题呢?谢谢。