sycommon-python-lib 0.1.16__py3-none-any.whl → 0.1.17__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.
Potentially problematic release.
This version of sycommon-python-lib might be problematic. Click here for more details.
- sycommon/rabbitmq/rabbitmq_client.py +194 -427
- sycommon/rabbitmq/rabbitmq_pool.py +104 -0
- sycommon/rabbitmq/rabbitmq_service.py +88 -85
- {sycommon_python_lib-0.1.16.dist-info → sycommon_python_lib-0.1.17.dist-info}/METADATA +1 -1
- {sycommon_python_lib-0.1.16.dist-info → sycommon_python_lib-0.1.17.dist-info}/RECORD +8 -7
- {sycommon_python_lib-0.1.16.dist-info → sycommon_python_lib-0.1.17.dist-info}/WHEEL +0 -0
- {sycommon_python_lib-0.1.16.dist-info → sycommon_python_lib-0.1.17.dist-info}/entry_points.txt +0 -0
- {sycommon_python_lib-0.1.16.dist-info → sycommon_python_lib-0.1.17.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
from typing import Optional, List
|
|
2
|
+
from aio_pika import connect_robust, Channel
|
|
3
|
+
from aio_pika.abc import AbstractRobustConnection
|
|
4
|
+
from aio_pika.pool import Pool
|
|
5
|
+
|
|
6
|
+
from sycommon.logging.kafka_log import SYLogger
|
|
7
|
+
|
|
8
|
+
logger = SYLogger
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class RabbitMQConnectionPool:
|
|
12
|
+
"""RabbitMQ连接池管理,负责创建和管理连接池与通道池"""
|
|
13
|
+
|
|
14
|
+
def __init__(
|
|
15
|
+
self,
|
|
16
|
+
hosts: List[str],
|
|
17
|
+
port: int,
|
|
18
|
+
username: str,
|
|
19
|
+
password: str,
|
|
20
|
+
virtualhost: str = "/",
|
|
21
|
+
connection_pool_size: int = 2,
|
|
22
|
+
channel_pool_size: int = 10,
|
|
23
|
+
heartbeat: int = 10,
|
|
24
|
+
app_name: str = ""
|
|
25
|
+
):
|
|
26
|
+
self.hosts = [host.strip() for host in hosts if host.strip()]
|
|
27
|
+
if not self.hosts:
|
|
28
|
+
raise ValueError("至少需要提供一个RabbitMQ主机地址")
|
|
29
|
+
self.port = port
|
|
30
|
+
self.username = username
|
|
31
|
+
self.password = password
|
|
32
|
+
self.virtualhost = virtualhost
|
|
33
|
+
self.app_name = app_name or "rabbitmq-client"
|
|
34
|
+
self.heartbeat = heartbeat
|
|
35
|
+
|
|
36
|
+
# 连接池和通道池
|
|
37
|
+
self.connection_pool: Optional[Pool] = None
|
|
38
|
+
self.channel_pool: Optional[Pool] = None
|
|
39
|
+
self.connection_pool_size = connection_pool_size
|
|
40
|
+
self.channel_pool_size = channel_pool_size
|
|
41
|
+
|
|
42
|
+
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)
|
|
50
|
+
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
|
+
)
|
|
62
|
+
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
|
+
)
|
|
90
|
+
|
|
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()
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import asyncio
|
|
2
|
-
import logging
|
|
3
2
|
from typing import (
|
|
4
3
|
Callable, Coroutine, Dict, List, Optional, Type, Union, Any, Set
|
|
5
4
|
)
|
|
@@ -11,15 +10,14 @@ from sycommon.models.mqlistener_config import RabbitMQListenerConfig
|
|
|
11
10
|
from sycommon.models.mqsend_config import RabbitMQSendConfig
|
|
12
11
|
from sycommon.models.sso_user import SsoUser
|
|
13
12
|
from sycommon.logging.kafka_log import SYLogger
|
|
14
|
-
from .rabbitmq_client import RabbitMQClient
|
|
13
|
+
from sycommon.rabbitmq.rabbitmq_client import RabbitMQClient, RabbitMQConnectionPool
|
|
15
14
|
|
|
16
15
|
logger = SYLogger
|
|
17
16
|
|
|
18
17
|
|
|
19
18
|
class RabbitMQService:
|
|
20
19
|
"""
|
|
21
|
-
RabbitMQ
|
|
22
|
-
负责客户端的创建、配置、生命周期管理和错误处理
|
|
20
|
+
RabbitMQ服务封装,管理多个客户端实例,基于连接池实现资源复用
|
|
23
21
|
"""
|
|
24
22
|
|
|
25
23
|
# 保存多个客户端实例
|
|
@@ -45,11 +43,13 @@ class RabbitMQService:
|
|
|
45
43
|
_has_senders: bool = False
|
|
46
44
|
# 消费启动超时设置
|
|
47
45
|
CONSUMER_START_TIMEOUT = 30 # 30秒超时
|
|
46
|
+
# 连接池实例
|
|
47
|
+
_connection_pool: Optional[RabbitMQConnectionPool] = None
|
|
48
48
|
|
|
49
49
|
@classmethod
|
|
50
50
|
def init(cls, config: dict, has_listeners: bool = False, has_senders: bool = False) -> Type['RabbitMQService']:
|
|
51
51
|
"""
|
|
52
|
-
初始化RabbitMQ
|
|
52
|
+
初始化RabbitMQ服务(支持集群配置),同时创建连接池
|
|
53
53
|
"""
|
|
54
54
|
from sycommon.synacos.nacos_service import NacosService
|
|
55
55
|
|
|
@@ -70,13 +70,63 @@ class RabbitMQService:
|
|
|
70
70
|
cls._has_listeners = has_listeners
|
|
71
71
|
cls._has_senders = has_senders
|
|
72
72
|
|
|
73
|
+
# 初始化连接池(在单独的异步方法中启动)
|
|
74
|
+
asyncio.create_task(cls._init_connection_pool())
|
|
75
|
+
|
|
73
76
|
return cls
|
|
74
77
|
|
|
75
78
|
@classmethod
|
|
76
|
-
async def
|
|
79
|
+
async def _init_connection_pool(cls):
|
|
80
|
+
"""初始化连接池(异步操作)"""
|
|
81
|
+
if cls._connection_pool or not cls._config:
|
|
82
|
+
return
|
|
83
|
+
|
|
84
|
+
try:
|
|
85
|
+
# 解析集群节点
|
|
86
|
+
hosts_str = cls._config.get('host', "")
|
|
87
|
+
hosts_list = [host.strip()
|
|
88
|
+
for host in hosts_str.split(',') if host.strip()]
|
|
89
|
+
if not hosts_list:
|
|
90
|
+
raise ValueError("RabbitMQ集群配置为空,请检查host参数")
|
|
91
|
+
|
|
92
|
+
# 创建连接池
|
|
93
|
+
cls._connection_pool = RabbitMQConnectionPool(
|
|
94
|
+
hosts=hosts_list,
|
|
95
|
+
port=cls._config.get('port', 5672),
|
|
96
|
+
username=cls._config.get('username', ""),
|
|
97
|
+
password=cls._config.get('password', ""),
|
|
98
|
+
virtualhost=cls._config.get('virtual-host', "/"),
|
|
99
|
+
connection_pool_size=cls._config.get(
|
|
100
|
+
'connection_pool_size', 2), # 连接池大小
|
|
101
|
+
channel_pool_size=cls._config.get(
|
|
102
|
+
'channel_pool_size', 10), # 通道池大小
|
|
103
|
+
heartbeat=cls._config.get('heartbeat', 10),
|
|
104
|
+
app_name=cls._config.get("APP_NAME", "")
|
|
105
|
+
)
|
|
106
|
+
|
|
107
|
+
# 初始化连接池
|
|
108
|
+
await cls._connection_pool.init_pools()
|
|
109
|
+
logger.info("RabbitMQ连接池初始化成功")
|
|
110
|
+
|
|
111
|
+
except Exception as e:
|
|
112
|
+
logger.error(f"RabbitMQ连接池初始化失败: {str(e)}", exc_info=True)
|
|
113
|
+
# 连接池初始化失败时重试
|
|
114
|
+
await asyncio.sleep(1)
|
|
115
|
+
asyncio.create_task(cls._init_connection_pool())
|
|
116
|
+
|
|
117
|
+
@classmethod
|
|
118
|
+
async def _create_client(cls, queue_name: str, **kwargs) -> RabbitMQClient:
|
|
77
119
|
"""
|
|
78
|
-
创建RabbitMQ
|
|
120
|
+
创建RabbitMQ客户端实例(基于连接池)
|
|
79
121
|
"""
|
|
122
|
+
if not cls._connection_pool:
|
|
123
|
+
# 等待连接池初始化
|
|
124
|
+
start_time = asyncio.get_event_loop().time()
|
|
125
|
+
while not cls._connection_pool:
|
|
126
|
+
if asyncio.get_event_loop().time() - start_time > 30:
|
|
127
|
+
raise TimeoutError("等待连接池初始化超时")
|
|
128
|
+
await asyncio.sleep(1)
|
|
129
|
+
|
|
80
130
|
app_name = kwargs.get('app_name', cls._config.get(
|
|
81
131
|
"APP_NAME", "")) if cls._config else ""
|
|
82
132
|
|
|
@@ -100,20 +150,9 @@ class RabbitMQService:
|
|
|
100
150
|
f"允许创建: {create_if_not_exists}"
|
|
101
151
|
)
|
|
102
152
|
|
|
103
|
-
# 将逗号分隔的host字符串拆分为集群节点列表
|
|
104
|
-
hosts_str = mq_config.get('host', "")
|
|
105
|
-
hosts_list = [host.strip()
|
|
106
|
-
for host in hosts_str.split(',') if host.strip()]
|
|
107
|
-
if not hosts_list:
|
|
108
|
-
raise ValueError("RabbitMQ集群配置为空,请检查host参数")
|
|
109
|
-
|
|
110
153
|
return RabbitMQClient(
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
username=mq_config.get('username', ""),
|
|
114
|
-
password=mq_config.get('password', ""),
|
|
115
|
-
virtualhost=mq_config.get('virtual-host', "/"),
|
|
116
|
-
exchange_name=mq_config.get(
|
|
154
|
+
connection_pool=cls._connection_pool, # 传入连接池实例
|
|
155
|
+
exchange_name=cls._config.get(
|
|
117
156
|
'exchange_name', "system.topic.exchange"),
|
|
118
157
|
exchange_type=kwargs.get('exchange_type', "topic"),
|
|
119
158
|
queue_name=processed_queue_name,
|
|
@@ -125,11 +164,9 @@ class RabbitMQService:
|
|
|
125
164
|
create_if_not_exists=create_if_not_exists,
|
|
126
165
|
connection_timeout=kwargs.get('connection_timeout', 10),
|
|
127
166
|
rpc_timeout=kwargs.get('rpc_timeout', 5),
|
|
128
|
-
app_name=app_name,
|
|
129
167
|
reconnection_delay=kwargs.get('reconnection_delay', 1),
|
|
130
168
|
max_reconnection_attempts=kwargs.get(
|
|
131
169
|
'max_reconnection_attempts', 5),
|
|
132
|
-
heartbeat=kwargs.get('heartbeat', 10),
|
|
133
170
|
prefetch_count=kwargs.get('prefetch_count', 2),
|
|
134
171
|
consumption_stall_threshold=kwargs.get(
|
|
135
172
|
'consumption_stall_threshold', 10)
|
|
@@ -141,15 +178,19 @@ class RabbitMQService:
|
|
|
141
178
|
client_name: str = "default", ** kwargs
|
|
142
179
|
) -> RabbitMQClient:
|
|
143
180
|
"""
|
|
144
|
-
获取或创建RabbitMQ
|
|
145
|
-
|
|
146
|
-
:param client_name: 客户端名称
|
|
147
|
-
:param kwargs: 客户端参数
|
|
148
|
-
:return: RabbitMQClient实例
|
|
181
|
+
获取或创建RabbitMQ客户端(基于连接池)
|
|
149
182
|
"""
|
|
150
183
|
if not cls._config:
|
|
151
184
|
raise ValueError("RabbitMQService尚未初始化,请先调用init方法")
|
|
152
185
|
|
|
186
|
+
# 等待连接池就绪
|
|
187
|
+
if not cls._connection_pool:
|
|
188
|
+
start_time = asyncio.get_event_loop().time()
|
|
189
|
+
while not cls._connection_pool:
|
|
190
|
+
if asyncio.get_event_loop().time() - start_time > 30:
|
|
191
|
+
raise TimeoutError("等待连接池初始化超时")
|
|
192
|
+
await asyncio.sleep(1)
|
|
193
|
+
|
|
153
194
|
# 确保锁存在
|
|
154
195
|
if client_name not in cls._init_locks:
|
|
155
196
|
cls._init_locks[client_name] = asyncio.Lock()
|
|
@@ -184,7 +225,6 @@ class RabbitMQService:
|
|
|
184
225
|
if is_sender:
|
|
185
226
|
kwargs['create_if_not_exists'] = False
|
|
186
227
|
client = await cls._create_client(
|
|
187
|
-
cls._config,
|
|
188
228
|
initial_queue_name,
|
|
189
229
|
app_name=cls._config.get("APP_NAME", ""),
|
|
190
230
|
**kwargs
|
|
@@ -200,7 +240,6 @@ class RabbitMQService:
|
|
|
200
240
|
if initial_queue_name in cls._initialized_queues:
|
|
201
241
|
logger.debug(f"队列 '{initial_queue_name}' 已初始化,直接创建客户端")
|
|
202
242
|
client = await cls._create_client(
|
|
203
|
-
cls._config,
|
|
204
243
|
initial_queue_name, ** kwargs
|
|
205
244
|
)
|
|
206
245
|
await client.connect(declare_queue=True)
|
|
@@ -209,7 +248,6 @@ class RabbitMQService:
|
|
|
209
248
|
|
|
210
249
|
# 创建并连接客户端
|
|
211
250
|
client = await cls._create_client(
|
|
212
|
-
cls._config,
|
|
213
251
|
initial_queue_name,
|
|
214
252
|
app_name=cls._config.get("APP_NAME", ""),
|
|
215
253
|
**kwargs
|
|
@@ -234,16 +272,11 @@ class RabbitMQService:
|
|
|
234
272
|
cls._clients[client_name] = client
|
|
235
273
|
return client
|
|
236
274
|
|
|
275
|
+
# 以下方法逻辑与原有保持一致(无需修改)
|
|
237
276
|
@classmethod
|
|
238
277
|
async def setup_senders(cls, senders: List[RabbitMQSendConfig], has_listeners: bool = False) -> None:
|
|
239
|
-
"""
|
|
240
|
-
设置消息发送器
|
|
241
|
-
|
|
242
|
-
:param senders: 发送器配置列表
|
|
243
|
-
:param has_listeners: 是否同时存在监听器
|
|
244
|
-
"""
|
|
278
|
+
"""设置消息发送器"""
|
|
245
279
|
cls._has_senders = True
|
|
246
|
-
# 保存监听器存在状态
|
|
247
280
|
cls._has_listeners = has_listeners
|
|
248
281
|
logger.info(f"开始设置 {len(senders)} 个消息发送器")
|
|
249
282
|
|
|
@@ -300,14 +333,8 @@ class RabbitMQService:
|
|
|
300
333
|
|
|
301
334
|
@classmethod
|
|
302
335
|
async def setup_listeners(cls, listeners: List[RabbitMQListenerConfig], has_senders: bool = False) -> None:
|
|
303
|
-
"""
|
|
304
|
-
设置消息监听器
|
|
305
|
-
|
|
306
|
-
:param listeners: 监听器配置列表
|
|
307
|
-
:param has_senders: 是否同时存在发送器
|
|
308
|
-
"""
|
|
336
|
+
"""设置消息监听器"""
|
|
309
337
|
cls._has_listeners = True
|
|
310
|
-
# 保存发送器存在状态
|
|
311
338
|
cls._has_senders = has_senders
|
|
312
339
|
logger.info(f"开始设置 {len(listeners)} 个消息监听器")
|
|
313
340
|
|
|
@@ -337,16 +364,11 @@ class RabbitMQService:
|
|
|
337
364
|
|
|
338
365
|
@classmethod
|
|
339
366
|
async def _verify_consumers_started(cls, timeout: int = 30) -> None:
|
|
340
|
-
"""
|
|
341
|
-
验证消费者是否成功启动
|
|
342
|
-
|
|
343
|
-
:param timeout: 超时时间(秒)
|
|
344
|
-
"""
|
|
367
|
+
"""验证消费者是否成功启动"""
|
|
345
368
|
start_time = asyncio.get_event_loop().time()
|
|
346
369
|
required_clients = list(cls._message_handlers.keys())
|
|
347
370
|
running_clients = []
|
|
348
371
|
|
|
349
|
-
# 等待所有消费者启动或超时
|
|
350
372
|
while len(running_clients) < len(required_clients) and \
|
|
351
373
|
(asyncio.get_event_loop().time() - start_time) < timeout:
|
|
352
374
|
|
|
@@ -357,14 +379,12 @@ class RabbitMQService:
|
|
|
357
379
|
|
|
358
380
|
logger.info(
|
|
359
381
|
f"消费者启动验证: {len(running_clients)}/{len(required_clients)} 已启动")
|
|
360
|
-
await asyncio.sleep(
|
|
382
|
+
await asyncio.sleep(1)
|
|
361
383
|
|
|
362
|
-
# 检查未成功启动的消费者
|
|
363
384
|
failed_clients = [
|
|
364
385
|
name for name in required_clients if name not in running_clients]
|
|
365
386
|
if failed_clients:
|
|
366
387
|
logger.error(f"以下消费者启动失败: {', '.join(failed_clients)}")
|
|
367
|
-
# 尝试重新启动失败的消费者
|
|
368
388
|
for client_name in failed_clients:
|
|
369
389
|
logger.info(f"尝试重新启动消费者: {client_name}")
|
|
370
390
|
asyncio.create_task(cls.start_consumer(client_name))
|
|
@@ -375,13 +395,7 @@ class RabbitMQService:
|
|
|
375
395
|
queue_name: str,
|
|
376
396
|
handler: Callable[[MQMsgModel, AbstractIncomingMessage], Coroutine[Any, Any, None]], ** kwargs
|
|
377
397
|
) -> None:
|
|
378
|
-
"""
|
|
379
|
-
添加消息监听器
|
|
380
|
-
|
|
381
|
-
:param queue_name: 队列名称
|
|
382
|
-
:param handler: 消息处理函数
|
|
383
|
-
:param kwargs: 其他参数
|
|
384
|
-
"""
|
|
398
|
+
"""添加消息监听器"""
|
|
385
399
|
if not cls._config:
|
|
386
400
|
raise ValueError("RabbitMQService尚未初始化,请先调用init方法")
|
|
387
401
|
|
|
@@ -408,11 +422,7 @@ class RabbitMQService:
|
|
|
408
422
|
|
|
409
423
|
@classmethod
|
|
410
424
|
async def start_consumer(cls, client_name: str) -> None:
|
|
411
|
-
"""
|
|
412
|
-
启动指定客户端的消费者
|
|
413
|
-
|
|
414
|
-
:param client_name: 客户端名称
|
|
415
|
-
"""
|
|
425
|
+
"""启动指定客户端的消费者"""
|
|
416
426
|
if client_name in cls._consumer_tasks and not cls._consumer_tasks[client_name].done():
|
|
417
427
|
logger.debug(f"消费者 '{client_name}' 已在运行中,无需重复启动")
|
|
418
428
|
return
|
|
@@ -461,7 +471,7 @@ class RabbitMQService:
|
|
|
461
471
|
logger.warning(
|
|
462
472
|
f"启动消费者尝试 {attempt}/{max_attempts} 失败: {str(e)}")
|
|
463
473
|
if attempt < max_attempts:
|
|
464
|
-
await asyncio.sleep(
|
|
474
|
+
await asyncio.sleep(1)
|
|
465
475
|
|
|
466
476
|
if not consumer_tag:
|
|
467
477
|
raise Exception(f"经过 {max_attempts} 次尝试仍无法启动消费者")
|
|
@@ -528,12 +538,7 @@ class RabbitMQService:
|
|
|
528
538
|
|
|
529
539
|
@classmethod
|
|
530
540
|
def get_sender(cls, queue_name: str) -> Optional[RabbitMQClient]:
|
|
531
|
-
"""
|
|
532
|
-
获取发送客户端
|
|
533
|
-
|
|
534
|
-
:param queue_name: 队列名称
|
|
535
|
-
:return: RabbitMQClient实例或None
|
|
536
|
-
"""
|
|
541
|
+
"""获取发送客户端"""
|
|
537
542
|
if not queue_name:
|
|
538
543
|
logger.warning("发送器名称不能为空")
|
|
539
544
|
return None
|
|
@@ -556,13 +561,7 @@ class RabbitMQService:
|
|
|
556
561
|
data: Union[BaseModel, str, Dict[str, Any], None],
|
|
557
562
|
queue_name: str, ** kwargs
|
|
558
563
|
) -> None:
|
|
559
|
-
"""
|
|
560
|
-
发送消息到指定队列
|
|
561
|
-
|
|
562
|
-
:param data: 消息数据
|
|
563
|
-
:param queue_name: 队列名称
|
|
564
|
-
:param kwargs: 其他参数
|
|
565
|
-
"""
|
|
564
|
+
"""发送消息到指定队列"""
|
|
566
565
|
# 获取发送客户端
|
|
567
566
|
sender = cls.get_sender(queue_name)
|
|
568
567
|
if not sender:
|
|
@@ -628,11 +627,7 @@ class RabbitMQService:
|
|
|
628
627
|
|
|
629
628
|
@classmethod
|
|
630
629
|
async def shutdown(cls, timeout: float = 10.0) -> None:
|
|
631
|
-
"""
|
|
632
|
-
优雅关闭所有资源
|
|
633
|
-
|
|
634
|
-
:param timeout: 超时时间(秒)
|
|
635
|
-
"""
|
|
630
|
+
"""优雅关闭所有资源(新增连接池关闭逻辑)"""
|
|
636
631
|
start_time = asyncio.get_event_loop().time()
|
|
637
632
|
logger.info("开始关闭RabbitMQ服务...")
|
|
638
633
|
|
|
@@ -646,7 +641,6 @@ class RabbitMQService:
|
|
|
646
641
|
0.0, timeout - (asyncio.get_event_loop().time() - start_time))
|
|
647
642
|
if remaining_time > 0 and cls._consumer_tasks:
|
|
648
643
|
try:
|
|
649
|
-
# 等待所有消费者任务完成或超时
|
|
650
644
|
done, pending = await asyncio.wait(
|
|
651
645
|
list(cls._consumer_tasks.values()),
|
|
652
646
|
timeout=remaining_time,
|
|
@@ -680,6 +674,14 @@ class RabbitMQService:
|
|
|
680
674
|
logger.warning(f"关闭客户端 '{name}' 时出错: {str(e)}")
|
|
681
675
|
logger.info(f"客户端 '{name}' 已关闭")
|
|
682
676
|
|
|
677
|
+
# 关闭连接池
|
|
678
|
+
if cls._connection_pool:
|
|
679
|
+
try:
|
|
680
|
+
await cls._connection_pool.close()
|
|
681
|
+
logger.info("RabbitMQ连接池已关闭")
|
|
682
|
+
except Exception as e:
|
|
683
|
+
logger.warning(f"关闭连接池时出错: {str(e)}")
|
|
684
|
+
|
|
683
685
|
# 清理所有状态
|
|
684
686
|
cls._clients.clear()
|
|
685
687
|
cls._consumer_tasks.clear()
|
|
@@ -691,5 +693,6 @@ class RabbitMQService:
|
|
|
691
693
|
cls._init_locks.clear()
|
|
692
694
|
cls._has_listeners = False
|
|
693
695
|
cls._has_senders = False
|
|
696
|
+
cls._connection_pool = None
|
|
694
697
|
|
|
695
698
|
logger.info("RabbitMQ服务已完全关闭")
|
|
@@ -33,8 +33,9 @@ sycommon/models/mqlistener_config.py,sha256=PPwhAVJ2AWvVAvNox_1t0fuBKTyRH3Ui9cuu
|
|
|
33
33
|
sycommon/models/mqmsg_model.py,sha256=cxn0M5b0utQK6crMYmL-1waeGYHvK3AlGaRy23clqTE,277
|
|
34
34
|
sycommon/models/mqsend_config.py,sha256=NQX9dc8PpuquMG36GCVhJe8omAW1KVXXqr6lSRU6D7I,268
|
|
35
35
|
sycommon/models/sso_user.py,sha256=i1WAN6k5sPcPApQEdtjpWDy7VrzWLpOrOQewGLGoGIw,2702
|
|
36
|
-
sycommon/rabbitmq/rabbitmq_client.py,sha256=
|
|
37
|
-
sycommon/rabbitmq/
|
|
36
|
+
sycommon/rabbitmq/rabbitmq_client.py,sha256=1mnccWeqBHHTPy__8kGEBX77UtAPL3_ffVoAZbbyPf4,26429
|
|
37
|
+
sycommon/rabbitmq/rabbitmq_pool.py,sha256=_NMOO4CZy-I_anMqpzfYinz-8373_rg5FM9eqzdjGyU,3598
|
|
38
|
+
sycommon/rabbitmq/rabbitmq_service.py,sha256=lpYSavAwl-UOmz5gTgS3yj2ulfF-s7boL3lsMibN-JM,28881
|
|
38
39
|
sycommon/sse/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
39
40
|
sycommon/sse/event.py,sha256=k_rBJy23R7crtzQeetT0Q73D8o5-5p-eESGSs_BPOj0,2797
|
|
40
41
|
sycommon/sse/sse.py,sha256=__CfWEcYxOxQ-HpLor4LTZ5hLWqw9-2X7CngqbVHsfw,10128
|
|
@@ -45,8 +46,8 @@ sycommon/tools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
|
45
46
|
sycommon/tools/docs.py,sha256=OPj2ETheuWjXLyaXtaZPbwmJKfJaYXV5s4XMVAUNrms,1607
|
|
46
47
|
sycommon/tools/snowflake.py,sha256=rc-VUjBMMpdAvbnHroVwfVt1xzApJbTCthUy9mglAuw,237
|
|
47
48
|
sycommon/tools/timing.py,sha256=OiiE7P07lRoMzX9kzb8sZU9cDb0zNnqIlY5pWqHcnkY,2064
|
|
48
|
-
sycommon_python_lib-0.1.
|
|
49
|
-
sycommon_python_lib-0.1.
|
|
50
|
-
sycommon_python_lib-0.1.
|
|
51
|
-
sycommon_python_lib-0.1.
|
|
52
|
-
sycommon_python_lib-0.1.
|
|
49
|
+
sycommon_python_lib-0.1.17.dist-info/METADATA,sha256=Yz-MTXIYKGwCFWX3SRSsNQpSiPXZ3vAhsSLig9fl890,7005
|
|
50
|
+
sycommon_python_lib-0.1.17.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
51
|
+
sycommon_python_lib-0.1.17.dist-info/entry_points.txt,sha256=q_h2nbvhhmdnsOUZEIwpuoDjaNfBF9XqppDEmQn9d_A,46
|
|
52
|
+
sycommon_python_lib-0.1.17.dist-info/top_level.txt,sha256=98CJ-cyM2WIKxLz-Pf0AitWLhJyrfXvyY8slwjTXNuc,17
|
|
53
|
+
sycommon_python_lib-0.1.17.dist-info/RECORD,,
|
|
File without changes
|
{sycommon_python_lib-0.1.16.dist-info → sycommon_python_lib-0.1.17.dist-info}/entry_points.txt
RENAMED
|
File without changes
|
|
File without changes
|