我正在尝试将 Celery 连接到另一台计算机上的 Redis 后端,但出现无主机路由错误。从问题中删除 Celery,我可以使用主机名与 Redis 客户端连接,但使用 Redis url 时会得到相同的“无路由到主机”错误。
我尝试使用每种方法创建 2 个连接对象 1,两者看起来都很相似:
>>> import redis
>>>
>>> r = redis.Redis(host='server.domain.com',port=6379)
>>> r2 = redis.Redis.from_url('redis://server.domain.com:6379')
>>>
>>> r
Redis<ConnectionPool<Connection<host=server.domain.com,port=6379,db=0>>>
>>> r2
Redis<ConnectionPool<Connection<host=server.domain.com,port=6379,db=0>>>
主机名版本按预期工作:
>>> r.get('test')
b'Test stuff'
但是使用redis url的版本返回“没有到主机的路由”错误:
>>> r2.get('test')
Traceback (most recent call last):
File "/home/user/venv/lib/python3.10/site-packages/redis/connection.py", line 264, in connect
sock = self.retry.call_with_retry(
File "/home/user/venv/lib/python3.10/site-packages/redis/retry.py", line 46, in call_with_retry
return do()
File "/home/user/venv/lib/python3.10/site-packages/redis/connection.py", line 265, in <lambda>
lambda: self._connect(), lambda error: self.disconnect(error)
File "/home/user/venv/lib/python3.10/site-packages/redis/connection.py", line 627, in _connect
raise err
File "/home/user/venv/lib/python3.10/site-packages/redis/connection.py", line 615, in _connect
sock.connect(socket_address)
OSError: [Errno 113] No route to host
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/home/user/venv/lib/python3.10/site-packages/redis/commands/core.py", line 1829, in get
return self.execute_command("GET", name)
File "/home/user/venv/lib/python3.10/site-packages/redis/client.py", line 533, in execute_command
conn = self.connection or pool.get_connection(command_name, **options)
File "/home/user/venv/lib/python3.10/site-packages/redis/connection.py", line 1086, in get_connection
connection.connect()
File "/home/user/venv/lib/python3.10/site-packages/redis/connection.py", line 270, in connect
raise ConnectionError(self._error_message(e))
redis.exceptions.ConnectionError: Error 113 connecting to server.domain.com:6379. No route to host.
更新
进步。我对 redis 对象进行了更深入的研究,似乎 from_url 方法在创建 connection_pool 时遗漏了几个 kwargs:
>>> r.connection_pool.__dict__
{'connection_class': <class 'redis.connection.Connection'>, 'connection_kwargs': {'db': 0, 'username': None, 'password': None, 'socket_timeout': None, 'encoding': 'utf-8', 'encoding_errors': 'strict', 'decode_responses': True, 'retry_on_error': [], 'retry': None, 'health_check_interval': 0, 'client_name': None, 'lib_name': 'redis-py', 'lib_version': '5.0.1', 'redis_connect_func': None, 'credential_provider': None, 'protocol': 2, 'host': 'server.domain.com', 'port': 6379, 'socket_connect_timeout': None, 'socket_keepalive': None, 'socket_keepalive_options': None}, 'max_connections': 2147483648, '_fork_lock': <unlocked _thread.lock object at 0x7fcfd576ebc0>, '_lock': <unlocked _thread.lock object at 0x7fcfd576d2c0>, '_created_connections': 1, '_available_connections': [Connection<host=server.domain.com,port=6379,db=0>], '_in_use_connections': set(), 'pid': 37317}
>>> r2.connection_pool.__dict__
{'connection_class': <class 'redis.connection.Connection'>, 'connection_kwargs': {'host': 'server.domain.com', 'port': 6379, 'db': 0}, 'max_connections': 2147483648, '_fork_lock': <unlocked _thread.lock object at 0x7fcfd5d6bb40>, '_lock': <unlocked _thread.lock object at 0x7fcfd5d6bbc0>, '_created_connections': 1, '_available_connections': [Connection<host=server.domain.com,port=6379,db=0>], '_in_use_connections': set(), 'pid': 37317}
这修复了独立 Redis 客户端的连接,但似乎不适用于 Celery,同样的错误:
>>> r2 = redis.Redis.from_url('redis://:@server.domain.com:6379')
>>> r2.get('test')
b'Test stuff'
您在 Python 中使用 URL 格式连接到 Redis 后端时遇到的问题表明,与标准主机名和端口方法相比,redis.Redis.from_url 方法解释 URL 的方式存在细微差别。
考虑到直接主机名和端口方法工作正常(redis.Redis(host='server.domain.com', port=6379)),但 URL 方法(redis.Redis.from_url('redis://server. domain.com:6379')) 会导致“没有到主机的路由”错误。
您可以尝试 URL 解析来解决您的错误: from_url 方法可能会以不同的方式解析 URL。仔细检查 URL 的格式。确保没有拼写错误或意外字符。它的格式应该是 redis://server.domain.com:6379。