【问题标题】:How to use multiple websocket connections using Django Channels?如何使用 Django Channels 使用多个 websocket 连接?
【发布时间】:2019-02-26 00:42:42
【问题描述】:

几个月来,我一直在愉快地使用 Django-Channels。但是,我在我的 Django 项目中添加了第二个依赖于 websocket 的应用程序,但我遇到了麻烦。

我得到的错误是websocket connection failed websocket is closed before the connection is established。奇怪的是,在部署第二个应用程序之前,第一个应用程序正在运行。此外,只要第二个应用程序没有运行,第一个应用程序就继续工作。

Django Channels documentation 说:

Channels routers only work on the scope level, not on the level of individual events, which means you can only have one consumer for any given connection. Routing is to work out what single consumer to give a connection, not how to spread events from one connection across multiple consumers.

我认为这意味着 Django-Channels 不支持多个 websocket 连接的路由。也就是说,我想我正在尝试为两个不同的应用程序使用相同的 websocket 连接/端口。我的routing.py 文件如下所示:

application = ProtocolTypeRouter({
    "websocket": AuthMiddlewareStack(
        URLRouter([
            path("first_application/stream/", app_1_consumers.AsyncApp1),
            path("second_application/stream/", app_2_consumers.AsyncApp2),
        ])
    )
})

当我尝试使用下面的设置时,它找不到第一个应用程序的路径:

application = ProtocolTypeRouter({
    "websocket": AuthMiddlewareStack(
        URLRouter([
            path("second_application/stream/", app_2_consumers.AsyncApp2),
        ])
    ),
    "websocket02": AuthMiddlewareStack(
        URLRouter([
            path("first_application/stream/", app_1_consumers.AsyncApp1),
        ])
    ),

})

如何设置我的 Django 应用程序以使用 Django-Channels 提供两个不同的 websocket 连接?可能吗?还是我只是配置不当?

【问题讨论】:

    标签: django websocket django-channels


    【解决方案1】:

    我在寻找类似解决方案时遇到了这个 SO。如果我理解到目前为止我所看到的解决方案,它们都需要在 Django 项目 routing 文件中指定消费者,如上面答案中提到的 (https://stackoverflow.com/a/52497306/8126390):

    application = ProtocolTypeRouter({
    
        # WebSocket chat handler
        "websocket": AuthMiddlewareStack(
            URLRouter([
                url(r"^chat/admin/$", AdminChatConsumer),
                url(r"^chat/$", PublicChatConsumer),
            ])
        ),
    })
    

    如果您想扩展教程,同时保持与教程相似的结构,您可以执行以下操作:

    application = ProtocolTypeRouter({
        # (http->django views is added by default)
        'websocket': AllowedHostsOriginValidator(
            AuthMiddlewareStack(
                URLRouter(
                    # Original chat connection
                    chat.routing.websocket_urlpatterns +
                    # Second chat connection
                    chat2.routing.websocket_urlpatterns
                )
            ),
        ),
    })
    

    这允许您将特定 URL 的路由留给应用程序中的特定消费者,而不是项目 routing 文件。本教程直接指向chat.routing.websocket_urlpatterns,它是pathsurls 的列表。您可以连接这些列表来构建您的整体项目路由结构,这就是我在上面用+ 展示的。

    我假设这是必需的(并且与 Django URL 不同),因为 URLRouter 需要一个列表,而 Django url (include('path.to.url')) 可以使用项目 URL 文件中的列表列表。

    【讨论】:

      【解决方案2】:

      根据他们的实现和文档 (here),ProtocolTypeRouter 的值是一个 map/dict,他们监听或查看的只是两种类型的键:

      ProtocolTypeRouter({
         "http": some_app,
         "websocket": some_other_app,
      })
      

      这带来了这样一个事实,如果您传递不同的密钥,例如 websocket02,它将无法正常工作。这显然意味着必须有一种方法可以通过相同的 websocket 组合两个 APP url 并创建单独的端点。

      事实上,你可以做的是,就像他们提到的那样:

      from django.conf.urls import url
      
      from channels.routing import ProtocolTypeRouter, URLRouter
      from channels.auth import AuthMiddlewareStack
      
      application = ProtocolTypeRouter({
      
          # WebSocket chat handler
          "websocket": AuthMiddlewareStack(
              URLRouter([
                  url(r"^first_application/stream/$", app_2_consumers.AsyncApp1Consumer),
                  url(r"^second_application/stream/$", app_2_consumers.AsyncApp2Consumer),
              ])
          ),
      
      })
      

      以上示例基于它们对两个端点 (here) 的实现:

      application = ProtocolTypeRouter({
      
          # WebSocket chat handler
          "websocket": AuthMiddlewareStack(
              URLRouter([
                  url(r"^chat/admin/$", AdminChatConsumer),
                  url(r"^chat/$", PublicChatConsumer),
              ])
          ),
      })
      

      同一websocket下基于不同通道的路由:https://github.com/django/channels/blob/master/docs/topics/routing.rst#channelnamerouter

      【讨论】:

        猜你喜欢
        • 2022-01-12
        • 2021-07-03
        • 2019-05-03
        • 1970-01-01
        • 2021-03-07
        • 2021-12-06
        • 1970-01-01
        • 2017-09-02
        • 2021-07-11
        相关资源
        最近更新 更多