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.
@@ -1,7 +1,7 @@
1
- from typing import Optional, List
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
- async def create_connection() -> AbstractRobustConnection:
46
- # 轮询选择主机(简单负载均衡)
47
- hosts = self.hosts.copy()
48
- while hosts:
49
- host = hosts.pop(0)
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
- return await connect_robust(
52
- host=host,
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
- f"连接主机 {host}:{self.port} 失败,尝试下一个节点: {str(e)}")
65
- if not hosts:
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
- async def close(self):
92
- """关闭连接池和通道池"""
93
- if self.channel_pool:
94
- await self.channel_pool.close()
95
- if self.connection_pool:
96
- await self.connection_pool.close()
97
- logger.info("RabbitMQ连接池已关闭")
98
-
99
- async def __aenter__(self):
100
- await self.init_pools()
101
- return self
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连接池已完全关闭")