首页 > 解决方案 > 通道:为什么在处理结束时发送消息

问题描述

为什么使用同步功能get_channel_layer().send(),消息在处理结束时发送

def external_send(channel_name, data):
    channel_layer = get_channel_layer()
    send_sync = async_to_sync(channel_layer.send)
    send_sync(
        channel_name,
        {
            "type": "send_json",
            "message": {"datetime": datetime.datetime.now().isoformat(), **data},
        },
    )

self.send()按预期在消费者工作中使用

这是我用于测试目的的消费者类:

class TestConsumer(JsonWebsocketConsumer):
    def connect(self):
        self.accept()

    def disconnect(self, close_code):
        pass

    def receive_json(self, content, **kwargs):
        logger.debug(f"RECEIVE {content}")
        self.send_json(
            {
                "id": 1,
                "text": "Before sleep: self.send_json",
                "datetime": datetime.datetime.now().isoformat(),
            }
        )
        external_send(
            self.channel_name, {"id": 2, "text": "Before sleep external_send"}
        )
        sleep(10)  # Simuleting long processing
        self.send_json(
            {
                "id": 3,
                "text": "After sleep: self.send_json",
                "datetime": datetime.datetime.now().isoformat(),
            }
        )
        super().receive_json(content, **kwargs)
        logger.debug("END")

在前端我收到订单

在此处输入图像描述

标签: djangodjango-channelschannels

解决方案


作为回答,每个渠道消费者都有自己的小运行循环。它一次只处理一个事件。这个单一的运行循环用于从客户端(通过 ws)接收的消息和通过通道层上的组发送事件处理的消息。

如果你receive_json的方法你正在睡觉,那就是在睡觉循环,所以不会发生其他任何事情。receive_json需要在处理通过通道层发送的任何消息之前完成。

查看您的代码,还有其他几点需要指出

同步sleep

如果您确实需要sleep在一个方法中永远不要在同步方法中这样做,这将使您的整个python 程序休眠(一切都会休眠)。

使用异步消费者然后你就可以await asyncio.sleep(20)了,然后sleep你的单个消费者的运行循环和其他 websocket 连接等将继续运行。对于任何其他长时间运行的任务也是如此,您应该使用异步使用者,然后对await这些长时间运行的任务使用异步线程池。

您不应尝试send_json直接将组发送到该方法。

Intread 你应该在你的消费者上创建一个方法,handle_message这个方法可以调用send_json并且你的组发送应该发送带有 type 的消息handle.message


推荐阅读