Reputation: 453
On the python side, I've created a 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)
On the javascript side, I start multiple clients (different browsers) at the same time with:
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));
}
All clients, as expected, finish at roughly the same time. However, each client's received messages are logged in the exact order (messageid
) that they were sent as if the WebSocketHandler
is queuing messages. Python logs on the server side reflect this as well.
So then, my questions are:
Note that this is not the real code but a reasonable facsimile.
Upvotes: 2
Views: 155
Reputation: 22154
You must never run "long, blocking calls" on the IOLoop thread, because that blocks everything else. That sleep
call (or whatever it's standing in for), must either be rewritten to be asynchronous or handed off to another thread (which is fairly easy with concurrent.futures.ThreadPoolExecutor
). See http://www.tornadoweb.org/en/stable/faq.html#why-isn-t-this-example-with-time-sleep-running-in-parallel for more on this.
Upvotes: 1