Django channels的group_send方法无法正常工作

4

我正在尝试使用django-channels实现竞标模块。基本上,我会广播从客户端收到的任何消息,我的消费者部分如下代码片段所示:

class BidderConsumer(AsyncJsonWebsocketConsumer):

    async def connect(self):
        print("Connected")
        await self.accept()
        # Add to group
        self.channel_layer.group_add("bidding", self.channel_name)
        # Add channel to group
        await self.send_json({"msg_type": "connected"})

    async def receive_json(self, content, **kwargs):
        price = int(content.get("price"))
        item_id = int(content.get("item_id"))
        print("receive price ", price)
        print("receive item_id ", item_id)
        if not price or not item_id:
            await self.send_json({"error": "invalid argument"})

        item = await get_item(item_id)
        # Update bidding price
        if price > item.price:
            item.price = price
            await save_item(item)
            # Broadcast new bidding price
            print("performing group send")
            await self.channel_layer.group_send(
                "bidding",
                {
                    "type": "update.price"
                    "price": price,
                    "item_id": item_id
                }
            )

    async def update_price(self, event):
        print("sending new price")
        await self.send_json({
            "msg_type": "update",
            "item_id": event["item_id"],
            "price": event["price"],
        })

但是当我尝试从浏览器更新价格时,消费者可以收到消息,但它无法成功调用update_price函数。(sending new price从未被打印):

receive price  701
receive item_id  2
performing group send

我只是在按照这个例子进行操作: https://github.com/andrewgodwin/channels-examples/tree/master/multichat

如果有任何建议,将不胜感激!


它会打印“执行组发送”吗? - mehamasum
@mehamasum 感谢您的提问,是的,它打印了“执行组发送”。 - Jiang Wenbo
不要在群发中使用 await。 - Mohit Harshan
@MohitHarshan 我尝试在 group_send 中删除 await,但也不起作用。 - Jiang Wenbo
你的通道层是否已经启动运行?https://channels.readthedocs.io/en/latest/tutorial/part_2.html#enable-a-channel-layer - mehamasum
我解决了这个问题...当我执行“group_add”时,我太愚蠢了,错过了“await”。 - Jiang Wenbo
3个回答

2
最初的回答:基本上,从这个开始改变:

await self.channel_layer.group_send(
    "bidding",
    {
        "type": "update.price"
         "price": price,
         "item_id": item_id
    }
)

转换为:

await self.channel_layer.group_send(
     "bidding",
     {
         "type": "update_price"
         "price": price,
         "item_id": item_id
     }
)

请注意type键中的下划线。您的函数名为update_price,因此类型需要保持一致。"最初的回答"

9
实际上,在调用之前,通道层会将点转换为下划线。像websocket.connect这样的类型变成了websocket_connect。在协议级别上使用点符号更清晰,但可以使用任一符号。查看文档中的示例,你会发现它们也使用点符号。 - Ken4scholars

0

我曾经遇到过同样的问题。您可以尝试为channels_layer分配单独的Redis数据库。这可以通过在端口后添加Redis数据库编号 + '/{number_of_database}'来完成。

似乎是这样:'redis://' + REDIS_HOST + ':' + REDIS_PORT + '/1'

默认情况下,Redis实例有16个数据库(从0到15编号),但这可以在Redis配置文件中进行配置。每个数据库都是一个独立的命名空间,可以保存其自己的键和值集合。

请注意,在生产环境中使用Redis数据库时,最好将不同类型的数据分别放入不同的数据库,甚至是不同的Redis实例中,以避免冲突并提高性能。

在settings.py中

CHANNEL_LAYERS = {
    'default': {
        'BACKEND': 'channels_redis.core.RedisChannelLayer',
        'CONFIG': {
            "hosts": ['redis://' + REDIS_HOST + ':' + REDIS_PORT + '/1'],
        },
    },
}

0

这可能会对你有所帮助:
在routing.py中尝试使用path("", MainConsumer.as_asgi())而不是path("", MainConsumer)


尽管这段代码可能解决了问题,但是在答案中加入一个解释关于它是如何解决这个问题的会真正帮助提高您回复的质量,并可能导致更多的赞同。请记住,您正在为未来的读者回答问题,而不仅仅是现在提问的人。请[编辑]您的回答以添加解释,并给出适用的限制和假设的指示。 - Yunnosch

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接