Search code examples
pythontornado

Broadcasting a message using Tornado


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.


Solution

  • 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 a yield gen.moment to the loop periodically:

    @gen.coroutine
    def broadcast_message(self, message):
        count = 0
        for client in self.clients:
            client.write_message(message)
            count += 1
            if count % 100 == 0:
                yield gen.moment