当前位置: 首页 > 知识库问答 >
问题:

结合tornado和zmq ioloops:通过对等异常重置连接

淳于健
2023-03-14

当我尝试将Tornado和pyzmq Ioops结合起来时,我遇到了一个恼人的问题(虽然不是关键问题),正如pyzmq官方文档中所描述的那样。

我有一个运行tornado(T)服务器的进程,它接受来自客户端(C)的RESTAPI请求,并通过ZMQ传输将它们代理到另一个执行实际工作的进程(Z)。

C <-> T <-> Z

如果C在Z回复T之前关闭连接,Z(tornado)输出一长串异常跟踪(见底部)。想象一下下面的例子:

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

从控制台2运行客户端并在服务器回复之前中断它(即在5秒内):

% curl -is http://localhost:8080/test/1
^C 

服务器的输出为:

Test arg 1
Ok, time to reply
WARNING:root:Read error on 24: [Errno 54] Connection reset by peer
ERROR:root:Uncaught exception 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'})
Traceback (most recent call last):
  File "/Library/Python/2.7/site-packages/tornado/web.py", line 1023, in _execute
    self.finish()
  File "/Library/Python/2.7/site-packages/tornado/web.py", line 701, in finish
    self.request.finish()
  File "/Library/Python/2.7/site-packages/tornado/httpserver.py", line 433, in finish
    self.connection.finish()
  File "/Library/Python/2.7/site-packages/tornado/httpserver.py", line 187, in finish
    self._finish_request()
  File "/Library/Python/2.7/site-packages/tornado/httpserver.py", line 223, in _finish_request
    self.stream.read_until(b("\r\n\r\n"), self._header_callback)
  File "/Library/Python/2.7/site-packages/tornado/iostream.py", line 153, in read_until
    self._try_inline_read()
  File "/Library/Python/2.7/site-packages/tornado/iostream.py", line 386, in _try_inline_read
    if self._read_to_buffer() == 0:
  File "/Library/Python/2.7/site-packages/tornado/iostream.py", line 421, in _read_to_buffer
    chunk = self._read_from_socket()
  File "/Library/Python/2.7/site-packages/tornado/iostream.py", line 402, in _read_from_socket
    chunk = self.socket.recv(self.read_chunk_size)
error: [Errno 54] Connection reset by peer
ERROR:root:Cannot send error response after headers written
ERROR:root:Uncaught exception, closing connection.
Traceback (most recent call last):
  File "/Library/Python/2.7/site-packages/tornado/iostream.py", line 304, in wrapper
    callback(*args)
  File "/Library/Python/2.7/site-packages/tornado/httpserver.py", line 262, in _on_headers
    self.request_callback(self._request)
  File "/Library/Python/2.7/site-packages/tornado/web.py", line 1412, in __call__
    handler._execute(transforms, *args, **kwargs)
  File "/Library/Python/2.7/site-packages/tornado/web.py", line 1025, in _execute
    self._handle_request_exception(e)
  File "/Library/Python/2.7/site-packages/tornado/web.py", line 1065, in _handle_request_exception
    self.send_error(500, exc_info=sys.exc_info())
  File "/Library/Python/2.7/site-packages/tornado/web.py", line 720, in send_error
    self.finish()
  File "/Library/Python/2.7/site-packages/tornado/web.py", line 700, in finish
    self.flush(include_footers=True)
  File "/Library/Python/2.7/site-packages/tornado/web.py", line 660, in flush
    self.request.write(headers + chunk, callback=callback)
  File "/Library/Python/2.7/site-packages/tornado/httpserver.py", line 429, in write
    self.connection.write(chunk, callback=callback)
  File "/Library/Python/2.7/site-packages/tornado/httpserver.py", line 177, in write
    assert self._request, "Request closed"
AssertionError: Request closed
ERROR:root:Exception in callback 
Traceback (most recent call last):
  File "/Library/Python/2.7/site-packages/pyzmq-2.2.0-py2.7-macosx-10.7-intel.egg/zmq/eventloop/ioloop.py", line 434, in _run_callback
    callback()
  File "/Library/Python/2.7/site-packages/tornado/iostream.py", line 304, in wrapper
    callback(*args)
  File "/Library/Python/2.7/site-packages/tornado/httpserver.py", line 262, in _on_headers
    self.request_callback(self._request)
  File "/Library/Python/2.7/site-packages/tornado/web.py", line 1412, in __call__
    handler._execute(transforms, *args, **kwargs)
  File "/Library/Python/2.7/site-packages/tornado/web.py", line 1025, in _execute
    self._handle_request_exception(e)
  File "/Library/Python/2.7/site-packages/tornado/web.py", line 1065, in _handle_request_exception
    self.send_error(500, exc_info=sys.exc_info())
  File "/Library/Python/2.7/site-packages/tornado/web.py", line 720, in send_error
    self.finish()
  File "/Library/Python/2.7/site-packages/tornado/web.py", line 700, in finish
    self.flush(include_footers=True)
  File "/Library/Python/2.7/site-packages/tornado/web.py", line 660, in flush
    self.request.write(headers + chunk, callback=callback)
  File "/Library/Python/2.7/site-packages/tornado/httpserver.py", line 429, in write
    self.connection.write(chunk, callback=callback)
  File "/Library/Python/2.7/site-packages/tornado/httpserver.py", line 177, in write
    assert self._request, "Request closed"
AssertionError: Request closed

注意:这似乎是pyzmq相关的问题,因为排除pyzmq ioloop后,它将消失。

服务器不会死掉,它可以被其他客户端使用,所以问题并不严重。不过,在日志文件中发现这些巨大的、令人困惑的痕迹是非常烦人的。

那么,有没有什么众所周知的方法来解决这个问题呢?谢谢。

共有1个答案

胡锋
2023-03-14

这不是ZMQ的问题。请求可以通过非超时原因关闭。ZMQ这里唯一的问题是,他们提出了AssertionError,这是常见的,而不是更具体的异常。

如果您确定不想在日志文件中出现这些异常,请执行以下操作:

try: 
    time_consuming_task()
except AssertionError as e:
    if e.message == 'Request closed': 
        logging.info('Bad, annoying client, came to us again!') 
    else:
        raise e
 类似资料:
  • 问题内容: 我正在开发一个从Web服务器下载数据的应用程序,一开始似乎没有任何问题,但是几天前我开始收到这种异常:javax.net.ssl.SSLException: Read error: ssl=0x7a6588: I/O error during system call, Connection reset by peer我不确定是什么原因引起的问题以及如何解决。这是整个LogCat消息:

  • 我正在编写Android应用程序,从一个网站下载特定的文件(目前为20M字节),以供测试之用。我使用URLConnection和BufferedInputStream。 下载了几兆字节后,我收到对等体重置的IOException连接。 InputStream.Read()暂停了大约130秒,然后引发异常。 经过几次尝试,我注意到下载的字节是11,272,192或11,010,048,知道文件可以从

  • 调试此程序时遇到一些问题。我总是在第一次启动我的应用程序时出现这个错误,然后间歇性地出现。有人能帮我扔掉一些调试技巧吗?我试过使用代理检查器,但没有用,我没有看到任何有用的东西。我尝试过在django设置中设置我的站点URL的建议。我尝试了使用和不使用http://以及使用和不使用端口。。。下面是一个毫无帮助的错误: 即使有了这个连接重置,这个应用程序似乎也能正常运行,但它一直让我疯狂地试图调试。

  • 问题内容: 建立: selenium :3.141.0 的Python :3.6.7 heroku-stack :heroku-18 headless-chrome :安装了v71.0.3578.80 buildpack chromedriver :已安装v2.44.609551 buildpack 在heroku中使用selenium时出现此错误: 我用谷歌搜索,但是没有运气。错误发生在此代码的

  • 我这个程序采用的是netty,此程序中有客户端和服务端。 程序思路:服务端接受消息后在利用客户端发给别的服务端。 出现问题:时不时会出现这个异常,也不知道是那报的异常,经过查资料此异常是由某一端断开,发生的连接异常 ,我的客户端做了断开重连 但是并没发现重连的log ,难道是上游的客户端断开,那我的服务端也不应该报异常啊。不是很清楚? 有知道的吗?或者提供解决思路。 客户端重连代码 断开后进入重连

  • 我一直使用芹菜与Rabbitmq作为后端。每当我发送一个高负载(大约600-1000)的任务到Rabbitmq,我得到以下错误socket.error[Errno 104]连接重置由对等 我一直在使用的一个示例命令是: 这是我的客户。py发送一个任务,该任务在worker上执行给定的bash命令,并轮询超时秒的结果。 我还尝试使用此命令在一段时间间隔内发送负载。它仍然给出相同的错误 是什么导致了这