Как использовать несколько веб-сокетов с использованием каналов Django? - PullRequest
0 голосов
/ 21 сентября 2018

Я с удовольствием пользуюсь Django-Channels уже несколько месяцев.Тем не менее, я решил добавить второе зависимое от веб-сокета приложение в свой проект Django, и у меня возникли проблемы.

Я получаю ошибку websocket connection failed websocket is closed before the connection is established.Странно то, что первое приложение работало до того, как было развернуто второе приложение.Кроме того, первое приложение продолжает работать, пока второе приложение не запущено.

Документация Django Channels гласит:

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 не поддерживает маршрутизацию для нескольких соединений веб-сокетов.То есть я думаю, что пытаюсь использовать одно и то же соединение / порт веб-сокета для двух разных приложений.Мой 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-каналов?Является ли это возможным?Или я просто неправильно настраиваю вещи?

Ответы [ 2 ]

0 голосов
/ 20 июля 2019

Я наткнулся на это ТА, когда искал похожее решение.Если я понимаю решения, которые я видел до сих пор, все они потребуют указать потребителей в файле routing проекта Django, как указано в ответе выше (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-адресов для определенных потребителей в приложении, а не для проекта * 1009.* file. Учебное пособие просто указывает на chat.routing.websocket_urlpatterns, который является списком paths или * 1012. * Вы можете объединить эти списки для построения общей структуры маршрутизации проекта, что я и показал выше с +.

Я предполагаю, что это необходимо (и отличается от URL-адресов Django), потому что URLRouter ожидает один список, а URL-адреса Django (include('path.to.url')) в порядке со списком списков в файле URL проекта.

0 голосов
/ 25 сентября 2018

В соответствии с их реализацией и документацией ( здесь ), значение ProtocolTypeRouter является картой / диктом, и все, что они слушают или просматривают, это два типа ключей:

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

Что приводит к тому, что если вы передадите другой ключ, например websocket02, он не будет работать.Что, очевидно, означало бы, что должен быть способ объединить оба URL-адреса приложения через один и тот же websocket и создать отдельную конечную точку.

Фактически, вы можете сделать что-то вроде того, что они упомянули:

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

})

Приведенный выше пример основан на их реализации для двух конечных точек ( здесь ):

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

...