I have an app sending messages which should be broadcasted to every currently connected client. Lets say the clients count could go in thousands. How do I achieve this broadcasting logic without blocking?
Sample code that I think will block:
clients = []
class Broadcaster(tornado.websocket.WebSocketHandler):
def on_message(self, message):
for client in clients:
self.write_message(message)
Every example I found on the web was like the above code. There were some examples using @gen.coroutine
but I don't understand how this decorator could help in this scenario.
WebSocketHandler.write_message
does not block on network I/O, so it will be pretty fast, although it can still add up if you have huge numbers of clients. I suggest doing some performance testing to see how long it will actually take to broadcast a message (remember the size of the message matters, too, and it will be much faster to write a byte string than a dict since the dict will be re-encoded as json every time). If it turns out to take longer than you can tolerate blocking in your application, add ayield gen.moment
to the loop periodically:You could avoid this
for
loop there if this message can go to thousands as you said. I suggest you'd use a task service, like celery, to deliver the message. Then it'd be like:and the
celery_task()
method will be a celery task methodThen a task will be added to the queue and each task will send the message you desire to your clients. I hope that helps.