无法使用 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 建立连接的主要内容,如果未能解决你的问题,请参考以下文章
无法使用 angularjs 调用 django json 视图