[BUG] redis-py does not use the "previously used host address" to connect when it gets a null/None response for the host during server redirects
Version: 4.5.5
Platform:
Ubuntu 20.04
Python 3.10.6
pip 22.0.2 from /usr/lib/python3/dist-packages/pip (python 3.10)
Redis cluster - redis-server version 7.0.11, All redis cluster member instances are accessible via the same hostname/IP address but on different ports.
Description:
When the Redis cluster is configured with cluster-preferred-endpoint-type unknown-endpoint, it indicates that the server doesn't know how clients can reach it during redirects. This is made clear to the client from the null/None response on the host field during redirects from the server. In this case, the server is expecting the client to reach out on the same endpoint it used for making the last request, but use the new port provided in the response.
This does not happen with redis-py. It tries to connect with the null/None hostname during redirects which is not the expected behavior from the server. This results in the following traceback.
Traceback (most recent call last):
File "/home/ubuntu/.local/lib/python3.10/site-packages/redis/connection.py", line 699, in connect
sock = self.retry.call_with_retry(
File "/home/ubuntu/.local/lib/python3.10/site-packages/redis/retry.py", line 46, in call_with_retry
return do()
File "/home/ubuntu/.local/lib/python3.10/site-packages/redis/connection.py", line 700, in <lambda>
lambda: self._connect(), lambda error: self.disconnect(error)
File "/home/ubuntu/.local/lib/python3.10/site-packages/redis/connection.py", line 1002, in _connect
raise err
File "/home/ubuntu/.local/lib/python3.10/site-packages/redis/connection.py", line 990, in _connect
sock.connect(socket_address)
ConnectionRefusedError: [Errno 111] Connection refused
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/home/ubuntu/.local/lib/python3.10/site-packages/redis/cluster.py", line 1119, in _execute_command
connection = get_connection(redis_node, *args, **kwargs)
File "/home/ubuntu/.local/lib/python3.10/site-packages/redis/cluster.py", line 47, in get_connection
return redis_node.connection or redis_node.connection_pool.get_connection(
File "/home/ubuntu/.local/lib/python3.10/site-packages/redis/connection.py", line 1457, in get_connection
connection.connect()
File "/home/ubuntu/.local/lib/python3.10/site-packages/redis/connection.py", line 705, in connect
raise ConnectionError(self._error_message(e))
redis.exceptions.ConnectionError: Error 111 connecting to None:6383. Connection refused.
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/home/ubuntu/.local/lib/python3.10/site-packages/redis/connection.py", line 699, in connect
sock = self.retry.call_with_retry(
File "/home/ubuntu/.local/lib/python3.10/site-packages/redis/retry.py", line 46, in call_with_retry
return do()
File "/home/ubuntu/.local/lib/python3.10/site-packages/redis/connection.py", line 700, in <lambda>
lambda: self._connect(), lambda error: self.disconnect(error)
File "/home/ubuntu/.local/lib/python3.10/site-packages/redis/connection.py", line 1002, in _connect
raise err
File "/home/ubuntu/.local/lib/python3.10/site-packages/redis/connection.py", line 990, in _connect
sock.connect(socket_address)
ConnectionRefusedError: [Errno 111] Connection refused
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/home/ubuntu/.local/lib/python3.10/site-packages/redis/cluster.py", line 1491, in initialize
if bool(r.info().get("cluster_enabled")) is False:
File "/home/ubuntu/.local/lib/python3.10/site-packages/redis/commands/core.py", line 991, in info
return self.execute_command("INFO", **kwargs)
File "/home/ubuntu/.local/lib/python3.10/site-packages/redis/client.py", line 1266, in execute_command
conn = self.connection or pool.get_connection(command_name, **options)
File "/home/ubuntu/.local/lib/python3.10/site-packages/redis/connection.py", line 1457, in get_connection
connection.connect()
File "/home/ubuntu/.local/lib/python3.10/site-packages/redis/connection.py", line 705, in connect
raise ConnectionError(self._error_message(e))
redis.exceptions.ConnectionError: Error 111 connecting to None:6381. Connection refused.
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/home/ubuntu/rc.py", line 93, in <module>
rc = RedisCluster(host=redis_cluster_node,
File "/home/ubuntu/.local/lib/python3.10/site-packages/redis/cluster.py", line 620, in __init__
self.commands_parser = CommandsParser(self)
File "/home/ubuntu/.local/lib/python3.10/site-packages/redis/commands/parser.py", line 16, in __init__
self.initialize(redis_connection)
File "/home/ubuntu/.local/lib/python3.10/site-packages/redis/commands/parser.py", line 19, in initialize
commands = r.execute_command("COMMAND")
File "/home/ubuntu/.local/lib/python3.10/site-packages/redis/cluster.py", line 1090, in execute_command
raise e
File "/home/ubuntu/.local/lib/python3.10/site-packages/redis/cluster.py", line 1076, in execute_command
res[node.name] = self._execute_command(node, *args, **kwargs)
File "/home/ubuntu/.local/lib/python3.10/site-packages/redis/cluster.py", line 1148, in _execute_command
self.nodes_manager.initialize()
File "/home/ubuntu/.local/lib/python3.10/site-packages/redis/cluster.py", line 1572, in initialize
raise RedisClusterException(
redis.exceptions.RedisClusterException: Redis Cluster cannot be connected. Please provide at least one reachable node: Error 111 connecting to None:6381. Connection refused.
Expected behavior:
When a server redirects a client with :new port, the client should connect using the same hostname/IP/endpoint it used previously to connect to the server but with the new port value indicated in the redirect.
Please let me check into the issue and get back to you.
This is a similar issue on other Redis clients. So far it seems to have been fixed on lettuce. It will soon be fixed on redis-cli - https://github.com/redis/redis/issues/12266
This issue is marked stale. It will be closed in 30 days if it is not updated.