如何使用Django Channels使用多个websocket连接?

问题描述:

我已经很开心地使用Django-Channels了几个月了.但是,我去了第二个依赖websocket的应用程序到我的Django项目中,我遇到了麻烦.

I have been happily using Django-Channels for several months now. However, I went to add a second websocket dependent application to my Django project and I am running into trouble.

我得到的错误是 websocket连接失败websocket在建立连接之前已关闭.奇怪的是,第一个应用程序在部署第二个应用程序之前就已运行.此外,只要第二个应用程序没有运行,第一个应用程序就可以继续工作.

The error I am getting is websocket connection failed websocket is closed before the connection is established. What is odd is that the first application was working before the second application was deployed. Further, the first application continues to work so long as the second application is not running.

Django渠道文档说:

通道路由器仅在作用域级别上起作用,而不在单个事件级别上起作用,这意味着对于任何给定的连接,您只能有一个使用者.路由是要确定要由哪个使用者使用来建立连接,而不是如何将事件从一个连接中传播到多个使用者上.

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

I think this means that Django-Channels does not support routing for multiple websocket connections. That is, I think I am trying to use the same websocket connection/port for two different applications. My routing.py file looks as follows:

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

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

When I attempted to use the setup below, it could not find the path to the first application:

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连接?是否可以?还是我只是配置不正确?

How can I setup my Django application to serve up two different websocket connections using Django-Channels? Is it possible? Or am I just configuring things improperly?

根据其实现和文档说明(

According to their implementation and documention (here), the value to the ProtocolTypeRouter is a map/dict and all they listen or view for is two types of keys:

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

这带来了一个事实,那就是,如果您传递 websocket02 之类的不同密钥,将无法正常工作.显然,这意味着必须有一种方法可以通过相同的websocket组合两个APP网址并创建单独的终结点.

Which brings to the fact that if you pass different key like websocket02 it will not work. Which would obviously mean there has to be a way to combine both the APP url's via same websocket and create separate endpoint.

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

Infact, what you can do is, something like they have mentioned:

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),
        ])
    ),

})

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

The above example is based on their implementation for two endpoints (here):

application = ProtocolTypeRouter({

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

OR

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

route based on different channels under same websocket: https://github.com/django/channels/blob/master/docs/topics/routing.rst#channelnamerouter