使用Tornado广播消息

时间:2015-01-03 17:24:08

标签: python tornado

我有一个应用程序发送消息,应该广播到每个当前连接的客户端。让我们说客户数量可以达到数千。如何在不阻塞的情况下实现这种广播逻辑?

我认为会阻止的示例代码:

clients = []

class Broadcaster(tornado.websocket.WebSocketHandler):
   def on_message(self, message):
       for client in clients:
           self.write_message(message)

我在网上找到的每个例子都与上面的代码类似。有一些使用@gen.coroutine的例子,但我不明白这个装饰者在这种情况下如何提供帮助。

2 个答案:

答案 0 :(得分:6)

WebSocketHandler.write_message不会阻止网络I / O,所以它会非常快,尽管如果你有大量的客户端它仍然会加起来。我建议做一些性能测试,看看实际播放消息需要多长时间(记住消息的大小也很重要,写一个字节串比dict要快得多,因为dict将重新开始每次编码为json)。如果结果需要的时间超过您在应用程序中可以阻止的阻塞,请定期向循环添加yield gen.moment

@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

答案 1 :(得分:0)

你可以避免这个for循环,如果这个消息可以像你说的那样成千上万。我建议您使用celery之类的任务服务来传递消息。 然后它就像:

clients = []

class Broadcaster(tornado.websocket.WebSocketHandler):
   def on_message(self, message):
       for client in clients:
           celery_task(message)

并且celery_task()方法将是芹菜任务方法

@app.task
def celery_task(message):
    //logic

然后,任务将添加到队列中,每个任务都会将您希望的消息发送给您的客户。 我希望有所帮助。