如何使用Django Channels多线程AsyncConsumer

时间:2018-09-12 14:46:44

标签: python django python-3.x multithreading django-channels

我已经在Django Channels工作了一个星期,并且有些东西使我陷入runworker并行性的困扰。

例如,我有这个MQTT客户端,它在收到基本消息时在通道中发布。

async def treat_message(msg):
    channel_layer = get_channel_layer()
    payload = json.loads(msg.payload, encoding="utf-8")

    await channel_layer.send("mqtt", {
        "type": "value.change",
        "message": payload
    })

这发送得很好。我可以发送我想要的数量,它将发送到Redis队列。到频道mqtt

然后,我运行工作程序,该工作程序将使用{p>重定向队列mqtt中的消息:

python manage.py runworker mqtt
2018-09-12 16:33:42,232 - INFO - runworker - Running worker for channels ['mqtt']

这是问题开始的地方。这是AsyncConsumer读取数据的内容:

class MQTTConsumer(AsyncConsumer):
    async def value_change(self, event):
        await asyncio.sleep(5)
        print("I received changes : {}".format(event["message"]))

为了模拟任务的完成,我睡了一段时间。这就是我要去的地方:异步使用者不是多线程的!当我向通道发送两条消息时,消费者需要10秒钟来处理第二条消息,如果它是多线程的,则需要5秒钟。如下所示。

2018-09-12 16:45:25,271 - INFO - runworker - Running worker for channels ['mqtt']
2018-09-12 16:45:32,559 - INFO - mqtt - I received changes : {'oui': 'non'}
2018-09-12 16:45:37,561 - INFO - mqtt - I received changes : {'oui': 'non'}
2018-09-12 16:45:42,563 - INFO - mqtt - I received changes : {'oui': 'non'}
2018-09-12 16:45:47,565 - INFO - mqtt - I received changes : {'oui': 'non'}

任何有关此主题的信息都会有很大的帮助,谢谢!!

编辑:我发现管理它的唯一方法是制作一个执行器,该执行器将包含工作人员以使其异步执行。但我不确定其用于部署目的的效率

def handle_mqtt(event):
    time.sleep(3)
    logger.info("I received changes : {}".format(event["message"]))


class MQTTConsumer(AsyncConsumer):
    def __init__(self, scope):
        super().__init__(scope)
        self.executor = concurrent.futures.ThreadPoolExecutor(max_workers=4)

    async def value_change(self, event):
        loop = asyncio.get_event_loop()
        future = loop.run_in_executor(self.executor, handle_mqtt, event)

1 个答案:

答案 0 :(得分:0)

这是目前设计的

  

是的,这是预期的设计,因为这是最安全的方法(如果您不了解它,则可以防止出现竞争情况)。如果您乐于并行运行消息,则只需在需要它们时就使用它们自己的协程(使用asyncio.create_task),确保您将它们清理干净并等待它们关闭。开销很大,因此希望我们将来会在消费者中采用这种选择模式,但目前我们提供的只是安全选项。

https://github.com/django/channels/issues/1203