sycommon-python-lib 0.1.0__py3-none-any.whl → 0.1.2__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/config/EmbeddingConfig.py +0 -1
- sycommon/config/MQConfig.py +15 -0
- sycommon/database/base_db_service.py +30 -0
- sycommon/logging/kafka_log.py +14 -38
- sycommon/middleware/middleware.py +4 -0
- sycommon/middleware/mq.py +9 -0
- sycommon/models/mqlistener_config.py +38 -0
- sycommon/models/mqmsg_model.py +11 -0
- sycommon/models/mqsend_config.py +8 -0
- sycommon/models/sso_user.py +60 -0
- sycommon/rabbitmq/rabbitmq_client.py +721 -0
- sycommon/rabbitmq/rabbitmq_service.py +476 -0
- sycommon/services.py +164 -20
- sycommon/synacos/feign.py +14 -10
- sycommon/synacos/nacos_service.py +252 -188
- {sycommon_python_lib-0.1.0.dist-info → sycommon_python_lib-0.1.2.dist-info}/METADATA +2 -2
- {sycommon_python_lib-0.1.0.dist-info → sycommon_python_lib-0.1.2.dist-info}/RECORD +19 -10
- {sycommon_python_lib-0.1.0.dist-info → sycommon_python_lib-0.1.2.dist-info}/WHEEL +0 -0
- {sycommon_python_lib-0.1.0.dist-info → sycommon_python_lib-0.1.2.dist-info}/top_level.txt +0 -0
|
@@ -9,7 +9,6 @@ import os
|
|
|
9
9
|
import yaml
|
|
10
10
|
import time
|
|
11
11
|
import atexit
|
|
12
|
-
import traceback
|
|
13
12
|
import random
|
|
14
13
|
from concurrent.futures import ThreadPoolExecutor
|
|
15
14
|
|
|
@@ -26,10 +25,21 @@ class NacosService(metaclass=SingletonMeta):
|
|
|
26
25
|
self.host = config['Host']
|
|
27
26
|
self.port = config['Port']
|
|
28
27
|
self.version = os.getenv('VERSION')
|
|
28
|
+
self.enable_register_nacos = os.getenv(
|
|
29
|
+
'REGISTER-NACOS', 'true').lower() == 'true'
|
|
29
30
|
self.registered = False
|
|
30
31
|
self._client_initialized = False # 客户端初始化状态
|
|
31
32
|
self._shutdown_event = threading.Event()
|
|
32
|
-
|
|
33
|
+
|
|
34
|
+
# 添加可重入锁用于状态同步
|
|
35
|
+
self._state_lock = threading.RLock()
|
|
36
|
+
|
|
37
|
+
# 优化线程池配置,增加工作线程数量
|
|
38
|
+
self._executor = ThreadPoolExecutor(max_workers=1) # 主线程池
|
|
39
|
+
self._heartbeat_executor = ThreadPoolExecutor(
|
|
40
|
+
max_workers=1) # 增加心跳线程
|
|
41
|
+
self._monitor_executor = ThreadPoolExecutor(
|
|
42
|
+
max_workers=1) # 增加监控线程
|
|
33
43
|
|
|
34
44
|
# 配置参数
|
|
35
45
|
self.max_retries = self.nacos_config.get('maxRetries', 5)
|
|
@@ -49,18 +59,20 @@ class NacosService(metaclass=SingletonMeta):
|
|
|
49
59
|
|
|
50
60
|
# 注册验证配置
|
|
51
61
|
self.registration_verify_count = self.nacos_config.get(
|
|
52
|
-
'registrationVerifyCount',
|
|
62
|
+
'registrationVerifyCount', 1) # 验证次数
|
|
53
63
|
self.registration_verify_interval = self.nacos_config.get(
|
|
54
64
|
'registrationVerifyInterval', 1) # 验证间隔
|
|
55
65
|
|
|
56
66
|
self.real_ip = self.get_service_ip(self.host)
|
|
57
67
|
self._long_term_retry_count = 0 # 长期重试计数器
|
|
58
68
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
69
|
+
if self.enable_register_nacos:
|
|
70
|
+
# 初始化客户端(仅在首次调用时执行)
|
|
71
|
+
self._initialize_client()
|
|
72
|
+
# 启动时清理残留实例
|
|
73
|
+
self._cleanup_stale_instance()
|
|
74
|
+
else:
|
|
75
|
+
SYLogger.info("nacos:本地开发模式,不初始化Nacos客户端")
|
|
64
76
|
|
|
65
77
|
self.share_configs = self.read_configs()
|
|
66
78
|
|
|
@@ -72,14 +84,21 @@ class NacosService(metaclass=SingletonMeta):
|
|
|
72
84
|
self._last_heartbeat_time = 0
|
|
73
85
|
self._heartbeat_fail_count = 0
|
|
74
86
|
self._heartbeat_thread = None
|
|
87
|
+
self.max_heartbeat_timeout = self.nacos_config.get(
|
|
88
|
+
'maxHeartbeatTimeout', 30) # 最大无心跳时间(秒)
|
|
89
|
+
self._last_successful_heartbeat = time.time() # 上次成功心跳时间戳
|
|
75
90
|
|
|
76
91
|
# 启动配置监视线程
|
|
77
92
|
self._watch_thread = threading.Thread(
|
|
78
93
|
target=self._watch_configs, daemon=True)
|
|
79
94
|
self._watch_thread.start()
|
|
80
95
|
|
|
81
|
-
#
|
|
82
|
-
self.
|
|
96
|
+
# 仅在需要注册时启动心跳和监控线程
|
|
97
|
+
if self.enable_register_nacos:
|
|
98
|
+
# 启动心跳线程
|
|
99
|
+
self.start_heartbeat()
|
|
100
|
+
else:
|
|
101
|
+
SYLogger.info("nacos:本地开发模式,不启动心跳和监控线程")
|
|
83
102
|
|
|
84
103
|
def _initialize_client(self):
|
|
85
104
|
"""初始化Nacos客户端(仅首次调用时执行)"""
|
|
@@ -98,8 +117,8 @@ class NacosService(metaclass=SingletonMeta):
|
|
|
98
117
|
self._client_initialized = True
|
|
99
118
|
return True
|
|
100
119
|
except Exception as e:
|
|
101
|
-
delay = min(self.retry_delay * (self.retry_backoff **
|
|
102
|
-
self.max_retry_delay)
|
|
120
|
+
delay = min(self.retry_delay * (self.retry_backoff **
|
|
121
|
+
attempt), self.max_retry_delay)
|
|
103
122
|
SYLogger.error(
|
|
104
123
|
f"nacos:客户端初始化失败 (尝试 {attempt+1}/{self.max_retries}): {e}")
|
|
105
124
|
time.sleep(delay)
|
|
@@ -119,15 +138,14 @@ class NacosService(metaclass=SingletonMeta):
|
|
|
119
138
|
port=int(self.port),
|
|
120
139
|
cluster_name="DEFAULT"
|
|
121
140
|
)
|
|
122
|
-
SYLogger.warning(
|
|
123
|
-
f"nacos:清理残留实例: {self.real_ip}:{self.port}")
|
|
141
|
+
SYLogger.warning(f"nacos:清理残留实例: {self.real_ip}:{self.port}")
|
|
124
142
|
except Exception as e:
|
|
125
143
|
SYLogger.error(f"nacos:清理残留实例异常: {e}")
|
|
126
144
|
|
|
127
145
|
def ensure_client_connected(self, retry_once=False):
|
|
128
146
|
"""确保Nacos客户端已连接,返回连接状态"""
|
|
129
147
|
# 使用线程锁保护客户端初始化状态
|
|
130
|
-
with
|
|
148
|
+
with self._state_lock:
|
|
131
149
|
if self._client_initialized:
|
|
132
150
|
return True
|
|
133
151
|
|
|
@@ -163,8 +181,8 @@ class NacosService(metaclass=SingletonMeta):
|
|
|
163
181
|
|
|
164
182
|
except Exception as e:
|
|
165
183
|
attempt += 1
|
|
166
|
-
delay = min(self.retry_delay * (self.retry_backoff **
|
|
167
|
-
self.max_retry_delay)
|
|
184
|
+
delay = min(self.retry_delay * (self.retry_backoff **
|
|
185
|
+
(attempt - 1)), self.max_retry_delay)
|
|
168
186
|
|
|
169
187
|
SYLogger.error(
|
|
170
188
|
f"nacos:客户端初始化失败 (尝试 {attempt}/{max_attempts}): {e}")
|
|
@@ -175,12 +193,15 @@ class NacosService(metaclass=SingletonMeta):
|
|
|
175
193
|
|
|
176
194
|
def _verify_client_connection(self):
|
|
177
195
|
"""验证客户端是否真正连接成功"""
|
|
196
|
+
# 本地开发模式下直接返回True,不进行实际验证
|
|
197
|
+
if not self.enable_register_nacos:
|
|
198
|
+
return True
|
|
199
|
+
|
|
178
200
|
try:
|
|
179
201
|
# 使用当前服务的命名实例查询来验证连接
|
|
180
202
|
namespace_id = self.nacos_config['namespaceId']
|
|
181
203
|
self.nacos_client.list_naming_instance(
|
|
182
204
|
service_name=self.service_name,
|
|
183
|
-
cluster_name="DEFAULT",
|
|
184
205
|
namespace_id=namespace_id,
|
|
185
206
|
group_name="DEFAULT_GROUP",
|
|
186
207
|
healthy_only=True
|
|
@@ -192,24 +213,39 @@ class NacosService(metaclass=SingletonMeta):
|
|
|
192
213
|
|
|
193
214
|
def check_service_registered(self):
|
|
194
215
|
"""检查服务是否已注册(基于实例列表)"""
|
|
216
|
+
# 本地开发模式下直接返回True,模拟已注册状态
|
|
217
|
+
if not self.enable_register_nacos:
|
|
218
|
+
return True
|
|
219
|
+
|
|
195
220
|
if not self.ensure_client_connected():
|
|
196
221
|
return False
|
|
197
222
|
|
|
198
223
|
try:
|
|
199
224
|
namespace_id = self.nacos_config['namespaceId']
|
|
200
225
|
instances = self.nacos_client.list_naming_instance(
|
|
201
|
-
self.service_name,
|
|
226
|
+
service_name=self.service_name,
|
|
227
|
+
namespace_id=namespace_id,
|
|
228
|
+
group_name="DEFAULT_GROUP",
|
|
229
|
+
healthy_only=True,
|
|
230
|
+
)
|
|
202
231
|
|
|
203
232
|
# 检查是否存在包含当前IP和端口的实例
|
|
233
|
+
found = False
|
|
204
234
|
for instance in instances.get('hosts', []):
|
|
205
235
|
if (instance.get('ip') == self.real_ip and
|
|
206
236
|
instance.get('port') == int(self.port)):
|
|
207
|
-
SYLogger.info(
|
|
208
|
-
|
|
209
|
-
|
|
237
|
+
SYLogger.info(f"nacos:找到已注册实例: {self.real_ip}:{self.port}")
|
|
238
|
+
found = True
|
|
239
|
+
break
|
|
210
240
|
|
|
211
|
-
|
|
212
|
-
|
|
241
|
+
if not found:
|
|
242
|
+
SYLogger.warning(f"nacos:未找到注册实例: {self.real_ip}:{self.port}")
|
|
243
|
+
|
|
244
|
+
# 带锁更新注册状态
|
|
245
|
+
with self._state_lock:
|
|
246
|
+
self.registered = found
|
|
247
|
+
|
|
248
|
+
return found
|
|
213
249
|
except Exception as e:
|
|
214
250
|
SYLogger.error(f"nacos:检查服务注册状态失败: {e}")
|
|
215
251
|
return False
|
|
@@ -243,10 +279,16 @@ class NacosService(metaclass=SingletonMeta):
|
|
|
243
279
|
retry_count = 0
|
|
244
280
|
last_error = None
|
|
245
281
|
|
|
246
|
-
#
|
|
247
|
-
self.
|
|
282
|
+
# 带锁重置注册状态
|
|
283
|
+
with self._state_lock:
|
|
284
|
+
self.registered = False
|
|
285
|
+
|
|
286
|
+
while (not self.registered) and (self.max_long_term_retries < 0 or retry_count < self.max_long_term_retries):
|
|
287
|
+
# 增加状态检查点,防止重复注册
|
|
288
|
+
with self._state_lock:
|
|
289
|
+
if self.registered:
|
|
290
|
+
return True
|
|
248
291
|
|
|
249
|
-
while not self.registered and (self.max_long_term_retries < 0 or retry_count < self.max_long_term_retries):
|
|
250
292
|
try:
|
|
251
293
|
# 尝试注册服务
|
|
252
294
|
register_success = self.register(force=True)
|
|
@@ -261,34 +303,46 @@ class NacosService(metaclass=SingletonMeta):
|
|
|
261
303
|
|
|
262
304
|
# 多次验证服务是否真正注册成功
|
|
263
305
|
registered = self.verify_registration()
|
|
264
|
-
self.registered = registered # <-- 确保设置注册状态
|
|
265
306
|
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
self.
|
|
307
|
+
# 带锁更新注册状态
|
|
308
|
+
with self._state_lock:
|
|
309
|
+
self.registered = registered
|
|
269
310
|
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
self.
|
|
311
|
+
# 再次检查状态,防止其他线程修改
|
|
312
|
+
with self._state_lock:
|
|
313
|
+
if self.registered:
|
|
314
|
+
# 注册成功后,更新客户端状态
|
|
315
|
+
self._client_initialized = True
|
|
273
316
|
|
|
274
|
-
|
|
275
|
-
|
|
317
|
+
# 注册成功后,通知心跳线程立即发送心跳
|
|
318
|
+
self._shutdown_event.set()
|
|
319
|
+
self._shutdown_event.clear()
|
|
276
320
|
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
321
|
+
# 注册成功后,更新监控线程的状态
|
|
322
|
+
self._long_term_retry_count = 0
|
|
323
|
+
|
|
324
|
+
SYLogger.info(
|
|
325
|
+
f"nacos:服务注册成功并通过验证: {self.service_name}")
|
|
326
|
+
return True
|
|
327
|
+
else:
|
|
328
|
+
raise RuntimeError("nacos:服务注册验证失败")
|
|
281
329
|
|
|
282
330
|
except Exception as e:
|
|
283
331
|
last_error = str(e)
|
|
284
332
|
retry_count += 1
|
|
285
|
-
delay = min(self.register_retry_interval *
|
|
286
|
-
self.max_retry_delay)
|
|
333
|
+
delay = min(self.register_retry_interval *
|
|
334
|
+
(self.retry_backoff ** (retry_count - 1)), self.max_retry_delay)
|
|
287
335
|
|
|
288
336
|
SYLogger.warning(
|
|
289
337
|
f"nacos:服务注册尝试 {retry_count} 失败: {last_error},{delay}秒后重试")
|
|
290
338
|
time.sleep(delay)
|
|
291
339
|
|
|
340
|
+
# 最终检查,防止在最后一次重试后其他线程成功注册
|
|
341
|
+
with self._state_lock:
|
|
342
|
+
if self.registered:
|
|
343
|
+
return True
|
|
344
|
+
|
|
345
|
+
# 确实注册失败
|
|
292
346
|
if last_error:
|
|
293
347
|
SYLogger.error(f"nacos:服务注册失败,最终错误: {last_error}")
|
|
294
348
|
else:
|
|
@@ -298,8 +352,8 @@ class NacosService(metaclass=SingletonMeta):
|
|
|
298
352
|
|
|
299
353
|
def register(self, force=False):
|
|
300
354
|
"""注册服务到Nacos"""
|
|
301
|
-
#
|
|
302
|
-
with
|
|
355
|
+
# 使用状态锁保护注册状态
|
|
356
|
+
with self._state_lock:
|
|
303
357
|
if self.registered and not force and self.check_service_registered():
|
|
304
358
|
return True
|
|
305
359
|
|
|
@@ -352,23 +406,47 @@ class NacosService(metaclass=SingletonMeta):
|
|
|
352
406
|
"""创建并初始化Nacos管理器"""
|
|
353
407
|
instance = NacosService(config)
|
|
354
408
|
|
|
355
|
-
#
|
|
356
|
-
if
|
|
357
|
-
#
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
409
|
+
# 仅在需要注册时执行注册逻辑
|
|
410
|
+
if instance.enable_register_nacos:
|
|
411
|
+
# 使用带超时的等待机制,而不是单次尝试
|
|
412
|
+
timeout = 60 # 60秒超时
|
|
413
|
+
start_time = time.time()
|
|
414
|
+
|
|
415
|
+
# 启动注册线程,不阻塞主线程
|
|
416
|
+
instance._executor.submit(instance.register_with_retry)
|
|
417
|
+
|
|
418
|
+
# 等待注册完成或超时
|
|
419
|
+
while True:
|
|
420
|
+
# 带锁检查状态
|
|
421
|
+
with instance._state_lock:
|
|
422
|
+
if instance.registered:
|
|
423
|
+
break
|
|
362
424
|
|
|
363
|
-
|
|
425
|
+
if time.time() - start_time >= timeout:
|
|
426
|
+
# 超时处理
|
|
427
|
+
break
|
|
364
428
|
|
|
365
|
-
|
|
366
|
-
signal.signal(signal.SIGTERM, instance.handle_signal)
|
|
367
|
-
signal.signal(signal.SIGINT, instance.handle_signal)
|
|
429
|
+
time.sleep(1)
|
|
368
430
|
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
431
|
+
# 最终状态检查
|
|
432
|
+
with instance._state_lock:
|
|
433
|
+
if not instance.registered:
|
|
434
|
+
# 清理并抛出异常
|
|
435
|
+
try:
|
|
436
|
+
instance.deregister_service()
|
|
437
|
+
except Exception as e:
|
|
438
|
+
SYLogger.error(f"nacos:服务注册失败后,注销服务时发生错误: {e}")
|
|
439
|
+
raise RuntimeError("nacos:服务注册失败,应用启动终止")
|
|
440
|
+
|
|
441
|
+
# 服务注册成功后再注册信号处理
|
|
442
|
+
signal.signal(signal.SIGTERM, instance.handle_signal)
|
|
443
|
+
signal.signal(signal.SIGINT, instance.handle_signal)
|
|
444
|
+
|
|
445
|
+
# 启动连接监控线程
|
|
446
|
+
threading.Thread(target=instance.monitor_connection,
|
|
447
|
+
daemon=True).start()
|
|
448
|
+
else:
|
|
449
|
+
SYLogger.info("nacos:本地开发模式,跳过服务注册流程")
|
|
372
450
|
|
|
373
451
|
return instance
|
|
374
452
|
|
|
@@ -382,131 +460,94 @@ class NacosService(metaclass=SingletonMeta):
|
|
|
382
460
|
name="NacosHeartbeatThread",
|
|
383
461
|
daemon=True
|
|
384
462
|
)
|
|
463
|
+
# 设置线程为守护线程并尝试提高优先级
|
|
464
|
+
self._heartbeat_thread.daemon = True
|
|
385
465
|
self._heartbeat_thread.start()
|
|
386
|
-
SYLogger.info("nacos:心跳线程已启动")
|
|
387
466
|
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
467
|
+
try:
|
|
468
|
+
# 尝试提高线程优先级
|
|
469
|
+
if hasattr(os, 'sched_setscheduler'):
|
|
470
|
+
os.sched_setscheduler(
|
|
471
|
+
self._heartbeat_thread.ident, os.SCHED_FIFO, os.sched_param(99))
|
|
472
|
+
elif hasattr(os, 'nice'):
|
|
473
|
+
os.nice(-10) # 在Unix系统上尝试提高优先级
|
|
474
|
+
SYLogger.info("nacos:心跳线程已启动并尝试提高优先级")
|
|
475
|
+
except Exception as e:
|
|
476
|
+
SYLogger.warning(f"nacos:无法提高心跳线程优先级: {e}")
|
|
395
477
|
|
|
396
|
-
|
|
397
|
-
|
|
478
|
+
def _send_heartbeat_loop(self):
|
|
479
|
+
"""优化后的心跳发送循环,确保严格按间隔执行"""
|
|
480
|
+
SYLogger.info("nacos:优化版心跳线程开始运行")
|
|
481
|
+
last_heartbeat_time = time.time() # 初始时间戳
|
|
398
482
|
|
|
399
483
|
while not self._shutdown_event.is_set():
|
|
484
|
+
current_time = time.time()
|
|
485
|
+
# 计算距离下次心跳的时间(确保严格按间隔执行)
|
|
486
|
+
sleep_time = max(0, self.heartbeat_interval -
|
|
487
|
+
(current_time - last_heartbeat_time))
|
|
488
|
+
|
|
489
|
+
if sleep_time > 0:
|
|
490
|
+
self._shutdown_event.wait(sleep_time) # 精准等待
|
|
491
|
+
|
|
492
|
+
# 执行心跳逻辑
|
|
400
493
|
try:
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
# 双重检查,确保服务确实注册
|
|
412
|
-
if not self.check_service_registered():
|
|
413
|
-
SYLogger.warning(
|
|
414
|
-
"nacos:服务状态显示已注册,但Nacos中未找到实例")
|
|
415
|
-
self.registered = False
|
|
416
|
-
continue
|
|
417
|
-
|
|
418
|
-
SYLogger.info("nacos:准备发送心跳...")
|
|
419
|
-
success = self.send_heartbeat()
|
|
420
|
-
if success:
|
|
421
|
-
heartbeat_counter += 1
|
|
422
|
-
consecutive_failures = 0
|
|
423
|
-
last_successful_heartbeat = current_time
|
|
424
|
-
# 更新下一次计划发送时间
|
|
425
|
-
next_heartbeat_time = current_time + self.heartbeat_interval
|
|
426
|
-
SYLogger.info(
|
|
427
|
-
f"nacos:心跳发送成功({heartbeat_counter}),下次发送时间: {next_heartbeat_time}")
|
|
428
|
-
else:
|
|
429
|
-
consecutive_failures += 1
|
|
430
|
-
# 失败时减少下次发送间隔,加快恢复
|
|
431
|
-
next_heartbeat_time = current_time + min(
|
|
432
|
-
self.heartbeat_interval,
|
|
433
|
-
self.long_term_retry_delay *
|
|
434
|
-
(self.retry_backoff **
|
|
435
|
-
(consecutive_failures - 1))
|
|
436
|
-
)
|
|
437
|
-
SYLogger.warning(
|
|
438
|
-
f"nacos:心跳发送失败,将减少下次发送间隔为 {next_heartbeat_time - current_time:.2f} 秒")
|
|
494
|
+
# 带锁检查注册状态
|
|
495
|
+
with self._state_lock:
|
|
496
|
+
registered_status = self.registered
|
|
497
|
+
|
|
498
|
+
if registered_status and self.check_service_registered():
|
|
499
|
+
success = self.send_heartbeat()
|
|
500
|
+
if success:
|
|
501
|
+
self._last_successful_heartbeat = time.time()
|
|
502
|
+
SYLogger.info(
|
|
503
|
+
f"nacos:心跳发送成功,时间: {self._last_successful_heartbeat:.3f}")
|
|
439
504
|
else:
|
|
440
|
-
SYLogger.warning(
|
|
441
|
-
|
|
442
|
-
if current_time - next_heartbeat_time > self.register_retry_interval:
|
|
443
|
-
SYLogger.info("nacos:服务未注册,尝试重新注册")
|
|
444
|
-
self.register_with_retry()
|
|
445
|
-
next_heartbeat_time = current_time + self.heartbeat_interval
|
|
446
|
-
else:
|
|
447
|
-
# 缩短检查间隔
|
|
448
|
-
next_heartbeat_time = current_time + \
|
|
449
|
-
min(self.heartbeat_interval, 5)
|
|
450
|
-
|
|
451
|
-
# 检查线程运行时间,防止线程挂起 - 统一为1小时重置
|
|
452
|
-
if current_time - thread_start_time > 3600:
|
|
453
|
-
SYLogger.info("nacos:心跳线程已运行1小时,重置内部状态")
|
|
454
|
-
thread_start_time = current_time
|
|
455
|
-
heartbeat_counter = 0
|
|
456
|
-
|
|
457
|
-
# 检查是否长时间没有成功心跳
|
|
458
|
-
if current_time - last_successful_heartbeat > self.heartbeat_interval * 3:
|
|
459
|
-
SYLogger.warning(
|
|
460
|
-
f"nacos:已超过3个心跳周期({self.heartbeat_interval*3}秒)没有成功发送心跳,尝试重新注册")
|
|
461
|
-
self.register_with_retry()
|
|
462
|
-
last_successful_heartbeat = current_time
|
|
463
|
-
|
|
464
|
-
# 计算休眠时间,避免过度循环
|
|
465
|
-
sleep_time = next_heartbeat_time - current_time
|
|
466
|
-
if sleep_time > 0:
|
|
467
|
-
SYLogger.info(f"nacos:心跳线程休眠 {sleep_time:.2f} 秒")
|
|
468
|
-
self._shutdown_event.wait(sleep_time)
|
|
505
|
+
SYLogger.warning(
|
|
506
|
+
f"nacos:心跳发送失败,已持续{current_time - self._last_successful_heartbeat:.1f}秒")
|
|
469
507
|
else:
|
|
470
|
-
|
|
471
|
-
self.
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
SYLogger.error(f"nacos:心跳线程异常: {str(e)}")
|
|
475
|
-
traceback.print_exc()
|
|
476
|
-
# 发生异常时,增加下次发送间隔
|
|
477
|
-
next_heartbeat_time = time.time() + 5
|
|
478
|
-
self._shutdown_event.wait(1)
|
|
479
|
-
|
|
480
|
-
SYLogger.info("nacos:心跳线程已停止")
|
|
508
|
+
SYLogger.warning("nacos:服务未注册,尝试重新注册")
|
|
509
|
+
self._executor.submit(self.register_with_retry)
|
|
510
|
+
finally:
|
|
511
|
+
last_heartbeat_time = time.time() # 更新上次执行时间
|
|
481
512
|
|
|
482
513
|
def send_heartbeat(self):
|
|
483
|
-
"""
|
|
514
|
+
"""发送心跳并添加超时控制"""
|
|
484
515
|
if not self.ensure_client_connected():
|
|
516
|
+
SYLogger.warning("nacos:客户端未连接,心跳发送失败")
|
|
485
517
|
return False
|
|
486
518
|
|
|
487
519
|
try:
|
|
488
|
-
#
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
# 处理返回结果
|
|
499
|
-
if result and isinstance(result, dict) and result.get('lightBeatEnabled', False):
|
|
500
|
-
SYLogger.info(
|
|
501
|
-
f"nacos:心跳发送成功,Nacos返回: {result}")
|
|
502
|
-
return True
|
|
503
|
-
else:
|
|
504
|
-
SYLogger.warning(
|
|
505
|
-
f"nacos:心跳发送失败,Nacos返回: {result}")
|
|
506
|
-
return False
|
|
507
|
-
|
|
520
|
+
# 严格控制心跳超时(3秒)
|
|
521
|
+
future = self._heartbeat_executor.submit(
|
|
522
|
+
self._send_heartbeat_internal)
|
|
523
|
+
result = future.result(timeout=3) # 超时后抛出异常
|
|
524
|
+
|
|
525
|
+
if result:
|
|
526
|
+
# 只有确认成功才更新时间戳
|
|
527
|
+
self._last_successful_heartbeat = time.time()
|
|
528
|
+
return result
|
|
508
529
|
except Exception as e:
|
|
509
530
|
SYLogger.error(f"nacos:发送心跳时发生异常: {e}")
|
|
531
|
+
self._client_initialized = False # 强制重连
|
|
532
|
+
return False
|
|
533
|
+
|
|
534
|
+
def _send_heartbeat_internal(self):
|
|
535
|
+
"""实际的心跳发送逻辑"""
|
|
536
|
+
result = self.nacos_client.send_heartbeat(
|
|
537
|
+
service_name=self.service_name,
|
|
538
|
+
ip=self.real_ip,
|
|
539
|
+
port=int(self.port),
|
|
540
|
+
cluster_name="DEFAULT",
|
|
541
|
+
weight=1.0,
|
|
542
|
+
metadata={"version": self.version} if self.version else None
|
|
543
|
+
)
|
|
544
|
+
|
|
545
|
+
# 处理返回结果
|
|
546
|
+
if result and isinstance(result, dict) and result.get('lightBeatEnabled', False):
|
|
547
|
+
SYLogger.info(f"nacos:心跳发送成功,Nacos返回: {result}")
|
|
548
|
+
return True
|
|
549
|
+
else:
|
|
550
|
+
SYLogger.warning(f"nacos:心跳发送失败,Nacos返回: {result}")
|
|
510
551
|
return False
|
|
511
552
|
|
|
512
553
|
def reconnect_nacos_client(self):
|
|
@@ -516,16 +557,18 @@ class NacosService(metaclass=SingletonMeta):
|
|
|
516
557
|
return self.ensure_client_connected()
|
|
517
558
|
|
|
518
559
|
def monitor_connection(self):
|
|
519
|
-
"""
|
|
520
|
-
|
|
560
|
+
"""优化的连接监控线程,缩短检查间隔"""
|
|
561
|
+
# 缩短检查间隔(5秒一次)
|
|
562
|
+
check_interval = self.nacos_config.get('checkInterval', 5)
|
|
521
563
|
thread_start_time = time.time() # 线程启动时间
|
|
522
564
|
check_counter = 0 # 检查计数器
|
|
523
565
|
|
|
524
566
|
while not self._shutdown_event.is_set():
|
|
525
567
|
try:
|
|
526
568
|
current_time = time.time()
|
|
569
|
+
|
|
527
570
|
SYLogger.info(
|
|
528
|
-
f"nacos
|
|
571
|
+
f"nacos:连接监控线程运行中,检查间隔: {check_interval}s")
|
|
529
572
|
|
|
530
573
|
# 检查客户端连接状态
|
|
531
574
|
if not self.ensure_client_connected():
|
|
@@ -535,19 +578,21 @@ class NacosService(metaclass=SingletonMeta):
|
|
|
535
578
|
# 检查服务注册状态
|
|
536
579
|
current_registered = self.check_service_registered()
|
|
537
580
|
|
|
538
|
-
#
|
|
539
|
-
|
|
540
|
-
if current_registered:
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
581
|
+
# 带锁更新注册状态
|
|
582
|
+
with self._state_lock:
|
|
583
|
+
if current_registered != self.registered:
|
|
584
|
+
if current_registered:
|
|
585
|
+
self.registered = True
|
|
586
|
+
SYLogger.info(f"nacos:服务实例已重新注册")
|
|
587
|
+
else:
|
|
588
|
+
self.registered = False
|
|
589
|
+
SYLogger.warning(f"nacos:服务实例未注册,尝试重新注册")
|
|
590
|
+
# 不在锁内调用可能耗时的操作
|
|
591
|
+
self._monitor_executor.submit(
|
|
592
|
+
self.register_with_retry)
|
|
548
593
|
|
|
549
|
-
#
|
|
550
|
-
if random.random() < 0.2:
|
|
594
|
+
# 20%的概率执行深度检查
|
|
595
|
+
if random.random() < 0.2:
|
|
551
596
|
self.verify_registration()
|
|
552
597
|
|
|
553
598
|
# 每小时重置一次内部状态
|
|
@@ -576,8 +621,9 @@ class NacosService(metaclass=SingletonMeta):
|
|
|
576
621
|
|
|
577
622
|
def deregister_service(self):
|
|
578
623
|
"""从Nacos注销服务"""
|
|
579
|
-
|
|
580
|
-
|
|
624
|
+
with self._state_lock:
|
|
625
|
+
if not self.registered or not self._client_initialized:
|
|
626
|
+
return
|
|
581
627
|
|
|
582
628
|
SYLogger.info("nacos:正在注销服务...")
|
|
583
629
|
try:
|
|
@@ -587,13 +633,20 @@ class NacosService(metaclass=SingletonMeta):
|
|
|
587
633
|
port=int(self.port),
|
|
588
634
|
cluster_name="DEFAULT"
|
|
589
635
|
)
|
|
590
|
-
self.
|
|
636
|
+
with self._state_lock:
|
|
637
|
+
self.registered = False
|
|
591
638
|
SYLogger.info(f"nacos:服务 {self.service_name} 已注销")
|
|
592
639
|
except Exception as e:
|
|
593
640
|
SYLogger.error(f"nacos:注销服务时发生错误: {e}")
|
|
594
641
|
finally:
|
|
595
642
|
self._shutdown_event.set()
|
|
596
|
-
|
|
643
|
+
# 优雅地关闭线程池
|
|
644
|
+
if self._executor:
|
|
645
|
+
self._executor.shutdown(wait=True)
|
|
646
|
+
if self._heartbeat_executor:
|
|
647
|
+
self._heartbeat_executor.shutdown(wait=True)
|
|
648
|
+
if self._monitor_executor:
|
|
649
|
+
self._monitor_executor.shutdown(wait=True)
|
|
597
650
|
|
|
598
651
|
def handle_signal(self, signum, frame):
|
|
599
652
|
"""处理退出信号"""
|
|
@@ -658,6 +711,8 @@ class NacosService(metaclass=SingletonMeta):
|
|
|
658
711
|
|
|
659
712
|
def _watch_configs(self):
|
|
660
713
|
"""配置监听线程"""
|
|
714
|
+
check_interval = 5 # 固定检查间隔
|
|
715
|
+
|
|
661
716
|
while not self._shutdown_event.is_set():
|
|
662
717
|
try:
|
|
663
718
|
for data_id, callback in list(self._config_listeners.items()):
|
|
@@ -667,7 +722,7 @@ class NacosService(metaclass=SingletonMeta):
|
|
|
667
722
|
self._config_cache[data_id] = new_config
|
|
668
723
|
except Exception as e:
|
|
669
724
|
SYLogger.error(f"nacos:配置监视线程异常: {str(e)}")
|
|
670
|
-
self._shutdown_event.wait(
|
|
725
|
+
self._shutdown_event.wait(check_interval) # 检查间隔
|
|
671
726
|
|
|
672
727
|
def discover_services(self, service_name: str, group: str = "DEFAULT_GROUP", version: str = None) -> List[Dict]:
|
|
673
728
|
"""发现服务实例列表 (与Java格式兼容)"""
|
|
@@ -677,12 +732,21 @@ class NacosService(metaclass=SingletonMeta):
|
|
|
677
732
|
return self.get_service_instances(service_name, group, version)
|
|
678
733
|
|
|
679
734
|
def get_service_instances(self, service_name: str, group: str = "DEFAULT_GROUP", version: str = None) -> List[Dict]:
|
|
735
|
+
"""获取服务实例列表"""
|
|
680
736
|
try:
|
|
681
737
|
namespace_id = self.nacos_config['namespaceId']
|
|
682
738
|
instances = self.nacos_client.list_naming_instance(
|
|
683
|
-
service_name,
|
|
739
|
+
service_name,
|
|
740
|
+
namespace_id=namespace_id,
|
|
741
|
+
group_name=group,
|
|
742
|
+
healthy_only=True,
|
|
743
|
+
)
|
|
684
744
|
if not instances or 'hosts' not in instances:
|
|
685
745
|
return []
|
|
746
|
+
|
|
747
|
+
SYLogger.info(
|
|
748
|
+
f"nacos:发现 {len(instances.get('hosts', []))} 个 {service_name} 服务实例")
|
|
749
|
+
|
|
686
750
|
return instances.get('hosts', [])
|
|
687
751
|
except Exception as e:
|
|
688
752
|
SYLogger.error(f"nacos:服务发现失败: {service_name}: {str(e)}")
|