我有一些长请求,我需要在我的龙卷风服务器处理。我刚刚开始理解龙卷风异步代码的整个概念,似乎这将允许更多的用户与服务器交互,而它正在处理我的长请求,它不会解决我的问题,这是请求超时。
异步代码在服务器中异步工作,但客户端保持同步,这意味着当服务器可以处理更多请求时,客户端被"卡住"等待响应,直到超时发生(我错了吗?)
问题是,我如何解决浏览器超时?换句话说,我正在寻找一种方法,从客户端发出请求,将立即返回,但在后台处理请求。当处理完成时,它应该以某种方式通知客户端。
有内置机制或库吗?处理这种情况的最好方法是什么?
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,并将其包含在它发布的信息中。
如果你想要一个更复杂的任务队列,你可以看看我的Toro项目。或者更简单的方法是使用Tornado PeriodicCallback来经常检查队列中是否有任务。
那么如何通知客户端任务已经完成呢?如果客户端是浏览器,我建议使用websocket连接。这是Tornado的websocket文档。当有人访问你的页面时,一些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客户端检测到它正在等待的任务已经完成。
注意,客户端在将任务提交给服务器之前订阅了关于任务的通知;这确保了没有竞争条件,即使服务器非常快地完成任务。