关于我的情况的简短摘要: 我正在编写一个服务器(扭曲供电),该服务器处理与多个客户端(超过1000个)的WebSocket连接。从服务器发送到客户端的消息是通过Redis pub /子接口处理的(因为可以通过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()
会阻止/休眠该“虚拟线程”并将控制权传递给另一个虚拟线程吗?也许一个“全局”线程可以席卷所有客户端是更好的选择?
答案 0 :(得分:0)
inlineCallbacks
不会启动任何操作系统线程。它只是与使用Deferred
不同的界面。 Deferred
只是用于处理回调的API。
queue.get()
返回一个Deferred
。当您产生它时,inlineCallbacks
在内部为其添加回调,并且您的函数保持暂停状态。触发回调后,inlineCallbacks
会通过传递给回调的值(即您产生的Deferred
的“结果”)恢复函数。
所有发生的事情是正在创建一些Deferred
对象,并向其中添加了一些回调。在您的Redis客户端实现内部的某个地方,一些事件源正在“触发” Deferred
,其结果是开始调用其回调的过程。
您可以拥有许多这样的产品: *由于您拥有系统内存 *,因为redis客户端可以一次跟踪
我不知道有关如何实现Redis客户端的详细信息。如果必须为每个队列打开一个套接字,那么您可能会受限于可以打开的文件描述符的数目或系统可以支持的套接字的数目。这些数字可能会达到数万,而当您遇到这些数字时,您可以使用一些技巧来进一步提高限制。
如果不必为每个队列打开一个套接字(例如,如果它可以在单个套接字上多路复用所有队列的通知),那么它的限制可能会高得多(可能是由于算法复杂性所造成的)实施过程中最慢的部分)。