Django Channels 测试失败

Posted

技术标签:

【中文标题】Django Channels 测试失败【英文标题】:Django Channels testing fails 【发布时间】:2018-06-05 08:40:37 【问题描述】:

我将 django-channels 放在一个基本的 django 站点上,配置方式如下。

consumers.py

from channels.generic.websocket import WebsocketConsumer
import json


class ChatConsumer(WebsocketConsumer):
    def connect(self):
        self.accept()

    def disconnect(self, close_code):
        pass

    def receive(self, text_data):
        text_data_json = json.loads(text_data)
        message = text_data_json['message']

        self.send(text_data=json.dumps(
            'message': message
        ))

routing.py

from django.conf.urls import url

from consumers import ChatConsumer

#supposed to be on the main routing
from channels.auth import AuthMiddlewareStack
from channels.routing import ProtocolTypeRouter, URLRouter

websocket_urlpatterns = [
    url(r'^ws/chat/$', ChatConsumer),
]

#after linking to above as chat.routing
application = ProtocolTypeRouter(
    # (http->django views is added by default)
    'websocket': AuthMiddlewareStack(
        URLRouter(
            websocket_urlpatterns
        )
    ),
)

settings.py

ASGI_APPLICATION = 'chatsys.routing.application'
CHANNEL_LAYERS = 
    'default': 
        'BACKEND': 'channels_redis.core.RedisChannelLayer',
        'CONFIG': 
            "hosts": [('35.185.80.98', 6379)],
        ,
    ,


INSTALLED_APPS = [
    ...
    'channels',
]

安装必要的应用程序后,我进入tutorial 中的下一步,该步骤正在外壳上进行测试。

In [1]: import channels.layers

In [2]: from asgiref.sync import async_to_sync

In [3]: async_to_sync(channel_layer.send)('test_channel', 'type': 'hello')
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-3-80e65666e9e2> in <module>()
----> 1 async_to_sync(channel_layer.send)('test_channel', 'type': 'hello')

NameError: name 'channel_layer' is not defined

In [4]: channel_layer = channels.layers.get_channel_layer()

In [5]: async_to_sync(channel_layer.send)('test_channel', 'type': 'hello')
---------------------------------------------------------------------------
TimeoutError                              Traceback (most recent call last)
<ipython-input-5-80e65666e9e2> in <module>()
----> 1 async_to_sync(channel_layer.send)('test_channel', 'type': 'hello')

~/webapp/chatenv/lib/python3.6/site-packages/asgiref/sync.py in __call__(self, *args, **kwargs)
     62             )
     63         # Wait for results from the future.
---> 64         return call_result.result()
     65 
     66     def __get__(self, parent, objtype):

/usr/lib/python3.6/concurrent/futures/_base.py in result(self, timeout)
    423                 raise CancelledError()
    424             elif self._state == FINISHED:
--> 425                 return self.__get_result()
    426 
    427             self._condition.wait(timeout)

...

    451 
    452     def _sock_connect(self, fut, sock, address):
/usr/lib/python3.6/asyncio/selector_events.py in _sock_connect_cb(self, fut, sock, address)
    478             if err != 0:
    479                 # Jump to any except clause below.
--> 480                 raise OSError(err, 'Connect call failed %s' % (address,))
    481         except (BlockingIOError, InterruptedError):
    482             # socket is still registered, the callback will be retried later
TimeoutError: [Errno 110] Connect call failed ('35.185.80.98', 6379)

连接失败并返回连接失败。 我认为问题可能是 redis 没有激活,所以我退出了 shell 并检查了结果。

(chatenv) muiruri_samuel@train:~/webapp/chatsys$ sudo docker run -p 6379:6379 -d redis:2.8
87ee2decc507984ffa153f7b9367a51786bc16ebf6ea330ebb0a030d99b60854
docker: Error response from daemon: driver failed programming external connectivity on endpoint infallible_payne (f40e48395d0e09e2741b1083b548ff2d0843f7ec150294
dbbb72acb3d5f61ea1): Bind for 0.0.0.0:6379 failed: port is already allocated.

所以端口已经分配并且正在运行。

【问题讨论】:

【参考方案1】:

发现问题是在设置而不是本地主机上设置服务器的 IP

CHANNEL_LAYERS = 
    'default': 
        'BACKEND': 'channels_redis.core.RedisChannelLayer',
        'CONFIG': 
            "hosts": [('127.0.0.1', 6379)],
        ,
    ,

所以把它换成这个就行了。

【讨论】:

【参考方案2】:

请检查服务器端口。是否可以从服务器外部连接。我的意思是它是从公共互联网连接的。我认为这就是问题所在。

在您的 Linux 终端或 Windows cmd 中运行此命令以检查端口是否可用于从您的物理机网络连接。

telnet 35.185.80.98 6379

【讨论】:

【参考方案3】:

使用以下代码:

from channels.layers import get_channel_layer
channel_layer = get_channel_layer()

【讨论】:

以上是关于Django Channels 测试失败的主要内容,如果未能解决你的问题,请参考以下文章

django-channels / websockets:WebSocketBadStatusException:握手状态200

列出连接到 django-channels 组的用户(频道 1.x)

Django Channels 错误:失败:在建立连接之前关闭 WebSocket

数据采集的flume架构

如何通过 Django Channels 将 cookie 添加到标头?

Django 通道 websocket 连接和断开连接(Nginx + Daphne + Django + Channels)