sycommon-python-lib 0.1.56__py3-none-any.whl → 0.1.56b2__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 +3 -24
- sycommon/llm/embedding.py +23 -78
- sycommon/llm/get_llm.py +164 -24
- sycommon/logging/kafka_log.py +433 -187
- sycommon/middleware/exception.py +16 -10
- sycommon/middleware/timeout.py +1 -2
- sycommon/middleware/traceid.py +76 -81
- sycommon/rabbitmq/rabbitmq_client.py +242 -232
- sycommon/rabbitmq/rabbitmq_pool.py +218 -278
- sycommon/rabbitmq/rabbitmq_service.py +843 -25
- sycommon/services.py +96 -122
- sycommon/synacos/nacos_service.py +779 -63
- sycommon/tools/merge_headers.py +0 -20
- sycommon/tools/snowflake.py +153 -101
- {sycommon_python_lib-0.1.56.dist-info → sycommon_python_lib-0.1.56b2.dist-info}/METADATA +8 -10
- {sycommon_python_lib-0.1.56.dist-info → sycommon_python_lib-0.1.56b2.dist-info}/RECORD +19 -40
- sycommon/config/LangfuseConfig.py +0 -15
- sycommon/config/SentryConfig.py +0 -13
- sycommon/llm/llm_tokens.py +0 -119
- sycommon/llm/struct_token.py +0 -192
- sycommon/llm/sy_langfuse.py +0 -103
- sycommon/llm/usage_token.py +0 -117
- sycommon/notice/__init__.py +0 -0
- sycommon/notice/uvicorn_monitor.py +0 -200
- sycommon/rabbitmq/rabbitmq_service_client_manager.py +0 -206
- sycommon/rabbitmq/rabbitmq_service_connection_monitor.py +0 -73
- sycommon/rabbitmq/rabbitmq_service_consumer_manager.py +0 -285
- sycommon/rabbitmq/rabbitmq_service_core.py +0 -117
- sycommon/rabbitmq/rabbitmq_service_producer_manager.py +0 -238
- sycommon/sentry/__init__.py +0 -0
- sycommon/sentry/sy_sentry.py +0 -35
- sycommon/synacos/nacos_client_base.py +0 -119
- sycommon/synacos/nacos_config_manager.py +0 -107
- sycommon/synacos/nacos_heartbeat_manager.py +0 -144
- sycommon/synacos/nacos_service_discovery.py +0 -157
- sycommon/synacos/nacos_service_registration.py +0 -270
- sycommon/tools/env.py +0 -62
- {sycommon_python_lib-0.1.56.dist-info → sycommon_python_lib-0.1.56b2.dist-info}/WHEEL +0 -0
- {sycommon_python_lib-0.1.56.dist-info → sycommon_python_lib-0.1.56b2.dist-info}/entry_points.txt +0 -0
- {sycommon_python_lib-0.1.56.dist-info → sycommon_python_lib-0.1.56b2.dist-info}/top_level.txt +0 -0
|
@@ -1,119 +0,0 @@
|
|
|
1
|
-
import threading
|
|
2
|
-
import time
|
|
3
|
-
from typing import Optional
|
|
4
|
-
import nacos
|
|
5
|
-
from sycommon.logging.kafka_log import SYLogger
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
class NacosClientBase:
|
|
9
|
-
"""Nacos客户端基础类 - 负责客户端初始化和连接管理"""
|
|
10
|
-
|
|
11
|
-
def __init__(self, nacos_config: dict, enable_register_nacos: bool):
|
|
12
|
-
self.nacos_config = nacos_config
|
|
13
|
-
self.enable_register_nacos = enable_register_nacos
|
|
14
|
-
|
|
15
|
-
# 客户端配置
|
|
16
|
-
self.max_retries = self.nacos_config.get('maxRetries', 5)
|
|
17
|
-
self.retry_delay = self.nacos_config.get('retryDelay', 5)
|
|
18
|
-
self.max_retry_delay = self.nacos_config.get('maxRetryDelay', 30)
|
|
19
|
-
|
|
20
|
-
# 状态管理
|
|
21
|
-
self._client_initialized = False
|
|
22
|
-
self._state_lock = threading.RLock()
|
|
23
|
-
self._shutdown_event = threading.Event()
|
|
24
|
-
self.nacos_client: Optional[nacos.NacosClient] = None
|
|
25
|
-
|
|
26
|
-
def _initialize_client(self) -> bool:
|
|
27
|
-
"""初始化Nacos客户端(仅首次调用时执行)"""
|
|
28
|
-
if self._client_initialized:
|
|
29
|
-
return True
|
|
30
|
-
|
|
31
|
-
for attempt in range(self.max_retries):
|
|
32
|
-
try:
|
|
33
|
-
register_ip = self.nacos_config['registerIp']
|
|
34
|
-
namespace_id = self.nacos_config['namespaceId']
|
|
35
|
-
self.nacos_client = nacos.NacosClient(
|
|
36
|
-
server_addresses=register_ip,
|
|
37
|
-
namespace=namespace_id
|
|
38
|
-
)
|
|
39
|
-
SYLogger.info("nacos:客户端初始化成功")
|
|
40
|
-
self._client_initialized = True
|
|
41
|
-
return True
|
|
42
|
-
except Exception as e:
|
|
43
|
-
delay = min(self.retry_delay, self.max_retry_delay)
|
|
44
|
-
SYLogger.error(
|
|
45
|
-
f"nacos:客户端初始化失败 (尝试 {attempt+1}/{self.max_retries}): {e}")
|
|
46
|
-
time.sleep(delay)
|
|
47
|
-
|
|
48
|
-
SYLogger.warning("nacos:无法连接到 Nacos 服务器,已达到最大重试次数")
|
|
49
|
-
return False
|
|
50
|
-
|
|
51
|
-
def ensure_client_connected(self, retry_once: bool = False) -> bool:
|
|
52
|
-
"""确保Nacos客户端已连接,返回连接状态"""
|
|
53
|
-
with self._state_lock:
|
|
54
|
-
if self._client_initialized:
|
|
55
|
-
return True
|
|
56
|
-
|
|
57
|
-
SYLogger.warning("nacos:客户端未初始化,尝试连接...")
|
|
58
|
-
|
|
59
|
-
max_attempts = 2 if retry_once else self.max_retries
|
|
60
|
-
attempt = 0
|
|
61
|
-
|
|
62
|
-
while attempt < max_attempts:
|
|
63
|
-
try:
|
|
64
|
-
register_ip = self.nacos_config['registerIp']
|
|
65
|
-
namespace_id = self.nacos_config['namespaceId']
|
|
66
|
-
|
|
67
|
-
self.nacos_client = nacos.NacosClient(
|
|
68
|
-
server_addresses=register_ip,
|
|
69
|
-
namespace=namespace_id
|
|
70
|
-
)
|
|
71
|
-
|
|
72
|
-
if self._verify_client_connection():
|
|
73
|
-
with self._state_lock:
|
|
74
|
-
self._client_initialized = True
|
|
75
|
-
SYLogger.info("nacos:客户端初始化成功")
|
|
76
|
-
return True
|
|
77
|
-
else:
|
|
78
|
-
raise ConnectionError("nacos:客户端初始化后无法验证连接")
|
|
79
|
-
|
|
80
|
-
except Exception as e:
|
|
81
|
-
attempt += 1
|
|
82
|
-
delay = min(self.retry_delay, self.max_retry_delay)
|
|
83
|
-
SYLogger.error(
|
|
84
|
-
f"nacos:客户端初始化失败 (尝试 {attempt}/{max_attempts}): {e}")
|
|
85
|
-
time.sleep(delay)
|
|
86
|
-
|
|
87
|
-
SYLogger.error("nacos:无法连接到 Nacos 服务器,已达到最大重试次数")
|
|
88
|
-
return False
|
|
89
|
-
|
|
90
|
-
def _verify_client_connection(self) -> bool:
|
|
91
|
-
"""验证客户端是否真正连接成功"""
|
|
92
|
-
if not self.enable_register_nacos:
|
|
93
|
-
return True
|
|
94
|
-
|
|
95
|
-
try:
|
|
96
|
-
namespace_id = self.nacos_config['namespaceId']
|
|
97
|
-
self.nacos_client.list_naming_instance(
|
|
98
|
-
service_name="", # 空服务名仅用于验证连接
|
|
99
|
-
namespace_id=namespace_id,
|
|
100
|
-
group_name="DEFAULT_GROUP",
|
|
101
|
-
healthy_only=True
|
|
102
|
-
)
|
|
103
|
-
return True
|
|
104
|
-
except Exception as e:
|
|
105
|
-
SYLogger.warning(f"nacos:客户端连接验证失败: {e}")
|
|
106
|
-
return False
|
|
107
|
-
|
|
108
|
-
def reconnect_nacos_client(self) -> bool:
|
|
109
|
-
"""重新连接Nacos客户端"""
|
|
110
|
-
SYLogger.warning("nacos:尝试重新连接Nacos客户端")
|
|
111
|
-
with self._state_lock:
|
|
112
|
-
self._client_initialized = False
|
|
113
|
-
return self.ensure_client_connected()
|
|
114
|
-
|
|
115
|
-
@property
|
|
116
|
-
def is_connected(self) -> bool:
|
|
117
|
-
"""检查客户端是否已连接"""
|
|
118
|
-
with self._state_lock:
|
|
119
|
-
return self._client_initialized
|
|
@@ -1,107 +0,0 @@
|
|
|
1
|
-
import json
|
|
2
|
-
import threading
|
|
3
|
-
import time
|
|
4
|
-
from typing import Callable, Optional, Dict, List
|
|
5
|
-
from sycommon.synacos.nacos_client_base import NacosClientBase
|
|
6
|
-
import yaml
|
|
7
|
-
from sycommon.logging.kafka_log import SYLogger
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
class NacosConfigManager:
|
|
11
|
-
"""Nacos配置管理类 - 负责配置读取、监听和更新"""
|
|
12
|
-
|
|
13
|
-
def __init__(self, client_base: NacosClientBase):
|
|
14
|
-
self.client_base = client_base
|
|
15
|
-
|
|
16
|
-
# 配置
|
|
17
|
-
self.config_watch_interval = self.client_base.nacos_config.get(
|
|
18
|
-
'configWatchInterval', 30)
|
|
19
|
-
|
|
20
|
-
# 状态
|
|
21
|
-
self.share_configs: Dict = {}
|
|
22
|
-
self._config_listeners: Dict[str, Callable[[str], None]] = {}
|
|
23
|
-
self._config_cache: Dict[str, str] = {}
|
|
24
|
-
self._watch_thread: Optional[threading.Thread] = None
|
|
25
|
-
|
|
26
|
-
def read_configs(self, shared_configs: List[Dict]) -> dict:
|
|
27
|
-
"""读取共享配置"""
|
|
28
|
-
configs = {}
|
|
29
|
-
|
|
30
|
-
for config in shared_configs:
|
|
31
|
-
data_id = config['dataId']
|
|
32
|
-
group = config['group']
|
|
33
|
-
|
|
34
|
-
for attempt in range(self.client_base.max_retries):
|
|
35
|
-
try:
|
|
36
|
-
if not self.client_base.ensure_client_connected():
|
|
37
|
-
self.client_base.reconnect_nacos_client()
|
|
38
|
-
|
|
39
|
-
content = self.client_base.nacos_client.get_config(
|
|
40
|
-
data_id, group)
|
|
41
|
-
|
|
42
|
-
try:
|
|
43
|
-
configs[data_id] = json.loads(content)
|
|
44
|
-
except json.JSONDecodeError:
|
|
45
|
-
try:
|
|
46
|
-
configs[data_id] = yaml.safe_load(content)
|
|
47
|
-
except yaml.YAMLError:
|
|
48
|
-
SYLogger.error(f"nacos:无法解析 {data_id} 的内容")
|
|
49
|
-
break
|
|
50
|
-
except Exception as e:
|
|
51
|
-
if attempt < self.client_base.max_retries - 1:
|
|
52
|
-
SYLogger.warning(
|
|
53
|
-
f"nacos:读取配置 {data_id} 失败 (尝试 {attempt+1}/{self.client_base.max_retries}): {e}")
|
|
54
|
-
time.sleep(self.client_base.retry_delay)
|
|
55
|
-
else:
|
|
56
|
-
SYLogger.error(
|
|
57
|
-
f"nacos:读取配置 {data_id} 失败,已达到最大重试次数: {e}")
|
|
58
|
-
|
|
59
|
-
self.share_configs = configs
|
|
60
|
-
return configs
|
|
61
|
-
|
|
62
|
-
def add_config_listener(self, data_id: str, callback: Callable[[str], None]):
|
|
63
|
-
"""添加配置变更监听器"""
|
|
64
|
-
self._config_listeners[data_id] = callback
|
|
65
|
-
if config := self.get_config(data_id):
|
|
66
|
-
callback(config)
|
|
67
|
-
|
|
68
|
-
def get_config(self, data_id: str, group: str = "DEFAULT_GROUP") -> Optional[str]:
|
|
69
|
-
"""获取配置内容"""
|
|
70
|
-
if not self.client_base.ensure_client_connected():
|
|
71
|
-
return None
|
|
72
|
-
|
|
73
|
-
try:
|
|
74
|
-
return self.client_base.nacos_client.get_config(data_id, group=group)
|
|
75
|
-
except Exception as e:
|
|
76
|
-
SYLogger.error(f"nacos:获取配置 {data_id} 失败: {str(e)}")
|
|
77
|
-
return None
|
|
78
|
-
|
|
79
|
-
def start_watch_configs(self):
|
|
80
|
-
"""启动配置监视线程"""
|
|
81
|
-
self._watch_thread = threading.Thread(
|
|
82
|
-
target=self._watch_configs, daemon=True)
|
|
83
|
-
self._watch_thread.start()
|
|
84
|
-
|
|
85
|
-
def _watch_configs(self):
|
|
86
|
-
"""配置监听线程"""
|
|
87
|
-
check_interval = self.config_watch_interval
|
|
88
|
-
|
|
89
|
-
while not self.client_base._shutdown_event.is_set():
|
|
90
|
-
try:
|
|
91
|
-
for data_id, callback in list(self._config_listeners.items()):
|
|
92
|
-
new_config = self.get_config(data_id)
|
|
93
|
-
if new_config and new_config != self._config_cache.get(data_id):
|
|
94
|
-
callback(new_config)
|
|
95
|
-
self._config_cache[data_id] = new_config
|
|
96
|
-
try:
|
|
97
|
-
self.share_configs[data_id] = json.loads(
|
|
98
|
-
new_config)
|
|
99
|
-
except json.JSONDecodeError:
|
|
100
|
-
try:
|
|
101
|
-
self.share_configs[data_id] = yaml.safe_load(
|
|
102
|
-
new_config)
|
|
103
|
-
except yaml.YAMLError:
|
|
104
|
-
SYLogger.error(f"nacos:无法解析 {data_id} 的内容")
|
|
105
|
-
except Exception as e:
|
|
106
|
-
SYLogger.error(f"nacos:配置监视线程异常: {str(e)}")
|
|
107
|
-
self.client_base._shutdown_event.wait(check_interval)
|
|
@@ -1,144 +0,0 @@
|
|
|
1
|
-
import threading
|
|
2
|
-
import time
|
|
3
|
-
from sycommon.logging.kafka_log import SYLogger
|
|
4
|
-
from sycommon.synacos.nacos_client_base import NacosClientBase
|
|
5
|
-
from sycommon.synacos.nacos_service_registration import NacosServiceRegistration
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
class NacosHeartbeatManager:
|
|
9
|
-
"""Nacos心跳管理类 - 负责心跳发送和监控"""
|
|
10
|
-
|
|
11
|
-
def __init__(self, client_base: NacosClientBase, registration: NacosServiceRegistration, heartbeat_interval: int = 15):
|
|
12
|
-
self.client_base = client_base
|
|
13
|
-
self.registration = registration
|
|
14
|
-
|
|
15
|
-
# 心跳配置
|
|
16
|
-
self.heartbeat_interval = heartbeat_interval
|
|
17
|
-
self.heartbeat_timeout = 15
|
|
18
|
-
self.max_heartbeat_timeout = self.client_base.nacos_config.get(
|
|
19
|
-
'maxHeartbeatTimeout', 30)
|
|
20
|
-
|
|
21
|
-
# 状态管理
|
|
22
|
-
self._heartbeat_lock = threading.Lock()
|
|
23
|
-
self._heartbeat_thread = None
|
|
24
|
-
self._last_heartbeat_time = 0
|
|
25
|
-
self._heartbeat_fail_count = 0
|
|
26
|
-
|
|
27
|
-
def start_heartbeat(self):
|
|
28
|
-
"""启动心跳线程(确保单例)"""
|
|
29
|
-
with self._heartbeat_lock:
|
|
30
|
-
if self._heartbeat_thread is not None and self._heartbeat_thread.is_alive():
|
|
31
|
-
return
|
|
32
|
-
|
|
33
|
-
self._heartbeat_thread = None
|
|
34
|
-
|
|
35
|
-
self._heartbeat_thread = threading.Thread(
|
|
36
|
-
target=self._send_heartbeat_loop,
|
|
37
|
-
name="NacosHeartbeatThread",
|
|
38
|
-
daemon=True
|
|
39
|
-
)
|
|
40
|
-
self._heartbeat_thread.start()
|
|
41
|
-
SYLogger.info(
|
|
42
|
-
f"nacos:心跳线程启动,线程ID: {self._heartbeat_thread.ident},"
|
|
43
|
-
f"心跳间隔: {self.heartbeat_interval}秒,"
|
|
44
|
-
f"心跳超时: {self.heartbeat_timeout}秒"
|
|
45
|
-
)
|
|
46
|
-
|
|
47
|
-
def _send_heartbeat_loop(self):
|
|
48
|
-
"""心跳发送循环"""
|
|
49
|
-
current_thread = threading.current_thread()
|
|
50
|
-
thread_ident = current_thread.ident
|
|
51
|
-
SYLogger.info(
|
|
52
|
-
f"nacos:心跳循环启动 - 线程ID: {thread_ident}, "
|
|
53
|
-
f"配置间隔: {self.heartbeat_interval}秒, "
|
|
54
|
-
f"超时时间: {self.heartbeat_timeout}秒"
|
|
55
|
-
)
|
|
56
|
-
|
|
57
|
-
consecutive_fail = 0
|
|
58
|
-
|
|
59
|
-
while not self.client_base._shutdown_event.is_set():
|
|
60
|
-
current_time = time.time()
|
|
61
|
-
|
|
62
|
-
try:
|
|
63
|
-
registered_status = self.registration.registered
|
|
64
|
-
|
|
65
|
-
if not registered_status:
|
|
66
|
-
SYLogger.warning(
|
|
67
|
-
f"nacos:服务未注册,跳过心跳 - 线程ID: {thread_ident}")
|
|
68
|
-
consecutive_fail = 0
|
|
69
|
-
else:
|
|
70
|
-
success = self.send_heartbeat()
|
|
71
|
-
if success:
|
|
72
|
-
consecutive_fail = 0
|
|
73
|
-
SYLogger.info(
|
|
74
|
-
f"nacos:心跳发送成功 - 时间: {current_time:.3f}, "
|
|
75
|
-
f"间隔: {self.heartbeat_interval}秒"
|
|
76
|
-
)
|
|
77
|
-
else:
|
|
78
|
-
consecutive_fail += 1
|
|
79
|
-
SYLogger.warning(
|
|
80
|
-
f"nacos:心跳发送失败 - 连续失败: {consecutive_fail}次"
|
|
81
|
-
)
|
|
82
|
-
if consecutive_fail >= 5:
|
|
83
|
-
SYLogger.error("nacos:心跳连续失败5次,尝试重连")
|
|
84
|
-
self.client_base.reconnect_nacos_client()
|
|
85
|
-
consecutive_fail = 0
|
|
86
|
-
|
|
87
|
-
except Exception as e:
|
|
88
|
-
consecutive_fail += 1
|
|
89
|
-
SYLogger.error(
|
|
90
|
-
f"nacos:心跳异常: {str(e)}, 连续失败: {consecutive_fail}次")
|
|
91
|
-
|
|
92
|
-
self.client_base._shutdown_event.wait(self.heartbeat_interval)
|
|
93
|
-
|
|
94
|
-
SYLogger.info(f"nacos:心跳循环已停止 - 线程ID: {thread_ident}")
|
|
95
|
-
|
|
96
|
-
def send_heartbeat(self) -> bool:
|
|
97
|
-
"""发送心跳并添加超时控制"""
|
|
98
|
-
if not self.client_base.ensure_client_connected():
|
|
99
|
-
SYLogger.warning("nacos:客户端未连接,心跳发送失败")
|
|
100
|
-
return False
|
|
101
|
-
|
|
102
|
-
result_list = []
|
|
103
|
-
|
|
104
|
-
def heartbeat_task():
|
|
105
|
-
try:
|
|
106
|
-
result = self._send_heartbeat_internal()
|
|
107
|
-
result_list.append(result)
|
|
108
|
-
except Exception as e:
|
|
109
|
-
SYLogger.error(f"nacos:心跳任务执行异常: {e}")
|
|
110
|
-
result_list.append(False)
|
|
111
|
-
|
|
112
|
-
task_thread = threading.Thread(
|
|
113
|
-
target=heartbeat_task,
|
|
114
|
-
daemon=True,
|
|
115
|
-
name="NacosHeartbeatTaskThread"
|
|
116
|
-
)
|
|
117
|
-
task_thread.start()
|
|
118
|
-
task_thread.join(timeout=self.heartbeat_timeout)
|
|
119
|
-
|
|
120
|
-
if not result_list:
|
|
121
|
-
SYLogger.error(f"nacos:心跳发送超时({self.heartbeat_timeout}秒)")
|
|
122
|
-
self.client_base._client_initialized = False
|
|
123
|
-
return False
|
|
124
|
-
|
|
125
|
-
return result_list[0]
|
|
126
|
-
|
|
127
|
-
def _send_heartbeat_internal(self) -> bool:
|
|
128
|
-
"""实际的心跳发送逻辑"""
|
|
129
|
-
result = self.client_base.nacos_client.send_heartbeat(
|
|
130
|
-
service_name=self.registration.service_name,
|
|
131
|
-
ip=self.registration.real_ip,
|
|
132
|
-
port=int(self.registration.port),
|
|
133
|
-
cluster_name="DEFAULT",
|
|
134
|
-
weight=1.0,
|
|
135
|
-
metadata={
|
|
136
|
-
"version": self.registration.version} if self.registration.version else None
|
|
137
|
-
)
|
|
138
|
-
|
|
139
|
-
if result and isinstance(result, dict) and result.get('lightBeatEnabled', False):
|
|
140
|
-
SYLogger.info(f"nacos:心跳发送成功,Nacos返回: {result}")
|
|
141
|
-
return True
|
|
142
|
-
else:
|
|
143
|
-
SYLogger.warning(f"nacos:心跳发送失败,Nacos返回: {result}")
|
|
144
|
-
return False
|
|
@@ -1,157 +0,0 @@
|
|
|
1
|
-
import threading
|
|
2
|
-
from typing import List, Dict
|
|
3
|
-
from sycommon.logging.kafka_log import SYLogger
|
|
4
|
-
from sycommon.synacos.nacos_client_base import NacosClientBase
|
|
5
|
-
from sycommon.synacos.nacos_service_registration import NacosServiceRegistration
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
class NacosServiceDiscovery:
|
|
9
|
-
"""Nacos服务发现类 - 负责服务实例发现和轮询"""
|
|
10
|
-
|
|
11
|
-
def __init__(self, client_base: NacosClientBase):
|
|
12
|
-
self.client_base = client_base
|
|
13
|
-
|
|
14
|
-
# 轮询管理
|
|
15
|
-
self._round_robin_index = 0
|
|
16
|
-
self._round_robin_lock = threading.Lock()
|
|
17
|
-
|
|
18
|
-
# 连接监控配置
|
|
19
|
-
self.connection_check_interval = self.client_base.nacos_config.get(
|
|
20
|
-
'connectionCheckInterval', 30)
|
|
21
|
-
self._monitor_thread_started = False
|
|
22
|
-
self._monitor_thread_lock = threading.Lock()
|
|
23
|
-
|
|
24
|
-
def discover_services(self, service_name: str, group: str = "DEFAULT_GROUP", version: str = None) -> List[Dict]:
|
|
25
|
-
"""发现服务实例列表 (与Java格式兼容)"""
|
|
26
|
-
if not self.client_base.ensure_client_connected():
|
|
27
|
-
return []
|
|
28
|
-
|
|
29
|
-
return self.get_service_instances(service_name, group, version)
|
|
30
|
-
|
|
31
|
-
def get_service_instances(self, service_name: str, group: str = "DEFAULT_GROUP", target_version: str = None) -> List[Dict]:
|
|
32
|
-
"""
|
|
33
|
-
获取服务实例列表,并按照以下优先级规则筛选:
|
|
34
|
-
1. 相同版本号的实例
|
|
35
|
-
2. 无版本号的实例
|
|
36
|
-
3. 所有实例中轮询
|
|
37
|
-
"""
|
|
38
|
-
try:
|
|
39
|
-
namespace_id = self.client_base.nacos_config['namespaceId']
|
|
40
|
-
instances = self.client_base.nacos_client.list_naming_instance(
|
|
41
|
-
service_name,
|
|
42
|
-
namespace_id=namespace_id,
|
|
43
|
-
group_name=group,
|
|
44
|
-
healthy_only=True,
|
|
45
|
-
)
|
|
46
|
-
|
|
47
|
-
if not instances or 'hosts' not in instances:
|
|
48
|
-
SYLogger.info(f"nacos:未发现 {service_name} 的服务实例")
|
|
49
|
-
return []
|
|
50
|
-
|
|
51
|
-
all_instances = instances.get('hosts', [])
|
|
52
|
-
all_instances = [
|
|
53
|
-
instance for instance in all_instances
|
|
54
|
-
if instance.get('enabled', True)
|
|
55
|
-
]
|
|
56
|
-
SYLogger.info(
|
|
57
|
-
f"nacos:共发现 {len(all_instances)} 个 {service_name} 服务实例")
|
|
58
|
-
|
|
59
|
-
version_to_use = target_version
|
|
60
|
-
|
|
61
|
-
if version_to_use:
|
|
62
|
-
same_version_instances = [
|
|
63
|
-
instance for instance in all_instances
|
|
64
|
-
if instance.get('metadata', {}).get('version') == version_to_use
|
|
65
|
-
]
|
|
66
|
-
|
|
67
|
-
if same_version_instances:
|
|
68
|
-
SYLogger.info(
|
|
69
|
-
f"nacos:筛选出 {len(same_version_instances)} 个与当前版本({version_to_use})匹配的实例")
|
|
70
|
-
return same_version_instances
|
|
71
|
-
|
|
72
|
-
no_version_instances = [
|
|
73
|
-
instance for instance in all_instances
|
|
74
|
-
if 'version' not in instance.get('metadata', {})
|
|
75
|
-
]
|
|
76
|
-
|
|
77
|
-
if no_version_instances:
|
|
78
|
-
SYLogger.info(
|
|
79
|
-
f"nacos:未找到相同版本({version_to_use})的实例,筛选出 {len(no_version_instances)} 个无版本号的实例")
|
|
80
|
-
return no_version_instances
|
|
81
|
-
else:
|
|
82
|
-
no_version_instances = [
|
|
83
|
-
instance for instance in all_instances
|
|
84
|
-
if 'version' not in instance.get('metadata', {})
|
|
85
|
-
]
|
|
86
|
-
|
|
87
|
-
if no_version_instances:
|
|
88
|
-
# 从通用实例中轮询
|
|
89
|
-
with self._round_robin_lock:
|
|
90
|
-
selected_index = self._round_robin_index % len(
|
|
91
|
-
no_version_instances)
|
|
92
|
-
self._round_robin_index = (
|
|
93
|
-
selected_index + 1) % len(no_version_instances)
|
|
94
|
-
|
|
95
|
-
SYLogger.info(
|
|
96
|
-
f"nacos:无版本请求,从 {len(no_version_instances)} 个通用实例中选择")
|
|
97
|
-
return [no_version_instances[selected_index]]
|
|
98
|
-
|
|
99
|
-
SYLogger.info(
|
|
100
|
-
f"nacos:使用轮询方式从 {len(all_instances)} 个实例中选择")
|
|
101
|
-
|
|
102
|
-
with self._round_robin_lock:
|
|
103
|
-
selected_index = self._round_robin_index % len(all_instances)
|
|
104
|
-
self._round_robin_index = (
|
|
105
|
-
selected_index + 1) % len(all_instances)
|
|
106
|
-
|
|
107
|
-
return [all_instances[selected_index]]
|
|
108
|
-
|
|
109
|
-
except Exception as e:
|
|
110
|
-
SYLogger.error(f"nacos:服务发现失败: {service_name}: {str(e)}")
|
|
111
|
-
return []
|
|
112
|
-
|
|
113
|
-
def monitor_connection(self, registration: NacosServiceRegistration):
|
|
114
|
-
"""连接监控线程"""
|
|
115
|
-
with self._monitor_thread_lock:
|
|
116
|
-
if self.client_base._shutdown_event.is_set() or self._monitor_thread_started:
|
|
117
|
-
SYLogger.warning("nacos:监控线程已启动/已关闭,拒绝重复启动")
|
|
118
|
-
return
|
|
119
|
-
self._monitor_thread_started = True
|
|
120
|
-
|
|
121
|
-
check_interval = self.connection_check_interval
|
|
122
|
-
SYLogger.info(
|
|
123
|
-
f"nacos:连接监控线程启动 - 线程ID: {threading.current_thread().ident}")
|
|
124
|
-
|
|
125
|
-
while not self.client_base._shutdown_event.is_set():
|
|
126
|
-
try:
|
|
127
|
-
if not self.client_base.is_connected:
|
|
128
|
-
SYLogger.warning("nacos:客户端未连接,尝试重新初始化")
|
|
129
|
-
self.client_base.ensure_client_connected()
|
|
130
|
-
else:
|
|
131
|
-
current_registered = registration.check_service_registered()
|
|
132
|
-
|
|
133
|
-
if current_registered != registration.registered:
|
|
134
|
-
registration.registered = current_registered
|
|
135
|
-
if not current_registered:
|
|
136
|
-
SYLogger.warning("nacos:服务实例未注册,触发单次重新注册")
|
|
137
|
-
retry_thread = threading.Thread(
|
|
138
|
-
target=registration.register,
|
|
139
|
-
args=(True,),
|
|
140
|
-
daemon=True,
|
|
141
|
-
name="NacosSingleRetryThread"
|
|
142
|
-
)
|
|
143
|
-
retry_thread.start()
|
|
144
|
-
else:
|
|
145
|
-
SYLogger.info("nacos:服务实例已注册,触发单次验证")
|
|
146
|
-
registration.verify_registration()
|
|
147
|
-
|
|
148
|
-
self.client_base._shutdown_event.wait(check_interval)
|
|
149
|
-
|
|
150
|
-
except Exception as e:
|
|
151
|
-
SYLogger.error(f"nacos:连接监控异常: {str(e)}")
|
|
152
|
-
self.client_base._shutdown_event.wait(5)
|
|
153
|
-
|
|
154
|
-
with self._monitor_thread_lock:
|
|
155
|
-
self._monitor_thread_started = False
|
|
156
|
-
SYLogger.info(
|
|
157
|
-
f"nacos:连接监控线程退出 - 线程ID: {threading.current_thread().ident}")
|