【问题标题】:Alternative to a while loop in twisted which doesn't block the reactor thread替代一个不会阻塞反应器线程的扭曲的while循环
【发布时间】:2014-12-07 09:33:37
【问题描述】:

我正在制作一个扭曲的聊天应用程序。假设我的服务器的设计方式是,每当它检测到客户端在线时,它都会向客户端发送所有未决消息(该客户端的那些消息,因为它处于离线状态而被缓存在服务器上的 python 列表中)一个-在 while 循环中逐一递增,直到列表用完。像这样的:

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 条待处理消息。

【问题讨论】:

    标签: python twisted


    【解决方案1】:

    我认为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 运行时间过长以至于其他客户端注意到服务中断

    【讨论】:

    • 我已根据您需要的信息更新了问题。 retrieveFromQueue() 是你提到的两种类型中的前一种。
    • 好的。我猜你想要更多基于此的提示? :)
    • 是的!因此,如果是这些情况,我是否需要替代当前实现以使服务器保持交互(以及什么?),还是当前策略有效?
    • 请给点提示?我应该使用线程来运行该循环吗?因为根据我的测试,如果有 1000-2000 条消息,那么在该循环完成之前,服务器会对其他用户有些反应。
    猜你喜欢
    • 1970-01-01
    • 2017-11-15
    • 2019-11-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-21
    相关资源
    最近更新 更多