无法使用 Django channels_redis 与 Heroku Redis 建立连接

Posted

技术标签:

【中文标题】无法使用 Django channels_redis 与 Heroku Redis 建立连接【英文标题】:Not able to establish connection with Heroku Redis using Django channels_redis 【发布时间】:2021-11-18 22:21:16 【问题描述】:

我在我的应用程序中使用 Django Channels 来实现人与人之间的聊天功能。为此我 使用使用“Redis”作为后备存储的 Django Channels 通道层。

我在 settings.py 中有以下配置:

CHANNEL_LAYERS = 
    "default": 
        "BACKEND": "channels_redis.core.RedisChannelLayer",
        "CONFIG": 
            "hosts": [os.environ.get('REDIS_URL', ("localhost", 6379))],
        ,
    ,

当“主机”指向本地主机时,CHANNEL_LAYERS 可以正常工作。 但是对于生产,当我试图确保通道层可以与 Heroku 上的 Redis 通信时,它不起作用。 使用Channels Docs中给出的代码如下所示,会出现以下错误

import channels.layers
>>> channel_layer = channels.layers.get_channel_layer()
>>> from asgiref.sync import async_to_sync
>>> async_to_sync(channel_layer.send)('test_channel', 'type': 'hello')
Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "/app/.heroku/python/lib/python3.7/site-packages/asgiref/sync.py", line 223, in __call__
    return call_result.result()
  File "/app/.heroku/python/lib/python3.7/concurrent/futures/_base.py", line 428, in result
    return self.__get_result()
  File "/app/.heroku/python/lib/python3.7/concurrent/futures/_base.py", line 384, in __get_result
    raise self._exception
  File "/app/.heroku/python/lib/python3.7/site-packages/asgiref/sync.py", line 292, in main_wrap
    result = await self.awaitable(*args, **kwargs)
  File "/app/.heroku/python/lib/python3.7/site-packages/channels_redis/core.py", line 299, in send
    async with self.connection(index) as connection:
  File "/app/.heroku/python/lib/python3.7/site-packages/channels_redis/core.py", line 835, in __aenter__
    self.conn = await self.pool.pop()
  File "/app/.heroku/python/lib/python3.7/site-packages/channels_redis/core.py", line 73, in pop
    conns.append(await aioredis.create_redis(**self.host, loop=loop))
  File "/app/.heroku/python/lib/python3.7/site-packages/aioredis/commands/__init__.py", line 175, in create_redis
    loop=loop)
  File "/app/.heroku/python/lib/python3.7/site-packages/aioredis/connection.py", line 133, in create_connection
    await conn.auth(password)
  File "/app/.heroku/python/lib/python3.7/site-packages/aioredis/util.py", line 52, in wait_ok
    res = await fut
  File "/app/.heroku/python/lib/python3.7/site-packages/aioredis/connection.py", line 186, in _read_data
    obj = await self._reader.readobj()
  File "/app/.heroku/python/lib/python3.7/site-packages/aioredis/stream.py", line 102, in readobj
    await self._wait_for_data('readobj')
  File "/app/.heroku/python/lib/python3.7/asyncio/streams.py", line 473, in _wait_for_data
    await self._waiter
  File "/app/.heroku/python/lib/python3.7/asyncio/selector_events.py", line 814, in _read_ready__data_received
    data = self._sock.recv(self.max_size)
ConnectionResetError: [Errno 104] Connection reset by peer

【问题讨论】:

【参考方案1】:

所以经过 Heroku 团队的大量研究和支持,可行的解决方案是对 channel_layers 进行以下设置

根据channels_redis指定主机的文档,我们可以创建符合create_connection的dicts,基本上就是这种方法:

aioredis.create_connection(address, *, db=0, password=None, ssl=None, encoding=None, parser=None, loop=None, timeout=None)

对于参数“ssl”,我们需要传递一个新的“ssl.SSLContext”。所以使用 'REDIS_TLS_URL' 的最终设置变为:

import ssl
new_context = ssl.SSLContext() # this sets the verify_mode to 'CERT_NONE'
host = [
        'address': f'rediss://REDIS_HOST:REDIS_PORT', # don't miss the 'rediss'!
        'db': REDIS_DB,
        'password': REDIS_PASSWORD,
        'ssl': new_context ,
    ]

CHANNEL_LAYERS = 
    'default': 
        'BACKEND': 'channels_redis.core.RedisChannelLayer',
        'CONFIG': 
            "hosts": host,
            "symmetric_encryption_keys": [SECRET_KEY],
        ,
    

使用上述设置出现以下错误

ssl.SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self signed certificate in certificate c
hain (_ssl.c:1076)

不再被抛出!

【讨论】:

以上是关于无法使用 Django channels_redis 与 Heroku Redis 建立连接的主要内容,如果未能解决你的问题,请参考以下文章

无法使用 Django runserver 提供静态文件

无法使用 angularjs 调用 django json 视图

使用django认证系统时login.html无法渲染

无法使用有效的用户名和密码登录 django 管理页面

Django:django-autocomplete-light 无法正常工作

无法在 Django 中使用动态图像 URL