Tornado WebSocketHandler可以异步接收消息吗?

时间:2015-11-02 18:33:40

标签: javascript python tornado coroutine

在python方面,我创建了一个WebSocketHandler

from tornado import gen
from tornado.escape import json_decode
from tornado.websocket import WebSocketHandler

class Echo(WebSocketHandler):
    ...
    @gen.coroutine
    def on_message(self, message):
        message = json_decode(message)
        response = yield self.do_echo(message)
        self.write_message(response)

    @gen.coroutine
    def do_echo(self, message):
        # emulate long, blocking call
        sleep(randint(0, 5))
        raise gen.Return(message)

在javascript方面,我同时启动多个客户端(不同的浏览器):

var ws = new WebSocket('ws://localhost:5000/echo');

ws.onmessage = function (evt) {
    console.log(JSON.parse(evt.data));
}

for (var i = 0; i < 10; i++) {
    var msg = {
        messageid: i,
        payload: 'An echo message.'
    };
    ws.send(JSON.stringify(msg));
}

正如预期的那样,所有客户大致在同一时间完成。但是,每个客户端收到的消息都按照发送它们的确切顺序(messageid)进行记录,就好像WebSocketHandler正在排队消息一样。服务器端的Python日志也反映了这一点。

那么,我的问题是:

  • 为什么每条消息都按照发送的顺序读取和返回?
  • 是否有可能规避这种排队行为?怎么样?
  • 我完全错过了令人尴尬的基本内容吗?

请注意,这不是真正的代码,而是合理的传真。

1 个答案:

答案 0 :(得分:1)

你必须永远不要在IOLoop线程上运行“长时间阻塞调用”,因为这会阻止其他所有内容。那个sleep调用(或者它所代表的任何东西)必须被重写为异步或者移交给另一个线程(concurrent.futures.ThreadPoolExecutor相当容易)。有关详情,请参阅http://www.tornadoweb.org/en/stable/faq.html#why-isn-t-this-example-with-time-sleep-running-in-parallel