Django - Channels 2.0:无法连接到消费者

Django - Channels 2.0: Unable to connect to consumer

在从频道 1.x 迁移到 2.x 之前,我正在做一些测试;我的原始代码将 csv 文件的值提取到数据库中。但是我目前无法与消费者建立连接。

settings.py

ASGI_APPLICATION = "UbiosData.routing.application"
CHANNEL_LAYERS = {
    "default": {
        "BACKEND": "channels_redis.core.RedisChannelLayer",
        "CONFIG": {
            "hosts": [("localhost", 6379)],
        },
    },
}

routing.py

from channels.routing import ProtocolTypeRouter, ChannelNameRouter
from .consumers import TestConsumer

application = ProtocolTypeRouter({
    "channel": ChannelNameRouter({
        "somename": TestConsumer,
    }),
})

consumers.py

from channels.consumer import SyncConsumer

class TestConsumer(SyncConsumer):

    def websocket_connect(self, event):
        print("websocket_connect")
        self.send({
            "type": "websocket.accept",
        })

    def websocket_receive(self, event):
        print("websocket_receive")
        self.send({
            "type": "websocket.send",
            "text": event["text"],
        })

    def test_send(self, message):
        print("Entering consumer")
        print(message["text"])

views.py

def test_channels(request):
    channel_layer = get_channel_layer()
    print(channel_layer)
    channel_layer.send("somename", {
        "type": "test.send",
        "text": "test"
    })
    return render(request, "data/data_index.html")

test_channels 函数中打印语句的结果:

RedisChannelLayer(hosts=[{'address': ('localhost', 6379)}])

消费者中的打印语句没有执行,我没有收到任何错误消息。 我正在使用 Python 3.5.3、通道 2.0.2 和通道-redis 2.0.2

编辑: 这是我使用 Channels 1.1.6 使用旧项目启动开发服务器时的输出:

Starting Channels development server at http://127.0.0.1:8000/
Channel layer default (asgi_redis.core.RedisChannelLayer)
Quit the server with CONTROL-C.
2018-02-16 16:46:48,604 - INFO - worker - Listening on channels http.request, ingest_equipment, ingest_values, websocket.connect, websocket.disconnect, websocket.receive
2018-02-16 16:46:48,606 - INFO - worker - Listening on channels http.request, ingest_equipment, ingest_values, websocket.connect, websocket.disconnect, websocket.receive
2018-02-16 16:46:48,608 - INFO - worker - Listening on channels http.request, ingest_equipment, ingest_values, websocket.connect, websocket.disconnect, websocket.receive
2018-02-16 16:46:48,609 - INFO - worker - Listening on channels http.request, ingest_equipment, ingest_values, websocket.connect, websocket.disconnect, websocket.receive
2018-02-16 16:46:48,611 - INFO - server - HTTP/2 support not enabled (install the http2 and tls Twisted extras)
2018-02-16 16:46:48,611 - INFO - server - Using busy-loop synchronous mode on channel layer
2018-02-16 16:46:48,611 - INFO - server - Listening on endpoint tcp:port=8000:interface=127.0.0.1

这是我使用 Channels 2.0.2 启动带有新项目的服务器时的输出:

Starting ASGI/Channels development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.
2018-02-16 17:05:08,331 - INFO - server - HTTP/2 support not enabled (install the http2 and tls Twisted extras)
2018-02-16 17:05:08,332 - INFO - server - Configuring endpoint tcp:port=8000:interface=127.0.0.1
2018-02-16 17:05:08,334 - INFO - server - Listening on TCP address 127.0.0.1:8000

你会注意到当我使用频道 2 时 "worker - Listening on channels" 不见了...

来自文档: "Remember that channel layers only support async methods, so you can either call it from your own asynchronous context" 或 "you’ll need to use async_to_sync"。由于您要发送给的消费者继承自同步 class (SyncConsumer),我认为第二个选项是您想要的。所以添加

from asgiref.sync import async_to_sync

再改

channel_layer.send("somename", {
    "type": "test.send",
    "text": "test"
})

async_to_sync(channel_layer.send)("somename", {
    "type": "test.send",
    "text": "test"
})

编辑:

是的,你是 spot-on:

You'll notice that "worker - Listening on channels" is missing when I use Channels 2...

由于您使用的是 ChannelNameRouter,因此您必须 运行 一个工作人员来处理 custom-named 频道上的事件。你可以这样做:

./manage.py runworker somename

如果您以后添加更多命名频道,也同样简单:

./manage.py runworker somename othername yetanothername

并且不要忘记按照上述方式进行 async_to_sync 业务,它仍然是必需的。