sycommon-python-lib 0.1.29__py3-none-any.whl → 0.1.40__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- sycommon/models/mqlistener_config.py +1 -0
- sycommon/rabbitmq/rabbitmq_client.py +205 -588
- sycommon/rabbitmq/rabbitmq_pool.py +141 -65
- sycommon/rabbitmq/rabbitmq_service.py +269 -145
- sycommon/services.py +64 -22
- sycommon/synacos/example.py +153 -0
- sycommon/synacos/example2.py +129 -0
- sycommon/synacos/feign.py +51 -436
- sycommon/synacos/feign_client.py +317 -0
- sycommon/synacos/nacos_service.py +1 -1
- sycommon/synacos/param.py +75 -0
- {sycommon_python_lib-0.1.29.dist-info → sycommon_python_lib-0.1.40.dist-info}/METADATA +1 -1
- {sycommon_python_lib-0.1.29.dist-info → sycommon_python_lib-0.1.40.dist-info}/RECORD +16 -12
- {sycommon_python_lib-0.1.29.dist-info → sycommon_python_lib-0.1.40.dist-info}/WHEEL +0 -0
- {sycommon_python_lib-0.1.29.dist-info → sycommon_python_lib-0.1.40.dist-info}/entry_points.txt +0 -0
- {sycommon_python_lib-0.1.29.dist-info → sycommon_python_lib-0.1.40.dist-info}/top_level.txt +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
|
|
1
|
+
import asyncio
|
|
2
|
+
from typing import List, Set
|
|
2
3
|
from aio_pika import connect_robust, Channel
|
|
3
4
|
from aio_pika.abc import AbstractRobustConnection
|
|
4
|
-
from aio_pika.pool import Pool
|
|
5
5
|
|
|
6
6
|
from sycommon.logging.kafka_log import SYLogger
|
|
7
7
|
|
|
@@ -9,7 +9,7 @@ logger = SYLogger
|
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
class RabbitMQConnectionPool:
|
|
12
|
-
"""RabbitMQ
|
|
12
|
+
"""RabbitMQ连接池管理(简化实现,避免上下文管理器冲突)"""
|
|
13
13
|
|
|
14
14
|
def __init__(
|
|
15
15
|
self,
|
|
@@ -33,72 +33,148 @@ class RabbitMQConnectionPool:
|
|
|
33
33
|
self.app_name = app_name or "rabbitmq-client"
|
|
34
34
|
self.heartbeat = heartbeat
|
|
35
35
|
|
|
36
|
-
#
|
|
37
|
-
self.connection_pool: Optional[Pool] = None
|
|
38
|
-
self.channel_pool: Optional[Pool] = None
|
|
36
|
+
# 连接池配置
|
|
39
37
|
self.connection_pool_size = connection_pool_size
|
|
40
38
|
self.channel_pool_size = channel_pool_size
|
|
41
39
|
|
|
40
|
+
# 实际存储的连接和通道
|
|
41
|
+
self._connections: List[AbstractRobustConnection] = []
|
|
42
|
+
self._free_channels: List[Channel] = []
|
|
43
|
+
self._used_channels: Set[Channel] = set()
|
|
44
|
+
|
|
45
|
+
# 锁用于线程安全
|
|
46
|
+
self._conn_lock = asyncio.Lock()
|
|
47
|
+
self._chan_lock = asyncio.Lock()
|
|
48
|
+
|
|
49
|
+
# 连接状态
|
|
50
|
+
self._initialized = False
|
|
51
|
+
|
|
42
52
|
async def init_pools(self):
|
|
43
|
-
"""
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
53
|
+
"""初始化连接池(创建指定数量的连接)"""
|
|
54
|
+
if self._initialized:
|
|
55
|
+
logger.warning("连接池已初始化,无需重复调用")
|
|
56
|
+
return
|
|
57
|
+
|
|
58
|
+
try:
|
|
59
|
+
# 创建核心连接(数量=connection_pool_size)
|
|
60
|
+
for i in range(self.connection_pool_size):
|
|
61
|
+
conn = await self._create_connection()
|
|
62
|
+
self._connections.append(conn)
|
|
63
|
+
# 为每个连接创建初始通道(数量=channel_pool_size//connection_pool_size)
|
|
64
|
+
chan_count_per_conn = self.channel_pool_size // self.connection_pool_size
|
|
65
|
+
for _ in range(chan_count_per_conn):
|
|
66
|
+
chan = await conn.channel()
|
|
67
|
+
self._free_channels.append(chan)
|
|
68
|
+
|
|
69
|
+
self._initialized = True
|
|
70
|
+
logger.info(
|
|
71
|
+
f"RabbitMQ连接池初始化成功 - 连接数: {len(self._connections)}, "
|
|
72
|
+
f"空闲通道数: {len(self._free_channels)}, 集群节点: {self.hosts}"
|
|
73
|
+
)
|
|
74
|
+
except Exception as e:
|
|
75
|
+
logger.error(f"连接池初始化失败: {str(e)}", exc_info=True)
|
|
76
|
+
# 清理异常状态
|
|
77
|
+
await self.close()
|
|
78
|
+
raise
|
|
79
|
+
|
|
80
|
+
async def _create_connection(self) -> AbstractRobustConnection:
|
|
81
|
+
"""创建单个RabbitMQ连接(支持集群节点轮询)"""
|
|
82
|
+
hosts = self.hosts.copy()
|
|
83
|
+
while hosts:
|
|
84
|
+
host = hosts.pop(0)
|
|
85
|
+
try:
|
|
86
|
+
connection = await connect_robust(
|
|
87
|
+
host=host,
|
|
88
|
+
port=self.port,
|
|
89
|
+
login=self.username,
|
|
90
|
+
password=self.password,
|
|
91
|
+
virtualhost=self.virtualhost,
|
|
92
|
+
heartbeat=self.heartbeat,
|
|
93
|
+
client_properties={
|
|
94
|
+
"connection_name": f"{self.app_name}@{host}"
|
|
95
|
+
},
|
|
96
|
+
reconnect_interval=2 # aio_pika 内置重连间隔
|
|
97
|
+
)
|
|
98
|
+
logger.info(f"成功连接到 RabbitMQ 节点: {host}:{self.port}")
|
|
99
|
+
return connection
|
|
100
|
+
except Exception as e:
|
|
101
|
+
logger.warning(
|
|
102
|
+
f"连接主机 {host}:{self.port} 失败,尝试下一个节点: {str(e)}")
|
|
103
|
+
if not hosts:
|
|
104
|
+
raise # 所有节点失败时抛出异常
|
|
105
|
+
|
|
106
|
+
async def acquire_channel(self) -> Channel:
|
|
107
|
+
"""获取通道(从空闲通道池获取,无则创建新通道)"""
|
|
108
|
+
if not self._initialized:
|
|
109
|
+
raise RuntimeError("连接池未初始化,请先调用 init_pools()")
|
|
110
|
+
|
|
111
|
+
async with self._chan_lock:
|
|
112
|
+
# 优先从空闲通道池获取
|
|
113
|
+
if self._free_channels:
|
|
114
|
+
channel = self._free_channels.pop()
|
|
115
|
+
# 检查通道是否有效
|
|
116
|
+
if not channel.is_closed:
|
|
117
|
+
self._used_channels.add(channel)
|
|
118
|
+
return channel
|
|
119
|
+
else:
|
|
120
|
+
logger.warning("发现无效通道,已自动清理")
|
|
121
|
+
|
|
122
|
+
# 空闲通道不足,创建新通道(不超过最大限制)
|
|
123
|
+
if len(self._used_channels) < self.channel_pool_size:
|
|
124
|
+
# 选择一个空闲连接创建通道
|
|
125
|
+
async with self._conn_lock:
|
|
126
|
+
for conn in self._connections:
|
|
127
|
+
if not conn.is_closed:
|
|
128
|
+
try:
|
|
129
|
+
channel = await conn.channel()
|
|
130
|
+
self._used_channels.add(channel)
|
|
131
|
+
logger.info(
|
|
132
|
+
f"创建新通道,当前通道数: {len(self._used_channels)}/{self.channel_pool_size}")
|
|
133
|
+
return channel
|
|
134
|
+
except Exception as e:
|
|
135
|
+
logger.warning(f"使用连接创建通道失败: {str(e)}")
|
|
136
|
+
# 所有连接都无效,尝试重新创建连接
|
|
137
|
+
conn = await self._create_connection()
|
|
138
|
+
self._connections.append(conn)
|
|
139
|
+
channel = await conn.channel()
|
|
140
|
+
self._used_channels.add(channel)
|
|
141
|
+
return channel
|
|
142
|
+
else:
|
|
143
|
+
raise RuntimeError(f"通道池已达最大限制: {self.channel_pool_size}")
|
|
144
|
+
|
|
145
|
+
async def release_channel(self, channel: Channel):
|
|
146
|
+
"""释放通道(归还到空闲通道池)"""
|
|
147
|
+
async with self._chan_lock:
|
|
148
|
+
if channel in self._used_channels:
|
|
149
|
+
self._used_channels.remove(channel)
|
|
150
|
+
# 通道有效则归还,无效则丢弃
|
|
151
|
+
if not channel.is_closed:
|
|
152
|
+
self._free_channels.append(channel)
|
|
153
|
+
else:
|
|
154
|
+
logger.warning("释放无效通道,已自动丢弃")
|
|
155
|
+
|
|
156
|
+
async def close(self):
|
|
157
|
+
"""关闭连接池(释放所有连接和通道)"""
|
|
158
|
+
# 释放所有通道
|
|
159
|
+
async with self._chan_lock:
|
|
160
|
+
for channel in self._free_channels + list(self._used_channels):
|
|
50
161
|
try:
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
port=self.port,
|
|
54
|
-
login=self.username,
|
|
55
|
-
password=self.password,
|
|
56
|
-
virtualhost=self.virtualhost,
|
|
57
|
-
heartbeat=self.heartbeat,
|
|
58
|
-
client_properties={
|
|
59
|
-
"connection_name": f"{self.app_name}@{host}"
|
|
60
|
-
}
|
|
61
|
-
)
|
|
162
|
+
if not channel.is_closed:
|
|
163
|
+
await channel.close()
|
|
62
164
|
except Exception as e:
|
|
63
|
-
logger.warning(
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
raise # 所有节点都失败时抛出异常
|
|
67
|
-
|
|
68
|
-
# 初始化连接池
|
|
69
|
-
self.connection_pool = Pool(
|
|
70
|
-
create_connection,
|
|
71
|
-
max_size=self.connection_pool_size
|
|
72
|
-
)
|
|
73
|
-
|
|
74
|
-
# 通道创建函数
|
|
75
|
-
async def create_channel() -> Channel:
|
|
76
|
-
async with self.connection_pool.acquire() as connection:
|
|
77
|
-
channel = await connection.channel()
|
|
78
|
-
return channel
|
|
79
|
-
|
|
80
|
-
# 初始化通道池
|
|
81
|
-
self.channel_pool = Pool(
|
|
82
|
-
create_channel,
|
|
83
|
-
max_size=self.channel_pool_size
|
|
84
|
-
)
|
|
85
|
-
|
|
86
|
-
logger.info(
|
|
87
|
-
f"RabbitMQ连接池初始化完成 - 连接池大小: {self.connection_pool_size}, "
|
|
88
|
-
f"通道池大小: {self.channel_pool_size}, 集群节点: {self.hosts}"
|
|
89
|
-
)
|
|
165
|
+
logger.warning(f"关闭通道失败: {str(e)}")
|
|
166
|
+
self._free_channels.clear()
|
|
167
|
+
self._used_channels.clear()
|
|
90
168
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
async def __aexit__(self, exc_type, exc, tb):
|
|
104
|
-
await self.close()
|
|
169
|
+
# 关闭所有连接
|
|
170
|
+
async with self._conn_lock:
|
|
171
|
+
for conn in self._connections:
|
|
172
|
+
try:
|
|
173
|
+
if not conn.is_closed:
|
|
174
|
+
await conn.close()
|
|
175
|
+
except Exception as e:
|
|
176
|
+
logger.warning(f"关闭连接失败: {str(e)}")
|
|
177
|
+
self._connections.clear()
|
|
178
|
+
|
|
179
|
+
self._initialized = False
|
|
180
|
+
logger.info("RabbitMQ连接池已完全关闭")
|