简体   繁体   English

用龙卷风处理请求超时

[英]handling request timeouts with tornado

I have some long requests that I need to handle in my Tornado server. 我在Tornado服务器中需要处理一些长请求。 I'm just starting to understand the whole concept of asynchronous code with Tornado, and it seems that while this will allow more users to interact with the server while it's processing my long requests, it will not solve my problem which is request timeouts . 我才刚刚开始了解Tornado异步代码的整个概念,似乎这将允许更多用户在处理我的长请求时与服务器进行交互,但这并不能解决我的问题,即请求超时

Asynchronous code works asynchronously in the server but the client remains synchronous, meaning that while the server can handle more requests, the client is "stuck" waiting for the response until a timeout occurs (am I wrong?) 异步代码在服务器中异步工作,但是客户端保持同步,这意味着虽然服务器可以处理更多请求,但客户端“卡住”了等待响应,直到发生超时(我错了吗?)

The question is, how do I solve the browser timeouts? 问题是,如何解决浏览器超时问题? In other words, I'm looking for a way to make a request from the client that will return immediately but process the request in the background. 换句话说,我正在寻找一种从客户端发出请求的方法,该方法将立即返回但在后台处理该请求。 When the processing is done, it should somehow inform the client. 处理完成后,应该以某种方式通知客户端。

Is there a builtin mechanism or library for that? 是否有内置的机制或库? What is the best way to handle this situation? 处理这种情况的最佳方法是什么?

Tornado's RequestHandler can accept a POST from the client, add the task to a queue, and respond "ok I got it": 龙卷风的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}))

The client should generate a unique task_id and include it in the information it POSTs. 客户端应该生成一个唯一的task_id,并将其包含在它发布的信息中。

If you want a more sophisticated task queue you can check out my Toro project . 如果您想要更复杂的任务队列,可以签出我的Toro项目 Or a simpler approach is to just use a Tornado PeriodicCallback to check often if there are tasks in the queue. 或更简单的方法是仅使用Tornado PeriodicCallback经常检查队列中是否有任务。

So how do you inform the client that a task is done? 那么,如何通知客户任务已完成? If the client is a browser, I suggest a websocket connection. 如果客户端是浏览器,则建议使用websocket连接。 Here's Tornado's websocket documentation . 这是Tornado的websocket文档 When someone visits your page, some Javascript should open a websocket connection to the server. 当有人访问您的页面时,某些Javascript应该会打开与服务器的websocket连接。 When the visitor submits a task, the Javascript first generates a task_id, subscribes for notifications about that task_id, and then it POSTs the task info to the server. 当访客提交任务时,JavaScript 首先会生成一个task_id,订阅有关该task_id的通知,然后将任务信息发布到服务器。 Javascript: 使用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}));
}

Here's the server's websocket handler: 这是服务器的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)

Now, whenever your code pulls a task from q and completes it, it does (in Python): 现在,只要您的代码从q提取任务并完成任务,它就会(在Python中)执行:

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

Then the Javascript client in the browser detects that the task it's waiting for is complete. 然后,浏览器中的Javascript客户端会检测到它正在等待的任务已完成。

Note that the client subscribes for notifications about a task before it actually submits the task to the server; 请注意,客户端在将任务实际提交给服务器之前先订阅了有关任务的通知; this ensures no race condition, even if the server finishes the task very quickly. 即使服务器非常快速地完成任务,这也可以确保不出现争用情况。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM