【问题标题】:Listening to django channels channel_layer from outside of a consumer从消费者外部收听 django 频道 channel_layer
【发布时间】:2018-08-20 13:03:57
【问题描述】:

文档解释说可以从消费者外部发布到通道层:https://channels.readthedocs.io/en/latest/topics/channel_layers.html#using-outside-of-consumers 我需要做相反的事情。我有一个相当复杂的 python 脚本,它从 pubnub 读取实时数据,对其进行处理,然后通过 channel_layer 上的组将其推送给消费者。这很好用,但我需要消费者能够向这个脚本宣布他们的存在,以便它可以向他们推送数据(它目前只有在从 pubnub 获取新数据时才会推送到通道层,这可能是每 24 小时一次)。

我决定通过让消费者在连接时发布到“存在”频道来解决这个问题。我现在需要 pubnub 源脚本来收听这个频道。 我尝试将以下内容添加到脚本中,它不再引发错误,但它实际上并没有响应消息。它成功加入了通道层,但消息处理程序(receive_json) 永远不会触发。

from channels.generic.websocket import JsonWebsocketConsumer


class channelConsumer(JsonWebsocketConsumer):

    def __init__(self):
        self.channel_name = 'source'
    def join(self):
        async_to_sync(channel_layer.group_add)('presence', self.channel_name)
    def receive_json(self, message):
        print("Presence Detected")
        # do some stuff

在代码中进一步说明:

global channel_layer
channel_layer = get_channel_layer()

global listener
listener = channelConsumer()
listener.join()

正如我所说,没有明确的错误,它似乎永远不会触发接收json。肯定有数据包被发布到“存在”,所以问题肯定在下面的代码中。

【问题讨论】:

  • 这听起来像是一个 PubNub 问题,但没有包含 PubNub 代码。同时,我用pubnub 对其进行了标记,但如果您确定此处不需要 PubNub 洞察力,则可以将其删除。
  • @CraigConover 我会删除它,如果你不介意的话。 PubNub 是数据的原始来源,但这里的问题是通过通道层发送数据。原始来源可以是任何东西。
  • 明白。听起来好像需要额外的 PubNub 实现。干杯!

标签: websocket redis listener django-channels


【解决方案1】:

对于接收消息的消费者,需要将该消费者插入路由器。最常见的情况是使用 URLRouter,其中消费者将从连接(例如 Web 套接字)接收事件。

您可以使用 ChannelNameRouter 创建将侦听特定 Chanel 的使用者。例如,消费者可能是:

from channels.consumer import SyncConsumer
class ChannelConsumer(SyncConsumer):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

    def post_save(self, event):
        print("POSTSAVE", event)

然后在你的路由器定义上

from channels.routing import ProtocolTypeRouter, URLRouter,ChannelNameRouter
application = ProtocolTypeRouter({
    "websocket": TokenAuthMiddlewareStack(
        URLRouter([
            url(r"^.*$", RestConsumer),
        ]),
    ),
    "channel":ChannelNameRouter({
        "signals": ChannelConsumer,
    })

})

现在您可以向该消费者发送消息

from channels.layers import get_channel_layer
channel_layer = get_channel_layer()
async_to_sync(channel_layer.send)("signals", {"type": "post.save", "message":"Hello Consumer"})

特别针对您的情况,如果您希望多个通道接收消息,您还需要将“信号”通道添加到要使用的组中。

请注意,如果您使用 ChannelNameRouter,您将需要启动将处理它的工作人员。

./manage.py runworker signals

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-20
    • 2022-08-09
    • 2022-09-27
    • 2013-08-25
    • 2018-04-29
    • 2020-07-16
    相关资源
    最近更新 更多