ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

python – 在Tornado中“超时”请求的正确方法

2019-08-30 14:56:08  阅读:229  来源: 互联网

标签:python tornado


我设法编写了一个相当愚蠢的bug,它会让我的一个请求处理程序运行一个非常慢的数据库查询.

有趣的一点是,我注意到即使很长时间围攻完成龙卷风仍然在通过请求(有时90年后)搅拌. (评论 – >我不是100%确定Siege的工作方式,但我很确定它关闭了连接..)

我的问题分为两部分:
– 当客户端关闭连接时,Tornado会取消请求处理程序吗?
– 有没有办法在Tornado中超时请求处理程序?

我通读了代码,似乎无法找到任何东西.即使我的请求处理程序在上面的错误中异步运行,待处理请求的数量也会增加到应用程序速度变慢的水平,最好关闭连接.

解决方法:

当客户端断开连接时,Tornado不会自动关闭请求处理程序.但是,您可以覆盖on_connection_close以在客户端丢弃时收到警报,这将允许您取消结束时的连接.可以使用上下文管理器(或装饰器)来处理设置超时以处理请求;使用tornado.ioloop.IOLoop.add_timeout来安排一些方法,将超时后运行的请求超时作为上下文管理器的__enter__的一部分,然后在上下文管理器的__exit__块中取消该回调.这是一个展示这两个想法的例子:

import time
import contextlib

from tornado.ioloop import IOLoop
import tornado.web
from tornado import gen

@gen.coroutine
def async_sleep(timeout):
    yield gen.Task(IOLoop.instance().add_timeout, time.time() + timeout)

@contextlib.contextmanager
def auto_timeout(self, timeout=2): # Seconds
    handle = IOLoop.instance().add_timeout(time.time() + timeout, self.timed_out)
    try:
        yield handle
    except Exception as e:
        print("Caught %s" % e)
    finally:
        IOLoop.instance().remove_timeout(handle)
        if not self._timed_out:
            self.finish()
        else:
            raise Exception("Request timed out") # Don't continue on passed this point

class TimeoutableHandler(tornado.web.RequestHandler):
    def initialize(self):
        self._timed_out = False

    def timed_out(self):
        self._timed_out = True
        self.write("Request timed out!\n")
        self.finish()  # Connection to client closes here.
        # You might want to do other clean up here.

class MainHandler(TimeoutableHandler):

    @gen.coroutine
    def get(self):
        with auto_timeout(self): # We'll timeout after 2 seconds spent in this block.
            self.sleeper = async_sleep(5)
            yield self.sleeper
        print("writing")  # get will abort before we reach here if we timed out.
        self.write("hey\n")

    def on_connection_close(self):
        # This isn't the greatest way to cancel a future, since it will not actually
        # stop the work being done asynchronously. You'll need to cancel that some
        # other way. Should be pretty straightforward with a DB connection (close
        # the cursor/connection, maybe?)
        self.sleeper.set_exception(Exception("cancelled"))


application = tornado.web.Application([
    (r"/test", MainHandler),
])
application.listen(8888)
IOLoop.instance().start()

标签:python,tornado
来源: https://codeday.me/bug/20190830/1769038.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有