代码之家  ›  专栏  ›  技术社区  ›  Scott Skiles

如何使用Django频道使用多个websocket连接?

  •  2
  • Scott Skiles  · 技术社区  · 7 年前

    我已经愉快地使用Django频道几个月了。然而,我去给我的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通道不支持多个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通道提供两个不同的websocket连接?有可能吗?还是我只是配置不当?

    1 回复  |  直到 7 年前
        1
  •  11
  •   Nagaraj Tantri    7 年前

    根据它们的实施和文件( here ),值 ProtocolTypeRouter

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

    如果你传递不同的键 websocket02 这是行不通的。这显然意味着必须有一种方法通过相同的websocket将两个应用程序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),
            ])
        ),
    })
    

    https://github.com/django/channels/blob/master/docs/topics/routing.rst#channelnamerouter

        2
  •  6
  •   Brian    7 年前

    我在寻找类似的解决方案时遇到了这个问题。如果我理解到目前为止看到的解决方案,它们都需要指定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的路由留给应用程序中的特定使用者,而不是项目 路由 文件。本教程只指向 chat.routing.websocket_urlpatterns paths urls 直接。您可以连接这些列表来构建您的整个项目路由结构,这就是我上面所展示的 +

    我假设这是必需的(与Django url不同),因为URLRouter需要一个列表,而Django url( include('path.to.url')