Tornado IOLoop的优雅关闭

8

我正在使用以下代码优雅地关闭我的龙卷风应用程序(取自https://gist.github.com/wonderbeyond/d38cd85243befe863cdde54b84505784):

def sig_handler(servers, sig, frame):
    io_loop = tornado.ioloop.IOLoop.instance()

    def stop_loop(deadline):
        now = time.time()
        if now < deadline and (io_loop._callbacks or io_loop._timeouts):
            logging.info('Waiting for next tick')
            print("CALL BACKS")
            print(io_loop._callbacks)
            print("TIMEOUTS")
            print(io_loop._timeouts)
            io_loop.add_timeout(now + 1, stop_loop, deadline)
        else:
            io_loop.stop()
            logging.info("Shutting down.")

    def shutdown():
        logging.info("Stopping http servers")

        # servers is a list of servers to stop
        for s in servers:
           s.stop()

        logging.info("Will shutdown in %s seconds ...",
                     MAX_WAIT_SEC_BEFORE_SHUTDOWN)
        stop_loop(time.time() + MAX_WAIT_SEC_BEFORE_SHUTDOWN)

    logging.warning("Caught signal: %s", sig)
    io_loop.add_callback_from_signal(shutdown)

我将MAX_WAIT_SEC_BEFORE_SHUTDOWN设置为10秒。即使关闭了http服务器,每次关闭服务器也需要完整的10秒钟。我注意到io_loop._timeouts列表中始终存在项目,例如:

[<tornado.ioloop._Timeout object at 0x106b90408>, <tornado.ioloop._Timeout object at 0x106b904c8>, ...]

“io_loop._timeouts”中有哪些项目?我应该期望这是一个空列表,还是我没有停止应该停止的东西?
这个关闭程序正常吗?有人能提供其他代码建议吗?
2个回答

4
停止 Tornado 的 HTTPServer 并不会关闭所有现有的连接,它只停止服务器接受新的连接。有一个未记录在案的 close_all_connections 方法,但它不能区分当前正在处理请求和空闲的连接,因此不适合用于优雅的关机。目前还没有办法在连接变为空闲时关闭所有连接。
每个空闲连接都在 IOLoop 上维护一个超时时间(如果连接空闲时间过长,则会被关闭,尽管默认值为一小时。将 idle_connection_timeout= 传递给 HTTPServer 构造函数以更改此设置)。此外,Tornado 或其他库的其他功能也可能创建超时(在 Tornado 自身中,curl_httpclientautoreload 都创建了始终运行的超时),因此您通常无法假定挂起超时的数量会达到零。
总的来说,我建议无条件地等待 MAX_WAIT_SEC_BEFORE_SHUTDOWN 而不是试图确定何时可以安全地更早关闭。如果您确实想确定所有挂起操作何时完成,则最好自己保留挂起操作的计数(对于您认为合适的“操作”定义)而不是试图从 IOLoop 的实现细节推断出这一点。

谢谢Ben,你的回答总是非常有启发性的。干杯! - johhny B

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接