Перекрутил много inlineCallbacks одновременно - PullRequest
0 голосов
/ 04 апреля 2019

Краткий обзор моей ситуации: я пишу сервер (витой с питанием), который обрабатывает соединения WebSocket с несколькими клиентами (более 1000).Сообщения, отправленные с сервера на клиент, обрабатываются через паб / подинтерфейс Redis (поскольку сообщения могут применяться через 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, который выполняет бесконечный цикл?Насколько я знаю, в витой есть настраиваемый лимит пула потоков.Что произойдет, если в пуле потоков будет больше клиентов (inlineCallbacks), чем потоков?Будет ли queue.get() блокировать / спать этот «виртуальный поток» и передавать управление другому?Может быть, лучше использовать один «глобальный» поток, охватывающий всех клиентов?

1 Ответ

0 голосов
/ 04 апреля 2019

inlineCallbacks не запускает никаких потоков ОС. Это просто другой интерфейс для использования Deferred. Deferred - это просто API для работы с обратными вызовами.

queue.get() возвращает Deferred. Когда вы его дадите, inlineCallbacks внутренне добавляет к нему обратный вызов, и ваша функция останется приостановленной. Когда сработает обратный вызов, inlineCallbacks возобновит вашу функцию со значением, переданным обратному вызову, что является «результатом» полученного вами Deferred.

Все, что происходит, - это создание Deferred объектов и добавление к ним некоторых обратных вызовов. Где-то внутри реализации вашего Redis-клиента, некоторые источники событий «запускают» Deferred с результатом, который запускает процесс вызова его обратных вызовов.

Вы можете иметь как можно больше из них: * поскольку у вас есть системная память для хранения * как клиент Redis может отслеживать одновременно

Я не знаю деталей того, как реализован ваш Redis-клиент. Если необходимо открыть сокет для каждой очереди, вы, вероятно, будете ограничены количеством дескрипторов файлов, которые вы можете открыть, или количеством сокетов, которые может поддерживать ваша система. Эти числа будут где-то в десятках тысяч, и когда вы натолкнетесь на них, вы можете использовать приемы для дальнейшего повышения лимита.

Если ему не нужно открывать сокет для каждой очереди (например, если он может мультиплексировать уведомления для всех очередей через один сокет), то он, вероятно, имеет предел, который намного, намного выше (возможно, обусловленный алгоритмической сложностью самой медленной части его реализации).

...