我有一个应用程序发送消息,应该广播到每个当前连接的客户端。让我们说客户数量可以达到数千。如何在不阻塞的情况下实现这种广播逻辑?
我认为会阻止的示例代码:
clients = []
class Broadcaster(tornado.websocket.WebSocketHandler):
def on_message(self, message):
for client in clients:
self.write_message(message)
我在网上找到的每个例子都与上面的代码类似。有一些使用@gen.coroutine
的例子,但我不明白这个装饰者在这种情况下如何提供帮助。
答案 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
然后,任务将添加到队列中,每个任务都会将您希望的消息发送给您的客户。 我希望有所帮助。