【问题标题】:handling request timeouts with tornado用龙卷风处理请求超时
【发布时间】:2014-07-02 08:55:29
【问题描述】:

我有一些长请求需要在我的 Tornado 服务器中处理。 我刚刚开始理解 Tornado 异步代码的整个概念,似乎虽然这将允许更多用户在处理我的长请求时与服务器交互,但它不能解决我的问题,即 request超时

异步代码在服务器中异步工作,但客户端保持同步,这意味着虽然服务器可以处理更多请求,但客户端“卡住”等待响应直到发生超时(我错了吗?)

问题是,如何解决浏览器超时问题? 换句话说,我正在寻找一种从客户端发出请求的方法,该请求将立即返回但在后台处理请求。处理完成后,它应该以某种方式通知客户端。

是否有内置机制或库? 处理这种情况的最佳方法是什么?

【问题讨论】:

    标签: python asynchronous timeout tornado


    【解决方案1】:

    Tornado 的 RequestHandler 可以接受来自客户端的 POST,将任务添加到队列中,然后响应“ok I got it”:

    q = collections.deque()
    
    class MyHandler(RequestHandler):
        def post(self):
            # Your code determines what work the client requests:
            task_info = parse(self.request.body)
            q.append(task_info)
            self.finish(json.dumps({'ok': 1}))
    

    客户端应生成唯一的 task_id 并将其包含在它发布的信息中。

    如果您想要更复杂的任务队列,可以查看my Toro project。或者更简单的方法是使用 Tornado PeriodicCallback 经常检查队列中是否有任务。

    那么,您如何通知客户某项任务已完成?如果客户端是浏览器,我建议使用 websocket 连接。这是Tornado's websocket documentation。当有人访问您的页面时,一些 Javascript 应该打开到服务器的 websocket 连接。当访问者提交任务时,Javascript 首先 生成一个 task_id,订阅有关该 task_id 的通知,然后将任务信息发布到服务器。 Javascript:

    var ws = new WebSocket("ws://localhost:8888/websocket");
    ws.onmessage = function (evt) {
       alert(evt.data);
    };
    
    /* Tell the server we want to know about this task */
    function subscribe(task_id) {
        ws.send(JSON.stringify({task_id: task_id}));
    }
    

    这是服务器的 websocket 处理程序:

    notifiers = set()
    
    class TaskNotifier(websocket.WebSocketHandler):
        def open(self):
            notifiers.add(self)
    
        def on_message(self, message):
            # Client is asking to subscribe to notifications about
            # a certain task_id.
            parsed = json.loads(message)
            self.task_id = parsed['task_id']
    
        def on_close(self):
            notifiers.discard(self)
    

    现在,每当您的代码从 q 提取任务并完成它时,它都会执行(在 Python 中):

    for n in notifiers:
        if n.task_id == task_id:
            n.write_message('task %s done' % task_id)
    

    然后浏览器中的 Javascript 客户端检测到它正在等待的任务已经完成。

    请注意,客户端在实际将任务提交给服务器之前订阅有关任务的通知;这确保了没有竞争条件,即使服务器很快完成任务。

    【讨论】:

    • 我正在寻找更一般的解释而不是代码示例,但感谢您的精心回复。
    • 不客气!还有什么我可以帮忙的吗,或者你会接受我的回答吗?
    • 实际上,我目前正在使用队列和实时连接(类似于您的建议),但我希望使用内置机制或库。如果这是处理这些情况的最佳方法,我会接受你的回答...
    猜你喜欢
    • 1970-01-01
    • 2013-05-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多