问题描述
我有一个应用程序发送消息,这些消息应该广播到每个当前连接的客户端.假设客户数量可能达到数千.如何在不阻塞的情况下实现这种广播逻辑?
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)
我在网上找到的每个例子都像上面的代码.有一些使用 @gen.coroutine
的例子,但我不明白这个装饰器如何在这种情况下提供帮助.
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
不会阻塞网络 I/O,所以它会很快,尽管如果它仍然可以加起来你有大量的客户.我建议做一些性能测试,看看广播一条消息实际需要多长时间(记住消息的大小也很重要,写字节字符串比写 dict 快得多,因为 dict 将被重新 -每次都编码为 json).如果结果证明花费的时间超过了您在应用程序中可以容忍的阻塞时间,请定期向循环添加 yield gen.moment
:
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
这篇关于使用 Tornado 广播消息的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!