【问题标题】:Twisted many inlineCallbacks at once一次扭曲了许多 inlineCallbacks
【发布时间】:2019-04-04 08:43:07
【问题描述】:

简要介绍一下我的情况: 我正在编写一个服务器(扭曲供电),它处理与多个客户端(超过 1000 个)的 WebSocket 连接。在该流程中,从服务器发送到客户端的消息通过 Redis pub/subinterface 处理(因为消息可以通过 REST 应用):

  • REST 将命令附加到客户端并发布,
  • twisted 被戳中,因为它订阅了那个 redis 频道,
  • 消息被添加到客户端队列并等待进一步处理

现在,当客户端连接并注册时,我将启动 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() 会阻止/休眠该“虚拟线程”并将控制权传递给另一个吗?也许一个覆盖所有客户端的“全局”线程是更好的选择?

【问题讨论】:

    标签: python twisted


    【解决方案1】:

    inlineCallbacks 不启动任何操作系统线程。这只是使用Deferred 的不同界面。 Deferred 只是一个处理回调的 API。

    queue.get() 返回一个Deferred。当您让出它时,inlineCallbacks 会在内部为其添加一个回调,并且您的函数将保持挂起状态。当回调触发时,inlineCallbacks 使用传递给回调的值恢复您的函数 - 这是您产生的 Deferred 的“结果”。

    所发生的只是一些Deferred 对象正在被创建并且一些回调被添加到它们。在你的 redis 客户端实现中的某个地方,一些事件源正在“触发”Deferred,其结果是开始调用其回调的过程。

    您可以拥有多个: * 因为你有系统内存可以保存 * 因为redis客户端可以一次跟踪

    我不知道你的redis客户端是如何实现的细节。如果它必须为每个队列打开一个套接字,那么您可能会受到可以打开的文件描述符数量或系统可以支持的套接字数量的限制。这些数字将达到数万,当您遇到它们时,您可以使用一些技巧来进一步提高限制。

    如果它不必为每个队列打开一个套接字(例如,如果它可以在一个套接字上为所有队列多路复用通知),那么它可能有一个非常非常高的限制(可能是算法复杂性强加的)最慢的部分)。

    【讨论】:

    • 感谢您提供有用且详细的回答!
    猜你喜欢
    • 2011-08-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多