我正在twisted
编写一个websocket服务器来学习框架。它将从rabbitmq
代理接收消息,并向连接的客户端发送更新。如果我想通过许多客户端连接一次广播/多播多条消息,那么调用(仅作为示例)deferToThread(channel.basic_consume, queue)
或callInThread(" ")
是一个非常好的选择吗?
如果没有,twisted
消费来自rabbitmq
的消息并将其转发给连接的客户端的方式是什么?
到目前为止,我的策略是:
reactor_thread: 监听端口(x)以设置和维护客户端连接
other_thread: 订阅rabbitmq队列并使用消息(如果有) (继续下去)
答案 0 :(得分:3)
调用(仅作为示例)deferToThread(channel.basic_consume,queue)或callInThread(“”)是一个非常好的选择吗?
在这种情况下使用线程实际上不会带来太多好处,因为消息已经在RabbitMQ中排队了。我过去一直处于类似的情况,我可以高度概述我在不使用线程的情况下解决问题的方法。免责声明:我没有使用RabbitMQ或Websockets一年或两年,所以我的知识可能有点模糊。
假设您正在将autobahn
用于websockets,您可以在工厂类(autobahn.twisted.websocket.WebSocketServerFactory
)中添加一个变量,该变量将跟踪已连接的客户端。 list
或dict
都可以正常使用。
factory = WebSocketServerFactory()
factory.connection_list = []
connection_list
变量将在建立连接后存储协议对象(autobahn.twisted.websocket.WebSocketServerProtocol
)。在协议中,您需要重载connectionMade
函数以将协议(在本例中为self
)附加到self.factory.connection_list
。
def connectionMade(self):
super(WSProtocol, self).connectionMade()
self.factory.connection_list.append(self)
最好为灵活性创建类似“onConnect deferred”的东西,但这是它的要点。也许autobahn
提供了这样做的界面。
使用pika
,您可以使用此example异步使用消息。根据需要对频道和交换名称进行更改,以使其适用于您的设置。然后我们将进行2次更改。首先,我们将factory.connection_list
传递给回调,然后当消息被消费时,我们会将其写入连接的客户端协议。
@defer.inlineCallbacks
def run(connection, proto_list):
#...
l = task.LoopingCall(read, queue_object, proto_list)
l.start(0.01)
@defer.inlineCallbacks
def read(queue_object, proto_list):
#...
if body:
print(body)
for client in sorted(proto_list):
yield client.write(body)
yield ch.basic_ack(delivery_tag=method.delivery_tag)
#...
d.addCallback(run, factory.connection_list)
reactor.run()
在read
回调函数中,每次使用消息时,循环任务将迭代连接的客户端列表并向其发送消息。