使用龙卷风处理请求超时

时间:2014-07-02 08:55:29

标签: python asynchronous timeout tornado

我需要在Tornado服务器中处理一些长时间的请求。 我刚刚开始用Tornado了解异步代码的整个概念,似乎虽然这会让更多用户在处理我的长请求时与服务器进行交互,但它无法解决我的问题这是请求超时

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

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

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

1 个答案:

答案 0 :(得分:1)

Tornado的RequestHandler可以接受来自客户端的POST,将任务添加到队列中,并回答“好吧我得到了”:

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,并将其包含在POST的信息中。

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

那么如何通知客户任务完成?如果客户端是浏览器,我建议使用websocket连接。这是Tornado's websocket documentation。当有人访问您的页面时,某些Javascript应该打开与服务器的websocket连接。当访问者提交任务时,Javascript first 会生成task_id,订阅有关该task_id的通知,然后将任务信息POST到服务器。使用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客户端检测到它正在等待的任务已完成。

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