sycommon-python-lib 0.1.56b7__py3-none-any.whl → 0.1.56b8__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/Config.py +1 -3
- sycommon/rabbitmq/rabbitmq_service.py +25 -854
- sycommon/rabbitmq/rabbitmq_service_client_manager.py +212 -0
- sycommon/rabbitmq/rabbitmq_service_connection_monitor.py +73 -0
- sycommon/rabbitmq/rabbitmq_service_consumer_manager.py +283 -0
- sycommon/rabbitmq/rabbitmq_service_core.py +117 -0
- sycommon/rabbitmq/rabbitmq_service_producer_manager.py +235 -0
- sycommon/synacos/nacos_client_base.py +119 -0
- sycommon/synacos/nacos_config_manager.py +106 -0
- sycommon/synacos/nacos_heartbeat_manager.py +142 -0
- sycommon/synacos/nacos_service.py +58 -798
- sycommon/synacos/nacos_service_discovery.py +138 -0
- sycommon/synacos/nacos_service_registration.py +252 -0
- {sycommon_python_lib-0.1.56b7.dist-info → sycommon_python_lib-0.1.56b8.dist-info}/METADATA +1 -1
- {sycommon_python_lib-0.1.56b7.dist-info → sycommon_python_lib-0.1.56b8.dist-info}/RECORD +18 -8
- {sycommon_python_lib-0.1.56b7.dist-info → sycommon_python_lib-0.1.56b8.dist-info}/WHEEL +0 -0
- {sycommon_python_lib-0.1.56b7.dist-info → sycommon_python_lib-0.1.56b8.dist-info}/entry_points.txt +0 -0
- {sycommon_python_lib-0.1.56b7.dist-info → sycommon_python_lib-0.1.56b8.dist-info}/top_level.txt +0 -0
|
@@ -1,18 +1,19 @@
|
|
|
1
1
|
import threading
|
|
2
|
-
import json
|
|
3
|
-
from typing import Callable, Dict, List, Optional
|
|
4
|
-
import nacos
|
|
5
2
|
import socket
|
|
6
3
|
import signal
|
|
7
4
|
import sys
|
|
8
5
|
import os
|
|
9
|
-
import yaml
|
|
10
6
|
import time
|
|
11
|
-
import
|
|
12
|
-
|
|
7
|
+
from typing import Callable, Dict, List, Optional
|
|
13
8
|
from sycommon.config.Config import Config, SingletonMeta
|
|
14
9
|
from sycommon.logging.kafka_log import SYLogger
|
|
15
10
|
|
|
11
|
+
from sycommon.synacos.nacos_client_base import NacosClientBase
|
|
12
|
+
from sycommon.synacos.nacos_service_registration import NacosServiceRegistration
|
|
13
|
+
from sycommon.synacos.nacos_heartbeat_manager import NacosHeartbeatManager
|
|
14
|
+
from sycommon.synacos.nacos_config_manager import NacosConfigManager
|
|
15
|
+
from sycommon.synacos.nacos_service_discovery import NacosServiceDiscovery
|
|
16
|
+
|
|
16
17
|
|
|
17
18
|
class NacosService(metaclass=SingletonMeta):
|
|
18
19
|
def __init__(self, config):
|
|
@@ -25,434 +26,62 @@ class NacosService(metaclass=SingletonMeta):
|
|
|
25
26
|
self.version = os.getenv('VERSION')
|
|
26
27
|
self.enable_register_nacos = os.getenv(
|
|
27
28
|
'REGISTER-NACOS', 'true').lower() == 'true'
|
|
28
|
-
self.registered = False
|
|
29
|
-
self._client_initialized = False # 客户端初始化状态
|
|
30
|
-
self._shutdown_event = threading.Event()
|
|
31
|
-
|
|
32
|
-
# 配置参数
|
|
33
|
-
self.max_retries = self.nacos_config.get('maxRetries', 5)
|
|
34
|
-
self.retry_delay = self.nacos_config.get('retryDelay', 5)
|
|
35
|
-
self.max_retry_delay = self.nacos_config.get('maxRetryDelay', 30)
|
|
36
|
-
# 心跳间隔:优先从配置读取,默认15秒(可通过配置修改)
|
|
37
|
-
self.heartbeat_interval = self.nacos_config.get(
|
|
38
|
-
'heartbeatInterval', 15)
|
|
39
|
-
# 心跳超时:固定设置为15秒
|
|
40
|
-
self.heartbeat_timeout = 15
|
|
41
|
-
self.register_retry_interval = self.nacos_config.get(
|
|
42
|
-
'registerRetryInterval', 15) # 注册重试间隔
|
|
43
|
-
|
|
44
|
-
# 长期重试配置
|
|
45
|
-
self.long_term_retry_delay = self.nacos_config.get(
|
|
46
|
-
'longTermRetryDelay', 30)
|
|
47
|
-
self.max_long_term_retries = self.nacos_config.get(
|
|
48
|
-
'maxLongTermRetries', -1) # -1表示无限重试
|
|
49
29
|
|
|
50
|
-
#
|
|
51
|
-
self.
|
|
52
|
-
|
|
53
|
-
self.registration_verify_interval = self.nacos_config.get(
|
|
54
|
-
'registrationVerifyInterval', 1) # 验证间隔
|
|
55
|
-
self.registration_post_delay = self.nacos_config.get(
|
|
56
|
-
'registrationPostDelay', 3) # 注册后延迟3秒再开始验证
|
|
30
|
+
# 初始化基础模块
|
|
31
|
+
self.client_base = NacosClientBase(
|
|
32
|
+
self.nacos_config, self.enable_register_nacos)
|
|
57
33
|
|
|
34
|
+
# 获取真实IP
|
|
58
35
|
self.real_ip = self.get_service_ip(self.host)
|
|
59
|
-
self._long_term_retry_count = 0 # 长期重试计数器
|
|
60
36
|
|
|
61
|
-
#
|
|
62
|
-
self.
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
self._verify_lock = threading.Lock()
|
|
68
|
-
self._last_verify_time = 0
|
|
37
|
+
# 初始化各功能模块
|
|
38
|
+
self.registration = NacosServiceRegistration(
|
|
39
|
+
self.client_base, self.service_name, self.real_ip, self.port, self.version
|
|
40
|
+
)
|
|
41
|
+
self.config_manager = NacosConfigManager(self.client_base)
|
|
42
|
+
self.discovery = NacosServiceDiscovery(self.client_base)
|
|
69
43
|
|
|
70
|
-
#
|
|
71
|
-
self.
|
|
72
|
-
|
|
44
|
+
# 心跳间隔配置
|
|
45
|
+
self.heartbeat_interval = self.nacos_config.get(
|
|
46
|
+
'heartbeatInterval', 15)
|
|
47
|
+
self.heartbeat_manager = NacosHeartbeatManager(
|
|
48
|
+
self.client_base, self.registration, self.heartbeat_interval
|
|
49
|
+
)
|
|
73
50
|
|
|
74
51
|
if self.enable_register_nacos:
|
|
75
|
-
#
|
|
76
|
-
self._initialize_client()
|
|
77
|
-
#
|
|
78
|
-
self._cleanup_stale_instance()
|
|
52
|
+
# 初始化客户端
|
|
53
|
+
self.client_base._initialize_client()
|
|
54
|
+
# 清理残留实例
|
|
55
|
+
self.registration._cleanup_stale_instance()
|
|
79
56
|
else:
|
|
80
57
|
SYLogger.info("nacos:本地开发模式,不初始化Nacos客户端")
|
|
81
58
|
|
|
82
|
-
|
|
83
|
-
|
|
59
|
+
# 读取配置并设置到全局配置
|
|
60
|
+
self.share_configs = self.config_manager.read_configs(
|
|
61
|
+
self.nacos_config.get('sharedConfigs', []))
|
|
84
62
|
Config().set_attr(self.share_configs)
|
|
85
63
|
|
|
86
|
-
# 配置监听器
|
|
87
|
-
self._config_listeners = {}
|
|
88
|
-
self._config_cache = {}
|
|
89
|
-
|
|
90
|
-
# 心跳相关
|
|
91
|
-
self._last_heartbeat_time = 0
|
|
92
|
-
self._heartbeat_fail_count = 0
|
|
93
|
-
self._heartbeat_lock = threading.Lock()
|
|
94
|
-
self._heartbeat_thread = None
|
|
95
|
-
|
|
96
|
-
self.max_heartbeat_timeout = self.nacos_config.get(
|
|
97
|
-
'maxHeartbeatTimeout', 30)
|
|
98
|
-
# 连接监控检查间隔(新增配置,默认30秒,避免硬编码)
|
|
99
|
-
self.connection_check_interval = self.nacos_config.get(
|
|
100
|
-
'connectionCheckInterval', 30)
|
|
101
|
-
# 配置监视线程检查间隔(默认30秒)
|
|
102
|
-
self.config_watch_interval = self.nacos_config.get(
|
|
103
|
-
'configWatchInterval', 30)
|
|
104
|
-
|
|
105
64
|
# 启动配置监视线程
|
|
106
|
-
self.
|
|
107
|
-
target=self._watch_configs, daemon=True)
|
|
108
|
-
self._watch_thread.start()
|
|
65
|
+
self.config_manager.start_watch_configs()
|
|
109
66
|
|
|
110
|
-
#
|
|
67
|
+
# 仅在需要注册时启动心跳
|
|
111
68
|
if self.enable_register_nacos:
|
|
112
|
-
|
|
113
|
-
self.start_heartbeat()
|
|
69
|
+
self.heartbeat_manager.start_heartbeat()
|
|
114
70
|
else:
|
|
115
71
|
SYLogger.info("nacos:本地开发模式,不启动心跳和监控线程")
|
|
116
72
|
|
|
117
|
-
def _initialize_client(self):
|
|
118
|
-
"""初始化Nacos客户端(仅首次调用时执行)"""
|
|
119
|
-
if self._client_initialized:
|
|
120
|
-
return True
|
|
121
|
-
|
|
122
|
-
for attempt in range(self.max_retries):
|
|
123
|
-
try:
|
|
124
|
-
register_ip = self.nacos_config['registerIp']
|
|
125
|
-
namespace_id = self.nacos_config['namespaceId']
|
|
126
|
-
self.nacos_client = nacos.NacosClient(
|
|
127
|
-
server_addresses=register_ip,
|
|
128
|
-
namespace=namespace_id
|
|
129
|
-
)
|
|
130
|
-
SYLogger.info("nacos:客户端初始化成功")
|
|
131
|
-
self._client_initialized = True
|
|
132
|
-
return True
|
|
133
|
-
except Exception as e:
|
|
134
|
-
delay = min(self.retry_delay, self.max_retry_delay)
|
|
135
|
-
SYLogger.error(
|
|
136
|
-
f"nacos:客户端初始化失败 (尝试 {attempt+1}/{self.max_retries}): {e}")
|
|
137
|
-
time.sleep(delay)
|
|
138
|
-
|
|
139
|
-
SYLogger.warning("nacos:无法连接到 Nacos 服务器,已达到最大重试次数")
|
|
140
|
-
return False
|
|
141
|
-
|
|
142
|
-
def _cleanup_stale_instance(self):
|
|
143
|
-
"""清理可能存在的残留实例"""
|
|
144
|
-
if not self._client_initialized:
|
|
145
|
-
return
|
|
146
|
-
|
|
147
|
-
try:
|
|
148
|
-
self.nacos_client.remove_naming_instance(
|
|
149
|
-
service_name=self.service_name,
|
|
150
|
-
ip=self.real_ip,
|
|
151
|
-
port=int(self.port),
|
|
152
|
-
cluster_name="DEFAULT"
|
|
153
|
-
)
|
|
154
|
-
SYLogger.warning(f"nacos:清理残留实例: {self.real_ip}:{self.port}")
|
|
155
|
-
except Exception as e:
|
|
156
|
-
SYLogger.error(f"nacos:清理残留实例异常: {e}")
|
|
157
|
-
|
|
158
|
-
def ensure_client_connected(self, retry_once=False):
|
|
159
|
-
"""确保Nacos客户端已连接,返回连接状态"""
|
|
160
|
-
# 使用线程锁保护客户端初始化状态
|
|
161
|
-
with self._state_lock:
|
|
162
|
-
if self._client_initialized:
|
|
163
|
-
return True
|
|
164
|
-
|
|
165
|
-
SYLogger.warning("nacos:客户端未初始化,尝试连接...")
|
|
166
|
-
|
|
167
|
-
# 记录尝试次数,避免无限循环
|
|
168
|
-
attempt = 0
|
|
169
|
-
max_attempts = 2 if retry_once else self.max_retries
|
|
170
|
-
|
|
171
|
-
while attempt < max_attempts:
|
|
172
|
-
try:
|
|
173
|
-
register_ip = self.nacos_config['registerIp']
|
|
174
|
-
namespace_id = self.nacos_config['namespaceId']
|
|
175
|
-
|
|
176
|
-
# 创建新的Nacos客户端实例
|
|
177
|
-
self.nacos_client = nacos.NacosClient(
|
|
178
|
-
server_addresses=register_ip,
|
|
179
|
-
namespace=namespace_id
|
|
180
|
-
)
|
|
181
|
-
|
|
182
|
-
# 验证客户端是否真正可用
|
|
183
|
-
connection_valid = self._verify_client_connection()
|
|
184
|
-
|
|
185
|
-
if connection_valid:
|
|
186
|
-
self._client_initialized = True
|
|
187
|
-
SYLogger.info("nacos:客户端初始化成功")
|
|
188
|
-
|
|
189
|
-
# 客户端重新连接后,检查服务注册状态
|
|
190
|
-
self.registered = self.check_service_registered()
|
|
191
|
-
return True
|
|
192
|
-
else:
|
|
193
|
-
raise ConnectionError("nacos:客户端初始化后无法验证连接")
|
|
194
|
-
|
|
195
|
-
except Exception as e:
|
|
196
|
-
attempt += 1
|
|
197
|
-
delay = min(self.retry_delay, self.max_retry_delay)
|
|
198
|
-
|
|
199
|
-
SYLogger.error(
|
|
200
|
-
f"nacos:客户端初始化失败 (尝试 {attempt}/{max_attempts}): {e}")
|
|
201
|
-
time.sleep(delay)
|
|
202
|
-
|
|
203
|
-
SYLogger.error("nacos:无法连接到 Nacos 服务器,已达到最大重试次数")
|
|
204
|
-
return False
|
|
205
|
-
|
|
206
|
-
def _verify_client_connection(self):
|
|
207
|
-
"""验证客户端是否真正连接成功"""
|
|
208
|
-
# 本地开发模式下直接返回True,不进行实际验证
|
|
209
|
-
if not self.enable_register_nacos:
|
|
210
|
-
return True
|
|
211
|
-
|
|
212
|
-
try:
|
|
213
|
-
# 使用当前服务的命名实例查询来验证连接
|
|
214
|
-
namespace_id = self.nacos_config['namespaceId']
|
|
215
|
-
self.nacos_client.list_naming_instance(
|
|
216
|
-
service_name=self.service_name,
|
|
217
|
-
namespace_id=namespace_id,
|
|
218
|
-
group_name="DEFAULT_GROUP",
|
|
219
|
-
healthy_only=True
|
|
220
|
-
)
|
|
221
|
-
return True
|
|
222
|
-
except Exception as e:
|
|
223
|
-
SYLogger.warning(f"nacos:客户端连接验证失败: {e}")
|
|
224
|
-
return False
|
|
225
|
-
|
|
226
|
-
def check_service_registered(self):
|
|
227
|
-
"""检查服务是否已注册(基于实例列表)"""
|
|
228
|
-
# 本地开发模式下直接返回True,模拟已注册状态
|
|
229
|
-
if not self.enable_register_nacos:
|
|
230
|
-
return True
|
|
231
|
-
|
|
232
|
-
if not self.ensure_client_connected():
|
|
233
|
-
return False
|
|
234
|
-
|
|
235
|
-
try:
|
|
236
|
-
namespace_id = self.nacos_config['namespaceId']
|
|
237
|
-
instances = self.nacos_client.list_naming_instance(
|
|
238
|
-
service_name=self.service_name,
|
|
239
|
-
namespace_id=namespace_id,
|
|
240
|
-
group_name="DEFAULT_GROUP",
|
|
241
|
-
healthy_only=True,
|
|
242
|
-
)
|
|
243
|
-
|
|
244
|
-
# 检查是否存在包含当前IP和端口的实例
|
|
245
|
-
found = False
|
|
246
|
-
for instance in instances.get('hosts', []):
|
|
247
|
-
if (instance.get('ip') == self.real_ip and
|
|
248
|
-
instance.get('port') == int(self.port)):
|
|
249
|
-
SYLogger.info(f"nacos:找到已注册实例: {self.real_ip}:{self.port}")
|
|
250
|
-
found = True
|
|
251
|
-
break
|
|
252
|
-
|
|
253
|
-
if not found:
|
|
254
|
-
SYLogger.warning(f"nacos:未找到注册实例: {self.real_ip}:{self.port}")
|
|
255
|
-
|
|
256
|
-
# 带锁更新注册状态
|
|
257
|
-
with self._state_lock:
|
|
258
|
-
self.registered = found
|
|
259
|
-
|
|
260
|
-
return found
|
|
261
|
-
except Exception as e:
|
|
262
|
-
SYLogger.error(f"nacos:检查服务注册状态失败: {e}")
|
|
263
|
-
return False
|
|
264
|
-
|
|
265
|
-
def verify_registration(self):
|
|
266
|
-
"""多次验证服务是否成功注册(加锁防止重复执行)"""
|
|
267
|
-
# 新增:线程级别的单次执行锁(避免同一轮循环重复调用)
|
|
268
|
-
if self._verify_lock.locked():
|
|
269
|
-
SYLogger.warning("nacos:注册验证已在执行中,跳过重复调用")
|
|
270
|
-
return self.registered
|
|
271
|
-
|
|
272
|
-
with self._verify_lock:
|
|
273
|
-
# 冷却时间控制(避免短时间重复验证,15秒内不重复)
|
|
274
|
-
current_time = time.time()
|
|
275
|
-
if current_time - self._last_verify_time < self.heartbeat_interval:
|
|
276
|
-
return True
|
|
277
|
-
|
|
278
|
-
success_count = 0
|
|
279
|
-
verify_count = self.registration_verify_count
|
|
280
|
-
SYLogger.info(
|
|
281
|
-
f"nacos:开始验证服务注册状态,共验证 {verify_count} 次,间隔 {self.registration_verify_interval} 秒")
|
|
282
|
-
|
|
283
|
-
self._last_verify_time = current_time # 更新最后验证时间
|
|
284
|
-
|
|
285
|
-
for i in range(verify_count):
|
|
286
|
-
# 调用去重后的 check_service_registered
|
|
287
|
-
if self.check_service_registered():
|
|
288
|
-
success_count += 1
|
|
289
|
-
|
|
290
|
-
if i < verify_count - 1:
|
|
291
|
-
# 可中断的等待,替代 sleep
|
|
292
|
-
self._shutdown_event.wait(
|
|
293
|
-
self.registration_verify_interval)
|
|
294
|
-
if self._shutdown_event.is_set():
|
|
295
|
-
SYLogger.warning("nacos:应用正在关闭,终止注册验证")
|
|
296
|
-
break
|
|
297
|
-
|
|
298
|
-
# 验证结果判断
|
|
299
|
-
pass_threshold = verify_count / 2
|
|
300
|
-
result = success_count >= pass_threshold
|
|
301
|
-
|
|
302
|
-
if result:
|
|
303
|
-
SYLogger.info(
|
|
304
|
-
f"nacos:服务注册验证成功,{success_count}/{verify_count} 次验证通过")
|
|
305
|
-
else:
|
|
306
|
-
SYLogger.error(
|
|
307
|
-
f"nacos:服务注册验证失败,仅 {success_count}/{verify_count} 次验证通过")
|
|
308
|
-
|
|
309
|
-
return result
|
|
310
|
-
|
|
311
|
-
def register_with_retry(self):
|
|
312
|
-
"""带重试机制的服务注册(基于实例列表检查)"""
|
|
313
|
-
retry_count = 0
|
|
314
|
-
last_error = None
|
|
315
|
-
|
|
316
|
-
# 带锁重置注册状态
|
|
317
|
-
with self._state_lock:
|
|
318
|
-
self.registered = False
|
|
319
|
-
|
|
320
|
-
while (not self.registered) and (self.max_long_term_retries < 0 or retry_count < self.max_long_term_retries):
|
|
321
|
-
# 增加状态检查点,防止重复注册
|
|
322
|
-
with self._state_lock:
|
|
323
|
-
if self.registered:
|
|
324
|
-
return True
|
|
325
|
-
|
|
326
|
-
try:
|
|
327
|
-
# 尝试注册服务
|
|
328
|
-
register_success = self.register(force=True)
|
|
329
|
-
|
|
330
|
-
if not register_success:
|
|
331
|
-
raise RuntimeError("nacos:服务注册请求失败")
|
|
332
|
-
|
|
333
|
-
# 关键优化1:注册请求发送后,延迟一段时间再验证(默认3秒)
|
|
334
|
-
SYLogger.info(
|
|
335
|
-
f"nacos:服务注册请求已发送,延迟 {self.registration_post_delay} 秒后开始验证(确保Nacos服务器完成实例写入)")
|
|
336
|
-
time.sleep(self.registration_post_delay)
|
|
337
|
-
|
|
338
|
-
# 关键优化2:多次验证服务是否真正注册成功(默认3次,每次间隔2秒)
|
|
339
|
-
registered = self.verify_registration()
|
|
340
|
-
|
|
341
|
-
# 带锁更新注册状态
|
|
342
|
-
with self._state_lock:
|
|
343
|
-
self.registered = registered
|
|
344
|
-
|
|
345
|
-
# 再次检查状态,防止其他线程修改
|
|
346
|
-
with self._state_lock:
|
|
347
|
-
if self.registered:
|
|
348
|
-
# 注册成功后,更新客户端状态
|
|
349
|
-
self._client_initialized = True
|
|
350
|
-
|
|
351
|
-
# 注册成功后,通知心跳线程立即发送心跳
|
|
352
|
-
self._shutdown_event.set()
|
|
353
|
-
self._shutdown_event.clear()
|
|
354
|
-
|
|
355
|
-
# 注册成功后,更新监控线程的状态
|
|
356
|
-
self._long_term_retry_count = 0
|
|
357
|
-
|
|
358
|
-
SYLogger.info(
|
|
359
|
-
f"nacos:服务注册成功并通过验证: {self.service_name}")
|
|
360
|
-
return True
|
|
361
|
-
else:
|
|
362
|
-
raise RuntimeError("nacos:服务注册验证失败")
|
|
363
|
-
|
|
364
|
-
except Exception as e:
|
|
365
|
-
last_error = str(e)
|
|
366
|
-
retry_count += 1
|
|
367
|
-
delay = min(self.register_retry_interval, self.max_retry_delay)
|
|
368
|
-
|
|
369
|
-
SYLogger.warning(
|
|
370
|
-
f"nacos:服务注册尝试 {retry_count} 失败: {last_error},{delay}秒后重试")
|
|
371
|
-
time.sleep(delay)
|
|
372
|
-
|
|
373
|
-
# 最终检查,防止在最后一次重试后其他线程成功注册
|
|
374
|
-
with self._state_lock:
|
|
375
|
-
if self.registered:
|
|
376
|
-
return True
|
|
377
|
-
|
|
378
|
-
# 确实注册失败
|
|
379
|
-
if last_error:
|
|
380
|
-
SYLogger.error(f"nacos:服务注册失败,最终错误: {last_error}")
|
|
381
|
-
else:
|
|
382
|
-
SYLogger.error(f"nacos:服务注册失败,已达到最大重试次数: {self.service_name}")
|
|
383
|
-
|
|
384
|
-
return False
|
|
385
|
-
|
|
386
|
-
def register(self, force=False):
|
|
387
|
-
"""注册服务到Nacos"""
|
|
388
|
-
# 使用状态锁保护注册状态
|
|
389
|
-
with self._state_lock:
|
|
390
|
-
if self.registered and not force and self.check_service_registered():
|
|
391
|
-
return True
|
|
392
|
-
|
|
393
|
-
if self.registered and not force:
|
|
394
|
-
self.registered = False
|
|
395
|
-
SYLogger.warning("nacos:本地状态显示已注册,但Nacos中未找到服务实例,准备重新注册")
|
|
396
|
-
|
|
397
|
-
metadata = {
|
|
398
|
-
"ignore-metrics": "true",
|
|
399
|
-
# "preserved.heart.beat.interval": "3000", # 心跳间隔 3 秒
|
|
400
|
-
# "preserved.heart.beat.timeout": "15000", # 心跳超时 15 秒
|
|
401
|
-
# "preserved.ip.delete.timeout": "30000" # 实例删除超时 30 秒
|
|
402
|
-
}
|
|
403
|
-
if self.version:
|
|
404
|
-
metadata["version"] = self.version
|
|
405
|
-
|
|
406
|
-
for attempt in range(self.max_retries):
|
|
407
|
-
if not self.ensure_client_connected():
|
|
408
|
-
return False
|
|
409
|
-
|
|
410
|
-
try:
|
|
411
|
-
# 注册服务
|
|
412
|
-
self.nacos_client.add_naming_instance(
|
|
413
|
-
service_name=self.service_name,
|
|
414
|
-
ip=self.real_ip,
|
|
415
|
-
port=int(self.port),
|
|
416
|
-
metadata=metadata,
|
|
417
|
-
cluster_name="DEFAULT",
|
|
418
|
-
healthy=True,
|
|
419
|
-
ephemeral=True,
|
|
420
|
-
heartbeat_interval=self.heartbeat_interval
|
|
421
|
-
)
|
|
422
|
-
SYLogger.info(
|
|
423
|
-
f"nacos:服务 {self.service_name} 注册请求已发送: {self.real_ip}:{self.port}")
|
|
424
|
-
|
|
425
|
-
# 注册退出时的清理函数
|
|
426
|
-
if not hasattr(self, '_atexit_registered') or not self._atexit_registered:
|
|
427
|
-
atexit.register(self.deregister_service)
|
|
428
|
-
self._atexit_registered = True
|
|
429
|
-
|
|
430
|
-
return True
|
|
431
|
-
except Exception as e:
|
|
432
|
-
if "signal only works in main thread" in str(e):
|
|
433
|
-
return True
|
|
434
|
-
elif attempt < self.max_retries - 1:
|
|
435
|
-
SYLogger.warning(
|
|
436
|
-
f"nacos:服务注册失败 (尝试 {attempt+1}/{self.max_retries}): {e}")
|
|
437
|
-
time.sleep(self.retry_delay)
|
|
438
|
-
else:
|
|
439
|
-
SYLogger.error(f"nacos:服务注册失败,已达到最大重试次数: {e}")
|
|
440
|
-
return False
|
|
441
|
-
|
|
442
73
|
@staticmethod
|
|
443
74
|
def setup_nacos(config: dict):
|
|
444
|
-
"""创建并初始化Nacos
|
|
75
|
+
"""创建并初始化Nacos管理器(保持原有接口)"""
|
|
445
76
|
instance = NacosService(config)
|
|
446
77
|
|
|
447
|
-
# 仅在需要注册时执行注册逻辑
|
|
448
78
|
if instance.enable_register_nacos:
|
|
449
|
-
#
|
|
450
|
-
timeout = 60
|
|
79
|
+
# 启动注册线程
|
|
80
|
+
timeout = 60
|
|
451
81
|
start_time = time.time()
|
|
452
82
|
|
|
453
|
-
# 启动注册线程,不阻塞主线程(替换原线程池)
|
|
454
83
|
register_thread = threading.Thread(
|
|
455
|
-
target=instance.register_with_retry,
|
|
84
|
+
target=instance.registration.register_with_retry,
|
|
456
85
|
daemon=True,
|
|
457
86
|
name="NacosRegisterThread"
|
|
458
87
|
)
|
|
@@ -460,237 +89,38 @@ class NacosService(metaclass=SingletonMeta):
|
|
|
460
89
|
|
|
461
90
|
# 等待注册完成或超时
|
|
462
91
|
while True:
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
if instance.registered:
|
|
466
|
-
break
|
|
92
|
+
if instance.registration.registered:
|
|
93
|
+
break
|
|
467
94
|
|
|
468
95
|
if time.time() - start_time >= timeout:
|
|
469
|
-
# 超时处理
|
|
470
96
|
break
|
|
471
97
|
|
|
472
98
|
time.sleep(1)
|
|
473
99
|
|
|
474
100
|
# 最终状态检查
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
SYLogger.error(f"nacos:服务注册失败后,注销服务时发生错误: {e}")
|
|
482
|
-
raise RuntimeError("nacos:服务注册失败,应用启动终止")
|
|
101
|
+
if not instance.registration.registered:
|
|
102
|
+
try:
|
|
103
|
+
instance.registration.deregister_service()
|
|
104
|
+
except Exception as e:
|
|
105
|
+
SYLogger.error(f"nacos:服务注册失败后,注销服务时发生错误: {e}")
|
|
106
|
+
raise RuntimeError("nacos:服务注册失败,应用启动终止")
|
|
483
107
|
|
|
484
|
-
#
|
|
108
|
+
# 注册信号处理
|
|
485
109
|
signal.signal(signal.SIGTERM, instance.handle_signal)
|
|
486
110
|
signal.signal(signal.SIGINT, instance.handle_signal)
|
|
487
111
|
|
|
488
112
|
# 启动连接监控线程
|
|
489
|
-
threading.Thread(target=instance.monitor_connection,
|
|
490
|
-
|
|
113
|
+
threading.Thread(target=instance.discovery.monitor_connection,
|
|
114
|
+
args=(instance.registration,),
|
|
115
|
+
daemon=True,
|
|
116
|
+
name="NacosConnectionMonitorThread").start()
|
|
491
117
|
else:
|
|
492
118
|
SYLogger.info("nacos:本地开发模式,跳过服务注册流程")
|
|
493
119
|
|
|
494
120
|
return instance
|
|
495
121
|
|
|
496
|
-
def start_heartbeat(self):
|
|
497
|
-
"""启动心跳线程(确保单例)"""
|
|
498
|
-
with self._heartbeat_lock: # 加锁确保线程安全
|
|
499
|
-
# 双重检查:先判断线程是否已存在且存活
|
|
500
|
-
if self._heartbeat_thread is not None and self._heartbeat_thread.is_alive():
|
|
501
|
-
return
|
|
502
|
-
|
|
503
|
-
# 彻底清理可能的残留线程引用
|
|
504
|
-
self._heartbeat_thread = None
|
|
505
|
-
|
|
506
|
-
# 创建新的心跳线程
|
|
507
|
-
self._heartbeat_thread = threading.Thread(
|
|
508
|
-
target=self._send_heartbeat_loop,
|
|
509
|
-
name="NacosHeartbeatThread",
|
|
510
|
-
daemon=True
|
|
511
|
-
)
|
|
512
|
-
self._heartbeat_thread.daemon = True
|
|
513
|
-
self._heartbeat_thread.start()
|
|
514
|
-
SYLogger.info(
|
|
515
|
-
f"nacos:心跳线程启动,线程ID: {self._heartbeat_thread.ident},"
|
|
516
|
-
f"心跳间隔: {self.heartbeat_interval}秒,"
|
|
517
|
-
f"心跳超时: {self.heartbeat_timeout}秒"
|
|
518
|
-
)
|
|
519
|
-
|
|
520
|
-
def _send_heartbeat_loop(self):
|
|
521
|
-
"""优化后的心跳发送循环,确保严格按间隔执行"""
|
|
522
|
-
current_thread = threading.current_thread()
|
|
523
|
-
thread_ident = current_thread.ident
|
|
524
|
-
SYLogger.info(
|
|
525
|
-
f"nacos:心跳循环启动 - 线程ID: {thread_ident}, "
|
|
526
|
-
f"配置间隔: {self.heartbeat_interval}秒, "
|
|
527
|
-
f"超时时间: {self.heartbeat_timeout}秒"
|
|
528
|
-
)
|
|
529
|
-
|
|
530
|
-
consecutive_fail = 0 # 连续失败计数器
|
|
531
|
-
|
|
532
|
-
while not self._shutdown_event.is_set():
|
|
533
|
-
# 记录当前时间,作为本次心跳的基准
|
|
534
|
-
current_time = time.time()
|
|
535
|
-
|
|
536
|
-
try:
|
|
537
|
-
# 检查注册状态(带锁读取)
|
|
538
|
-
with self._state_lock:
|
|
539
|
-
registered_status = self.registered
|
|
540
|
-
|
|
541
|
-
if not registered_status:
|
|
542
|
-
SYLogger.warning(
|
|
543
|
-
f"nacos:服务未注册,跳过心跳 - 线程ID: {thread_ident}")
|
|
544
|
-
consecutive_fail = 0
|
|
545
|
-
else:
|
|
546
|
-
# 发送心跳(15秒超时)
|
|
547
|
-
success = self.send_heartbeat()
|
|
548
|
-
if success:
|
|
549
|
-
consecutive_fail = 0
|
|
550
|
-
SYLogger.info(
|
|
551
|
-
f"nacos:心跳发送成功 - 时间: {current_time:.3f}, "
|
|
552
|
-
f"间隔: {self.heartbeat_interval}秒"
|
|
553
|
-
)
|
|
554
|
-
else:
|
|
555
|
-
consecutive_fail += 1
|
|
556
|
-
SYLogger.warning(
|
|
557
|
-
f"nacos:心跳发送失败 - 连续失败: {consecutive_fail}次"
|
|
558
|
-
)
|
|
559
|
-
if consecutive_fail >= 5:
|
|
560
|
-
SYLogger.error("nacos:心跳连续失败5次,尝试重连")
|
|
561
|
-
self.reconnect_nacos_client()
|
|
562
|
-
consecutive_fail = 0
|
|
563
|
-
|
|
564
|
-
except Exception as e:
|
|
565
|
-
consecutive_fail += 1
|
|
566
|
-
SYLogger.error(
|
|
567
|
-
f"nacos:心跳异常: {str(e)}, 连续失败: {consecutive_fail}次")
|
|
568
|
-
|
|
569
|
-
self._shutdown_event.wait(self.heartbeat_interval)
|
|
570
|
-
|
|
571
|
-
SYLogger.info(f"nacos:心跳循环已停止 - 线程ID: {thread_ident}")
|
|
572
|
-
|
|
573
|
-
def send_heartbeat(self):
|
|
574
|
-
"""发送心跳并添加10秒超时控制(仅保留核心逻辑,移除重复日志)"""
|
|
575
|
-
if not self.ensure_client_connected():
|
|
576
|
-
SYLogger.warning("nacos:客户端未连接,心跳发送失败")
|
|
577
|
-
return False
|
|
578
|
-
|
|
579
|
-
# 用线程+join实现10秒超时控制
|
|
580
|
-
result_list = [] # 用于线程间传递结果
|
|
581
|
-
|
|
582
|
-
def heartbeat_task():
|
|
583
|
-
"""心跳实际执行任务"""
|
|
584
|
-
try:
|
|
585
|
-
result = self._send_heartbeat_internal()
|
|
586
|
-
result_list.append(result)
|
|
587
|
-
except Exception as e:
|
|
588
|
-
SYLogger.error(f"nacos:心跳任务执行异常: {e}")
|
|
589
|
-
result_list.append(False)
|
|
590
|
-
|
|
591
|
-
# 启动心跳任务线程
|
|
592
|
-
task_thread = threading.Thread(
|
|
593
|
-
target=heartbeat_task,
|
|
594
|
-
daemon=True,
|
|
595
|
-
name="NacosHeartbeatTaskThread"
|
|
596
|
-
)
|
|
597
|
-
task_thread.start()
|
|
598
|
-
|
|
599
|
-
# 等待线程完成,最多等待10秒
|
|
600
|
-
task_thread.join(timeout=self.heartbeat_timeout)
|
|
601
|
-
|
|
602
|
-
# 处理结果
|
|
603
|
-
if not result_list:
|
|
604
|
-
# 超时未返回
|
|
605
|
-
SYLogger.error(f"nacos:心跳发送超时({self.heartbeat_timeout}秒)")
|
|
606
|
-
self._client_initialized = False # 强制重连
|
|
607
|
-
return False
|
|
608
|
-
|
|
609
|
-
return result_list[0]
|
|
610
|
-
|
|
611
|
-
def _send_heartbeat_internal(self):
|
|
612
|
-
"""实际的心跳发送逻辑"""
|
|
613
|
-
result = self.nacos_client.send_heartbeat(
|
|
614
|
-
service_name=self.service_name,
|
|
615
|
-
ip=self.real_ip,
|
|
616
|
-
port=int(self.port),
|
|
617
|
-
cluster_name="DEFAULT",
|
|
618
|
-
weight=1.0,
|
|
619
|
-
metadata={"version": self.version} if self.version else None
|
|
620
|
-
)
|
|
621
|
-
|
|
622
|
-
# 处理返回结果
|
|
623
|
-
if result and isinstance(result, dict) and result.get('lightBeatEnabled', False):
|
|
624
|
-
SYLogger.info(f"nacos:心跳发送成功,Nacos返回: {result}")
|
|
625
|
-
return True
|
|
626
|
-
else:
|
|
627
|
-
SYLogger.warning(f"nacos:心跳发送失败,Nacos返回: {result}")
|
|
628
|
-
return False
|
|
629
|
-
|
|
630
|
-
def reconnect_nacos_client(self):
|
|
631
|
-
"""重新连接Nacos客户端"""
|
|
632
|
-
SYLogger.warning("nacos:尝试重新连接Nacos客户端")
|
|
633
|
-
self._client_initialized = False
|
|
634
|
-
return self.ensure_client_connected()
|
|
635
|
-
|
|
636
|
-
def monitor_connection(self):
|
|
637
|
-
"""优化的连接监控线程(彻底去重)"""
|
|
638
|
-
# 单例锁:防止重复启动
|
|
639
|
-
with self._monitor_thread_lock:
|
|
640
|
-
if self._shutdown_event.is_set() or self._monitor_thread_started:
|
|
641
|
-
SYLogger.warning("nacos:监控线程已启动/已关闭,拒绝重复启动")
|
|
642
|
-
return
|
|
643
|
-
self._monitor_thread_started = True
|
|
644
|
-
|
|
645
|
-
check_interval = self.connection_check_interval
|
|
646
|
-
SYLogger.info(
|
|
647
|
-
f"nacos:连接监控线程启动 - 线程ID: {threading.current_thread().ident}")
|
|
648
|
-
|
|
649
|
-
while not self._shutdown_event.is_set():
|
|
650
|
-
try:
|
|
651
|
-
# 步骤1:检查客户端连接(仅在连接断开时重试)
|
|
652
|
-
if not self._client_initialized:
|
|
653
|
-
SYLogger.warning("nacos:客户端未连接,尝试重新初始化")
|
|
654
|
-
self.ensure_client_connected()
|
|
655
|
-
else:
|
|
656
|
-
# 步骤2:检查注册状态(仅检查一次,不重复调用)
|
|
657
|
-
current_registered = self.check_service_registered()
|
|
658
|
-
|
|
659
|
-
# 步骤3:仅在注册状态变化时,才触发验证+重新注册
|
|
660
|
-
with self._state_lock:
|
|
661
|
-
if current_registered != self.registered:
|
|
662
|
-
self.registered = current_registered
|
|
663
|
-
if not current_registered:
|
|
664
|
-
SYLogger.warning("nacos:服务实例未注册,触发单次重新注册")
|
|
665
|
-
# 启动单次重试线程(非循环)
|
|
666
|
-
retry_thread = threading.Thread(
|
|
667
|
-
target=self.register,
|
|
668
|
-
args=(True,),
|
|
669
|
-
daemon=True,
|
|
670
|
-
name="NacosSingleRetryThread"
|
|
671
|
-
)
|
|
672
|
-
retry_thread.start()
|
|
673
|
-
else:
|
|
674
|
-
# 仅在「从未注册→已注册」时验证一次
|
|
675
|
-
SYLogger.info("nacos:服务实例已注册,触发单次验证")
|
|
676
|
-
self.verify_registration()
|
|
677
|
-
|
|
678
|
-
# 优化2:固定休眠,避免逻辑耗时导致的间隔混乱
|
|
679
|
-
self._shutdown_event.wait(check_interval)
|
|
680
|
-
|
|
681
|
-
except Exception as e:
|
|
682
|
-
SYLogger.error(f"nacos:连接监控异常: {str(e)}")
|
|
683
|
-
# 异常时缩短休眠,快速恢复
|
|
684
|
-
self._shutdown_event.wait(5)
|
|
685
|
-
|
|
686
|
-
# 线程退出重置标记
|
|
687
|
-
with self._monitor_thread_lock:
|
|
688
|
-
self._monitor_thread_started = False
|
|
689
|
-
SYLogger.info(
|
|
690
|
-
f"nacos:连接监控线程退出 - 线程ID: {threading.current_thread().ident}")
|
|
691
|
-
|
|
692
122
|
def get_service_ip(self, config_ip):
|
|
693
|
-
"""获取服务实际IP
|
|
123
|
+
"""获取服务实际IP地址(保持原有逻辑)"""
|
|
694
124
|
if config_ip in ['127.0.0.1', '0.0.0.0']:
|
|
695
125
|
try:
|
|
696
126
|
with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as s:
|
|
@@ -700,191 +130,21 @@ class NacosService(metaclass=SingletonMeta):
|
|
|
700
130
|
return '127.0.0.1'
|
|
701
131
|
return config_ip
|
|
702
132
|
|
|
703
|
-
def deregister_service(self):
|
|
704
|
-
"""从Nacos注销服务"""
|
|
705
|
-
with self._state_lock:
|
|
706
|
-
if not self.registered or not self._client_initialized:
|
|
707
|
-
return
|
|
708
|
-
|
|
709
|
-
SYLogger.info("nacos:正在注销服务...")
|
|
710
|
-
try:
|
|
711
|
-
self.nacos_client.remove_naming_instance(
|
|
712
|
-
service_name=self.service_name,
|
|
713
|
-
ip=self.real_ip,
|
|
714
|
-
port=int(self.port),
|
|
715
|
-
cluster_name="DEFAULT"
|
|
716
|
-
)
|
|
717
|
-
with self._state_lock:
|
|
718
|
-
self.registered = False
|
|
719
|
-
SYLogger.info(f"nacos:服务 {self.service_name} 已注销")
|
|
720
|
-
except Exception as e:
|
|
721
|
-
SYLogger.error(f"nacos:注销服务时发生错误: {e}")
|
|
722
|
-
finally:
|
|
723
|
-
self._shutdown_event.set()
|
|
724
|
-
|
|
725
133
|
def handle_signal(self, signum, frame):
|
|
726
|
-
"""
|
|
134
|
+
"""处理退出信号(保持原有逻辑)"""
|
|
727
135
|
SYLogger.info(f"nacos:收到信号 {signum},正在关闭服务...")
|
|
728
|
-
self.deregister_service()
|
|
136
|
+
self.registration.deregister_service()
|
|
729
137
|
sys.exit(0)
|
|
730
138
|
|
|
731
|
-
|
|
732
|
-
"""读取共享配置"""
|
|
733
|
-
configs = {}
|
|
734
|
-
shared_configs = self.nacos_config.get('sharedConfigs', [])
|
|
735
|
-
|
|
736
|
-
for config in shared_configs:
|
|
737
|
-
data_id = config['dataId']
|
|
738
|
-
group = config['group']
|
|
739
|
-
|
|
740
|
-
for attempt in range(self.max_retries):
|
|
741
|
-
try:
|
|
742
|
-
# 检查客户端连接
|
|
743
|
-
if not self.ensure_client_connected():
|
|
744
|
-
self.reconnect_nacos_client()
|
|
745
|
-
|
|
746
|
-
# 获取配置
|
|
747
|
-
content = self.nacos_client.get_config(data_id, group)
|
|
748
|
-
|
|
749
|
-
try:
|
|
750
|
-
configs[data_id] = json.loads(content)
|
|
751
|
-
except json.JSONDecodeError:
|
|
752
|
-
try:
|
|
753
|
-
configs[data_id] = yaml.safe_load(content)
|
|
754
|
-
except yaml.YAMLError:
|
|
755
|
-
SYLogger.error(f"nacos:无法解析 {data_id} 的内容")
|
|
756
|
-
break
|
|
757
|
-
except Exception as e:
|
|
758
|
-
if attempt < self.max_retries - 1:
|
|
759
|
-
SYLogger.warning(
|
|
760
|
-
f"nacos:读取配置 {data_id} 失败 (尝试 {attempt+1}/{self.max_retries}): {e}")
|
|
761
|
-
time.sleep(self.retry_delay)
|
|
762
|
-
else:
|
|
763
|
-
SYLogger.error(
|
|
764
|
-
f"nacos:读取配置 {data_id} 失败,已达到最大重试次数: {e}")
|
|
765
|
-
|
|
766
|
-
return configs
|
|
767
|
-
|
|
139
|
+
# 以下为兼容原有接口的封装方法
|
|
768
140
|
def add_config_listener(self, data_id: str, callback: Callable[[str], None]):
|
|
769
|
-
|
|
770
|
-
self._config_listeners[data_id] = callback
|
|
771
|
-
# 初始获取一次配置
|
|
772
|
-
if config := self.get_config(data_id):
|
|
773
|
-
callback(config)
|
|
141
|
+
return self.config_manager.add_config_listener(data_id, callback)
|
|
774
142
|
|
|
775
143
|
def get_config(self, data_id: str, group: str = "DEFAULT_GROUP") -> Optional[str]:
|
|
776
|
-
|
|
777
|
-
if not self.ensure_client_connected():
|
|
778
|
-
return None
|
|
779
|
-
|
|
780
|
-
try:
|
|
781
|
-
return self.nacos_client.get_config(data_id, group=group)
|
|
782
|
-
except Exception as e:
|
|
783
|
-
SYLogger.error(f"nacos:获取配置 {data_id} 失败: {str(e)}")
|
|
784
|
-
return None
|
|
785
|
-
|
|
786
|
-
def _watch_configs(self):
|
|
787
|
-
"""配置监听线程"""
|
|
788
|
-
check_interval = self.config_watch_interval
|
|
789
|
-
|
|
790
|
-
while not self._shutdown_event.is_set():
|
|
791
|
-
try:
|
|
792
|
-
for data_id, callback in list(self._config_listeners.items()):
|
|
793
|
-
new_config = self.get_config(data_id)
|
|
794
|
-
if new_config and new_config != self._config_cache.get(data_id):
|
|
795
|
-
# 直接执行回调(替换原线程池,配置回调通常为轻量操作)
|
|
796
|
-
callback(new_config)
|
|
797
|
-
self._config_cache[data_id] = new_config
|
|
798
|
-
try:
|
|
799
|
-
self.share_configs[data_id] = json.loads(
|
|
800
|
-
new_config)
|
|
801
|
-
except json.JSONDecodeError:
|
|
802
|
-
try:
|
|
803
|
-
self.share_configs[data_id] = yaml.safe_load(
|
|
804
|
-
new_config)
|
|
805
|
-
except yaml.YAMLError:
|
|
806
|
-
SYLogger.error(f"nacos:无法解析 {data_id} 的内容")
|
|
807
|
-
except Exception as e:
|
|
808
|
-
SYLogger.error(f"nacos:配置监视线程异常: {str(e)}")
|
|
809
|
-
self._shutdown_event.wait(check_interval)
|
|
144
|
+
return self.config_manager.get_config(data_id, group)
|
|
810
145
|
|
|
811
146
|
def discover_services(self, service_name: str, group: str = "DEFAULT_GROUP", version: str = None) -> List[Dict]:
|
|
812
|
-
|
|
813
|
-
if not self.ensure_client_connected():
|
|
814
|
-
return []
|
|
815
|
-
|
|
816
|
-
return self.get_service_instances(service_name, group, version)
|
|
147
|
+
return self.discovery.discover_services(service_name, group, version)
|
|
817
148
|
|
|
818
149
|
def get_service_instances(self, service_name: str, group: str = "DEFAULT_GROUP", target_version: str = None) -> List[Dict]:
|
|
819
|
-
|
|
820
|
-
获取服务实例列表,并按照以下优先级规则筛选:
|
|
821
|
-
1. 相同版本号的实例
|
|
822
|
-
2. 无版本号的实例
|
|
823
|
-
3. 所有实例中轮询
|
|
824
|
-
"""
|
|
825
|
-
try:
|
|
826
|
-
namespace_id = self.nacos_config['namespaceId']
|
|
827
|
-
instances = self.nacos_client.list_naming_instance(
|
|
828
|
-
service_name,
|
|
829
|
-
namespace_id=namespace_id,
|
|
830
|
-
group_name=group,
|
|
831
|
-
healthy_only=True,
|
|
832
|
-
)
|
|
833
|
-
|
|
834
|
-
if not instances or 'hosts' not in instances:
|
|
835
|
-
SYLogger.info(f"nacos:未发现 {service_name} 的服务实例")
|
|
836
|
-
return []
|
|
837
|
-
|
|
838
|
-
all_instances = instances.get('hosts', [])
|
|
839
|
-
# 筛选已上线实例
|
|
840
|
-
all_instances = [
|
|
841
|
-
instance for instance in all_instances
|
|
842
|
-
if instance.get('enabled', True) # 默认True担心阿里变更sdk
|
|
843
|
-
]
|
|
844
|
-
SYLogger.info(
|
|
845
|
-
f"nacos:共发现 {len(all_instances)} 个 {service_name} 服务实例")
|
|
846
|
-
|
|
847
|
-
# 确定要使用的目标版本,如果未指定则使用当前服务的版本
|
|
848
|
-
version_to_use = target_version or self.version
|
|
849
|
-
|
|
850
|
-
# 按规则筛选实例
|
|
851
|
-
if version_to_use:
|
|
852
|
-
# 1. 筛选相同版本号的实例
|
|
853
|
-
same_version_instances = [
|
|
854
|
-
instance for instance in all_instances
|
|
855
|
-
if instance.get('metadata', {}).get('version') == version_to_use
|
|
856
|
-
]
|
|
857
|
-
|
|
858
|
-
if same_version_instances:
|
|
859
|
-
SYLogger.info(
|
|
860
|
-
f"nacos:筛选出 {len(same_version_instances)} 个与当前版本({version_to_use})匹配的实例")
|
|
861
|
-
return same_version_instances
|
|
862
|
-
|
|
863
|
-
# 2. 如果没有相同版本的实例,筛选无版本号的实例
|
|
864
|
-
no_version_instances = [
|
|
865
|
-
instance for instance in all_instances
|
|
866
|
-
if 'version' not in instance.get('metadata', {})
|
|
867
|
-
]
|
|
868
|
-
|
|
869
|
-
if no_version_instances:
|
|
870
|
-
SYLogger.info(
|
|
871
|
-
f"nacos:未找到相同版本({version_to_use})的实例,筛选出 {len(no_version_instances)} 个无版本号的实例")
|
|
872
|
-
return no_version_instances
|
|
873
|
-
|
|
874
|
-
# 3. 如果没有指定版本或前两个规则都不满足,使用轮询方式选择所有健康实例
|
|
875
|
-
SYLogger.info(
|
|
876
|
-
f"nacos:使用轮询方式从 {len(all_instances)} 个实例中选择")
|
|
877
|
-
|
|
878
|
-
# 线程安全地获取下一个轮询索引
|
|
879
|
-
with self._round_robin_lock:
|
|
880
|
-
selected_index = self._round_robin_index % len(all_instances)
|
|
881
|
-
# 更新轮询索引,为下一次请求做准备
|
|
882
|
-
self._round_robin_index = (
|
|
883
|
-
selected_index + 1) % len(all_instances)
|
|
884
|
-
|
|
885
|
-
# 返回包含当前选中实例的列表
|
|
886
|
-
return [all_instances[selected_index]]
|
|
887
|
-
|
|
888
|
-
except Exception as e:
|
|
889
|
-
SYLogger.error(f"nacos:服务发现失败: {service_name}: {str(e)}")
|
|
890
|
-
return []
|
|
150
|
+
return self.discovery.get_service_instances(service_name, group, target_version)
|