可以替代WILE循环,该循环不会阻塞反应器线程
问题描述
我正在制作一个Twisted聊天应用程序。假设我的服务器是这样设计的,每当它检测到客户端在线时,它就会在While循环中一个接一个地向客户端发送所有挂起的消息(该客户端的那些消息,因为它离线而被缓存在服务器上的python列表中),直到该列表耗尽。大概是这样的:
class MyChat(LineReceiver):
def connectionMade(self):
self.factory.clients.append(self)
while True:
#retrieve first message from a list of pending-messages(queue) of "self"
msg = self.retrieveFromQueue(self)
if msg != "empty":
self.transport.write(msg)
else:
break
def lineReceived(self, line):
...
def connectionLost(self, reason):
...
def retrieveFromQueue(self, who):
msglist = []
if who in self.factory.userMessages:
msglist = self.factory.userMessages[who]
if msglist != []:
msg = msglist.pop(0) #msglist is a list of strings
self.factory.userMessages[self] = msglist
return msg
else:
return "empty"
factory.userMessages = {} #dict of list of incoming messages of users who aren't online
因此,根据我对Twisted的理解,While循环将阻塞主反应器线程,来自任何其他客户端与服务器的任何交互都不会被服务器注册。如果是这种情况,我想要此方法的替代代码/方法,它不会阻止扭曲的线程。
更新:根据应用程序的性质,每个用户可能有2000-3000封挂起的消息。
解决方案
我认为https://glyph.twistedmatrix.com/2011/11/blocking-vs-running.html解决了这一点。
这里的答案取决于self.retrieveFromQueue(self)
到底做了什么。您暗示它是这样的:
if self.list_of_messages:
return self.list_of_messages.pop(0)
return b"empty"
如果是这样的话,答案是一回事。另一方面,如果实现更类似于:
return self.remote_mq_client.retrieve_queue_item(self.queue_identifier)
那么答案可能是完全不同的东西。但是,请注意,答案似乎取决于retrieveFromQueue
的实现。
有while
循环并不那么重要。while
循环反映这样一个事实(用Glyph的话说),此代码正在完成工作。
您可能会认为此循环所代表的工作量太大,不可能一次完成所有工作。如果有数以亿计的排队消息,则将它们逐个复制到连接的发送缓冲区可能会占用大量的时间和内存。在这种情况下,您可能希望考虑生产者/消费者模式和its support in Twisted。这不会减少(或增加)代码的"阻塞"程度,但会使代码一次运行的时间更短。
所以这里要回答的问题确实是:
- 是否
retrieveFromQueue
阻止 - 如果它不阻止,是否会有太多排队的消息,以至于处理它们都会导致
connectionMade
运行太长时间,以至于其他客户端注意到服务中断
相关文章