天天看點

【Azure Redis 緩存】 Python連接配接Azure Redis, 使用redis.ConnectionPool 出現

問題描述

Python連接配接Azure Redis, 使用redis.ConnectionPool 出現 "ConnectionResetError: [Errno 104] Connection reset by peer" "ConnectionResetError: [WinError 10054] An existing connection was forcibly closed by the remote host" 

Traceback (most recent call last):
  File "C:\Users\AppData\Local\Programs\Python\Python310\lib\site-packages\redis\connection.py", line 748, in read_response
    response = self._parser.read_response()
  File "C:\Users\AppData\Local\Programs\Python\Python310\lib\site-packages\redis\connection.py", line 318, in read_response
    raw = self._buffer.readline()
  File "C:\Users\AppData\Local\Programs\Python\Python310\lib\site-packages\redis\connection.py", line 250, in readline
    self._read_from_socket()
  File "C:\Users\AppData\Local\Programs\Python\Python310\lib\site-packages\redis\connection.py", line 192, in _read_from_socket
    data =ConnectionResetError: [WinError 10054] An existing connection was forcibly closed by the remote host... ...      

連接配接出錯的Python代碼為:

import redis

redis_params = {
    'host': 'redis-xxxxxx.redis.cache.chinacloudapi.cn',
    'port': 6380,
    'db': 1,
    'password': 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=',
    'timeout': 5000,
    'ssl': True
}

print('-----Try # 2------: Redis 使用連接配接池 ')

print('connected to redis by connection pool ...')
pool = redis.ConnectionPool( host=redis_params['host'], port=redis_params['port'], db=redis_params['db'], password=redis_params['password'], max_connections=20)
conn_pool = redis.Redis(connection_pool=pool, socket_timeout=redis_params['timeout'], ssl=redis_params['ssl'], health_check_interval=30)


conn_pool.set('test03', 'Value 結果顯示在此')
data = conn_pool.get('test03').decode()
print(data)

print('Connection Pool use Successful')      

而在不使用 ConnectionPool 的情況下,是能夠正常連接配接的。

print('-----Try # 1------: Redis 沒有使用連接配接池的情況下: ')
conn = redis.Redis(host=redis_params['host'], port=redis_params['port'], db=redis_params['db'], password=redis_params['password'], ssl=redis_params['ssl'], socket_timeout=redis_params['timeout'])
print('connected to redis')
conn.set('test', 'the normal value to set ')
print('set done .... ')      

問題解答

根據redis.py的源碼檢視,使用redis.Redis 當ssl為True時,構造函數中為 connection_class參數 初始化值為 SSLConnection。 而ConnectionPool的構造函數中預設使用的是 connection_class=Connection。

redis.Redis

【Azure Redis 緩存】 Python連接配接Azure Redis, 使用redis.ConnectionPool 出現

redis.ConnectionPool

【Azure Redis 緩存】 Python連接配接Azure Redis, 使用redis.ConnectionPool 出現

根據以上分析,要解決Python Redis使用Connection Pool連接配接,隻需要在建立Connection Pool對象時候,為Connection_class對象指派為SSLConnection。

修改後的代碼為:

import redis

from redis.connection import SSLConnection= {
    'host': 'redis-xxxxxx.redis.cache.chinacloudapi.cn',
    'port': 6380,
    'db': 1,
    'password': 'xxxxxxxxxxxxxxxxxxx=',
    'timeout': 5000,
    'ssl': True
}

print('-----Try # 1------: Redis 沒有使用連接配接池的情況下: ')
conn = redis.Redis(host=redis_params['host'], port=redis_params['port'], db=redis_params['db'], password=redis_params['password'], ssl=redis_params['ssl'], socket_timeout=redis_params['timeout'])
print('connected to redis')
conn.set('test', 'the normal value to set ')
print('set done .... ')

data = conn.get('test').decode()
print(str(data))

print('-----Try # 2------: Redis 使用連接配接池 ')

print('connected to redis by connection pool ...')
pool = redis.ConnectionPool(connection_class= SSLConnection, host=redis_params['host'], port=redis_params['port'], db=redis_params['db'], password=redis_params['password'], max_connections=20)
conn_pool = redis.Redis(connection_pool=pool, socket_timeout=redis_params['timeout'], ssl=redis_params['ssl'], health_check_interval=30)


conn_pool.set('test03', 'Value 結果顯示在此')
data = conn_pool.get('test03').decode()
print(data)

print('Connection Pool use Successful')

for i in range(1,10):
    conn_pool_1 = redis.Redis(connection_pool=pool, socket_timeout=redis_params['timeout'], ssl=redis_params['ssl'], health_check_interval=30)
    conn_pool_1.set('test_test__'+str(i), 'use conn pool to set value.......')
    print(conn_pool_1.client)
 

clist = conn_pool.client_list()
for c in clist:
    print(c)      

PS: 添加黃色高亮部分即可。

整體示範動畫如下:

【Azure Redis 緩存】 Python連接配接Azure Redis, 使用redis.ConnectionPool 出現

[END]

參考資料