关于我的情况的简短说明:我正在编写一个服务器(扭曲供电),它处理多个客户端(超过1000个)的WebSocket连接。从服务器发送到客户端的消息通过Redis发布/子接口处理(因为消息可以通过REST应用)在该流程中:
现在,当客户端连接时,注册我正在为每个客户端启动inlineCallback
以扫描整个队列,如下所示:
@inlineCallbacks
def client_queue_handler(self, uuid):
queue = self.send_queue[uuid]
client = self.get_client(uuid)
while True:
uniqueID = yield queue.get()
client_context = self.redis_handler.get_single(uuid)
msg_context = next(iter([msg
for msg in client_context
if msg['unique'] == unique]),
None)
client.sendMessage(msg_context)
正如我之前所说,许多客户可能会联系。这是完全没问题,每个客户都有自己的inlineCallback
执行无限循环?据我所知,twisted有可定制的线程池限制。如果将有比线程池中的线程更多的客户端(inlineCallbacks)会发生什么? queue.get()
会阻止/睡眠“虚拟线程”并将控制传递给另一个吗?也许一个扫除所有客户的“全球”线程是更好的选择?
inlineCallbacks
没有启动任何操作系统线程。它只是使用Deferred
的不同界面。 Deferred
只是一个用于处理回调的API。
queue.get()
返回Deferred
。当你产生它时,inlineCallbacks
在内部添加一个回调函数,你的函数仍然被暂停。当回调触发时,inlineCallbacks
将使用传递给回调的值恢复您的函数 - 这是您产生的Deferred
的“结果”。
所有发生的事情都是正在创建一些Deferred
对象,并且正在向它们添加一些回调。在redis客户端实现的某个地方,一些事件源正在“触发”Deferred
,其结果是启动调用其回调的过程。
你可以拥有尽可能多的:*因为你有系统内存来保存*,因为redis客户端可以一次跟踪
我不知道你的redis客户端如何实现的细节。如果必须为每个队列打开一个套接字,那么您可能仅限于可以打开的文件描述符的数量或系统可以支持的套接字数量。这些数字将在成千上万的某个地方,当你碰到它们时,你可以部署一些技巧来进一步提高限制。
如果它不必为每个队列打开一个套接字(例如,如果它可以通过单个套接字复用所有队列的通知),那么它可能有一个更高,更高的限制(可能由最慢的算法复杂性强加)部分实施)。