sycommon-python-lib 0.1.56b5__py3-none-any.whl → 0.1.57b4__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 +24 -3
- sycommon/config/LangfuseConfig.py +15 -0
- sycommon/config/SentryConfig.py +13 -0
- sycommon/llm/embedding.py +269 -50
- sycommon/llm/get_llm.py +9 -218
- sycommon/llm/struct_token.py +192 -0
- sycommon/llm/sy_langfuse.py +103 -0
- sycommon/llm/usage_token.py +117 -0
- sycommon/logging/kafka_log.py +187 -433
- sycommon/middleware/exception.py +10 -16
- sycommon/middleware/timeout.py +2 -1
- sycommon/middleware/traceid.py +81 -76
- sycommon/notice/uvicorn_monitor.py +32 -27
- sycommon/rabbitmq/rabbitmq_client.py +247 -242
- sycommon/rabbitmq/rabbitmq_pool.py +201 -123
- sycommon/rabbitmq/rabbitmq_service.py +25 -843
- sycommon/rabbitmq/rabbitmq_service_client_manager.py +211 -0
- sycommon/rabbitmq/rabbitmq_service_connection_monitor.py +73 -0
- sycommon/rabbitmq/rabbitmq_service_consumer_manager.py +285 -0
- sycommon/rabbitmq/rabbitmq_service_core.py +117 -0
- sycommon/rabbitmq/rabbitmq_service_producer_manager.py +238 -0
- sycommon/sentry/__init__.py +0 -0
- sycommon/sentry/sy_sentry.py +35 -0
- sycommon/services.py +122 -96
- sycommon/synacos/nacos_client_base.py +121 -0
- sycommon/synacos/nacos_config_manager.py +107 -0
- sycommon/synacos/nacos_heartbeat_manager.py +144 -0
- sycommon/synacos/nacos_service.py +63 -783
- sycommon/synacos/nacos_service_discovery.py +157 -0
- sycommon/synacos/nacos_service_registration.py +270 -0
- sycommon/tools/env.py +62 -0
- sycommon/tools/merge_headers.py +20 -0
- sycommon/tools/snowflake.py +101 -153
- {sycommon_python_lib-0.1.56b5.dist-info → sycommon_python_lib-0.1.57b4.dist-info}/METADATA +10 -8
- {sycommon_python_lib-0.1.56b5.dist-info → sycommon_python_lib-0.1.57b4.dist-info}/RECORD +38 -20
- {sycommon_python_lib-0.1.56b5.dist-info → sycommon_python_lib-0.1.57b4.dist-info}/WHEEL +0 -0
- {sycommon_python_lib-0.1.56b5.dist-info → sycommon_python_lib-0.1.57b4.dist-info}/entry_points.txt +0 -0
- {sycommon_python_lib-0.1.56b5.dist-info → sycommon_python_lib-0.1.57b4.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,157 @@
|
|
|
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}")
|
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
import threading
|
|
2
|
+
import time
|
|
3
|
+
import atexit
|
|
4
|
+
from sycommon.logging.kafka_log import SYLogger
|
|
5
|
+
from sycommon.synacos.nacos_client_base import NacosClientBase
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class NacosServiceRegistration:
|
|
9
|
+
"""Nacos服务注册类 - 负责服务注册、注销和状态验证"""
|
|
10
|
+
|
|
11
|
+
def __init__(self, client_base: NacosClientBase, service_name: str, real_ip: str, port: int, version: str):
|
|
12
|
+
self.client_base = client_base
|
|
13
|
+
self.service_name = service_name
|
|
14
|
+
self.real_ip = real_ip
|
|
15
|
+
self.port = port
|
|
16
|
+
self.version = version
|
|
17
|
+
|
|
18
|
+
# 注册配置
|
|
19
|
+
self.register_retry_interval = self.client_base.nacos_config.get(
|
|
20
|
+
'registerRetryInterval', 15)
|
|
21
|
+
self.long_term_retry_delay = self.client_base.nacos_config.get(
|
|
22
|
+
'longTermRetryDelay', 30)
|
|
23
|
+
self.max_long_term_retries = self.client_base.nacos_config.get(
|
|
24
|
+
'maxLongTermRetries', -1)
|
|
25
|
+
|
|
26
|
+
# 验证配置
|
|
27
|
+
self.registration_verify_count = self.client_base.nacos_config.get(
|
|
28
|
+
'registrationVerifyCount', 1)
|
|
29
|
+
self.registration_verify_interval = self.client_base.nacos_config.get(
|
|
30
|
+
'registrationVerifyInterval', 1)
|
|
31
|
+
self.registration_post_delay = self.client_base.nacos_config.get(
|
|
32
|
+
'registrationPostDelay', 3)
|
|
33
|
+
|
|
34
|
+
# 状态管理
|
|
35
|
+
self.registered = False
|
|
36
|
+
self._long_term_retry_count = 0
|
|
37
|
+
self._verify_lock = threading.Lock()
|
|
38
|
+
self._last_verify_time = 0
|
|
39
|
+
self._atexit_registered = False
|
|
40
|
+
|
|
41
|
+
def _cleanup_stale_instance(self):
|
|
42
|
+
"""清理可能存在的残留实例"""
|
|
43
|
+
if not self.client_base.is_connected:
|
|
44
|
+
return
|
|
45
|
+
|
|
46
|
+
try:
|
|
47
|
+
self.client_base.nacos_client.remove_naming_instance(
|
|
48
|
+
service_name=self.service_name,
|
|
49
|
+
ip=self.real_ip,
|
|
50
|
+
port=int(self.port),
|
|
51
|
+
cluster_name="DEFAULT"
|
|
52
|
+
)
|
|
53
|
+
SYLogger.warning(f"nacos:清理残留实例: {self.real_ip}:{self.port}")
|
|
54
|
+
except Exception as e:
|
|
55
|
+
SYLogger.error(f"nacos:清理残留实例异常: {e}")
|
|
56
|
+
|
|
57
|
+
def check_service_registered(self) -> bool:
|
|
58
|
+
"""检查服务是否已注册(基于实例列表)"""
|
|
59
|
+
if not self.client_base.enable_register_nacos:
|
|
60
|
+
return True
|
|
61
|
+
|
|
62
|
+
if not self.client_base.ensure_client_connected():
|
|
63
|
+
return False
|
|
64
|
+
|
|
65
|
+
try:
|
|
66
|
+
namespace_id = self.client_base.nacos_config['namespaceId']
|
|
67
|
+
instances = self.client_base.nacos_client.list_naming_instance(
|
|
68
|
+
service_name=self.service_name,
|
|
69
|
+
namespace_id=namespace_id,
|
|
70
|
+
group_name="DEFAULT_GROUP",
|
|
71
|
+
healthy_only=True,
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
found = False
|
|
75
|
+
for instance in instances.get('hosts', []):
|
|
76
|
+
if (instance.get('ip') == self.real_ip and
|
|
77
|
+
instance.get('port') == int(self.port)):
|
|
78
|
+
SYLogger.info(f"nacos:找到已注册实例: {self.real_ip}:{self.port}")
|
|
79
|
+
found = True
|
|
80
|
+
break
|
|
81
|
+
|
|
82
|
+
if not found:
|
|
83
|
+
SYLogger.warning(f"nacos:未找到注册实例: {self.real_ip}:{self.port}")
|
|
84
|
+
|
|
85
|
+
self.registered = found
|
|
86
|
+
return found
|
|
87
|
+
except Exception as e:
|
|
88
|
+
SYLogger.error(f"nacos:检查服务注册状态失败: {e}")
|
|
89
|
+
return False
|
|
90
|
+
|
|
91
|
+
def verify_registration(self) -> bool:
|
|
92
|
+
"""多次验证服务是否成功注册(加锁防止重复执行)"""
|
|
93
|
+
if self._verify_lock.locked():
|
|
94
|
+
SYLogger.warning("nacos:注册验证已在执行中,跳过重复调用")
|
|
95
|
+
return self.registered
|
|
96
|
+
|
|
97
|
+
with self._verify_lock:
|
|
98
|
+
current_time = time.time()
|
|
99
|
+
if current_time - self._last_verify_time < 15: # 15秒冷却
|
|
100
|
+
return True
|
|
101
|
+
|
|
102
|
+
success_count = 0
|
|
103
|
+
verify_count = self.registration_verify_count
|
|
104
|
+
SYLogger.info(
|
|
105
|
+
f"nacos:开始验证服务注册状态,共验证 {verify_count} 次,间隔 {self.registration_verify_interval} 秒")
|
|
106
|
+
|
|
107
|
+
self._last_verify_time = current_time
|
|
108
|
+
|
|
109
|
+
for i in range(verify_count):
|
|
110
|
+
if self.check_service_registered():
|
|
111
|
+
success_count += 1
|
|
112
|
+
|
|
113
|
+
if i < verify_count - 1:
|
|
114
|
+
self.client_base._shutdown_event.wait(
|
|
115
|
+
self.registration_verify_interval)
|
|
116
|
+
if self.client_base._shutdown_event.is_set():
|
|
117
|
+
SYLogger.warning("nacos:应用正在关闭,终止注册验证")
|
|
118
|
+
break
|
|
119
|
+
|
|
120
|
+
pass_threshold = verify_count / 2
|
|
121
|
+
result = success_count >= pass_threshold
|
|
122
|
+
|
|
123
|
+
if result:
|
|
124
|
+
SYLogger.info(
|
|
125
|
+
f"nacos:服务注册验证成功,{success_count}/{verify_count} 次验证通过")
|
|
126
|
+
else:
|
|
127
|
+
SYLogger.error(
|
|
128
|
+
f"nacos:服务注册验证失败,仅 {success_count}/{verify_count} 次验证通过")
|
|
129
|
+
|
|
130
|
+
return result
|
|
131
|
+
|
|
132
|
+
def register(self, force: bool = False) -> bool:
|
|
133
|
+
"""注册服务到Nacos"""
|
|
134
|
+
if self.registered and not force and self.check_service_registered():
|
|
135
|
+
return True
|
|
136
|
+
|
|
137
|
+
if self.registered and not force:
|
|
138
|
+
self.registered = False
|
|
139
|
+
SYLogger.warning("nacos:本地状态显示已注册,但Nacos中未找到服务实例,准备重新注册")
|
|
140
|
+
|
|
141
|
+
metadata = {
|
|
142
|
+
"ignore-metrics": "true",
|
|
143
|
+
}
|
|
144
|
+
if self.version:
|
|
145
|
+
metadata["version"] = self.version
|
|
146
|
+
|
|
147
|
+
for attempt in range(self.client_base.max_retries):
|
|
148
|
+
if not self.client_base.ensure_client_connected():
|
|
149
|
+
return False
|
|
150
|
+
|
|
151
|
+
try:
|
|
152
|
+
self.client_base.nacos_client.add_naming_instance(
|
|
153
|
+
service_name=self.service_name,
|
|
154
|
+
ip=self.real_ip,
|
|
155
|
+
port=int(self.port),
|
|
156
|
+
metadata=metadata,
|
|
157
|
+
cluster_name="DEFAULT",
|
|
158
|
+
healthy=True,
|
|
159
|
+
ephemeral=True,
|
|
160
|
+
heartbeat_interval=15 # 心跳间隔默认15秒
|
|
161
|
+
)
|
|
162
|
+
SYLogger.info(
|
|
163
|
+
f"nacos:服务 {self.service_name} 注册请求已发送: {self.real_ip}:{self.port}")
|
|
164
|
+
|
|
165
|
+
if not self._atexit_registered:
|
|
166
|
+
atexit.register(self.deregister_service)
|
|
167
|
+
self._atexit_registered = True
|
|
168
|
+
|
|
169
|
+
return True
|
|
170
|
+
except Exception as e:
|
|
171
|
+
if "signal only works in main thread" in str(e):
|
|
172
|
+
return True
|
|
173
|
+
elif attempt < self.client_base.max_retries - 1:
|
|
174
|
+
SYLogger.warning(
|
|
175
|
+
f"nacos:服务注册失败 (尝试 {attempt+1}/{self.client_base.max_retries}): {e}")
|
|
176
|
+
time.sleep(self.client_base.retry_delay)
|
|
177
|
+
else:
|
|
178
|
+
SYLogger.error(f"nacos:服务注册失败,已达到最大重试次数: {e}")
|
|
179
|
+
return False
|
|
180
|
+
|
|
181
|
+
def register_with_retry(self) -> bool:
|
|
182
|
+
"""带重试机制的服务注册(基于实例列表检查)"""
|
|
183
|
+
retry_count = 0
|
|
184
|
+
last_error = None
|
|
185
|
+
self.registered = False
|
|
186
|
+
# 首次注册尝试标记
|
|
187
|
+
first_attempt = True
|
|
188
|
+
|
|
189
|
+
while (not self.registered) and (self.max_long_term_retries < 0 or retry_count < self.max_long_term_retries):
|
|
190
|
+
if self.registered:
|
|
191
|
+
return True
|
|
192
|
+
|
|
193
|
+
try:
|
|
194
|
+
register_success = self.register(force=True)
|
|
195
|
+
if not register_success:
|
|
196
|
+
raise RuntimeError("nacos:服务注册请求失败")
|
|
197
|
+
|
|
198
|
+
SYLogger.info(
|
|
199
|
+
f"nacos:服务注册请求已发送,{'首次启动信任注册,跳过阻塞验证' if first_attempt else f'延迟 {self.registration_post_delay} 秒后开始验证'}")
|
|
200
|
+
|
|
201
|
+
# 核心逻辑:首次注册跳过阻塞验证,非首次按原逻辑
|
|
202
|
+
if first_attempt:
|
|
203
|
+
# 首次注册:直接标记成功,不阻塞
|
|
204
|
+
self.registered = True
|
|
205
|
+
self.client_base._client_initialized = True
|
|
206
|
+
self.client_base._shutdown_event.set()
|
|
207
|
+
self.client_base._shutdown_event.clear()
|
|
208
|
+
self._long_term_retry_count = 0
|
|
209
|
+
|
|
210
|
+
SYLogger.info(f"nacos:首次启动信任注册成功: {self.service_name}")
|
|
211
|
+
first_attempt = False # 标记为非首次
|
|
212
|
+
return True
|
|
213
|
+
else:
|
|
214
|
+
# 非首次/重试:保留原有阻塞验证逻辑
|
|
215
|
+
time.sleep(self.registration_post_delay)
|
|
216
|
+
registered = self.verify_registration()
|
|
217
|
+
self.registered = registered
|
|
218
|
+
|
|
219
|
+
if self.registered:
|
|
220
|
+
self.client_base._client_initialized = True
|
|
221
|
+
self.client_base._shutdown_event.set()
|
|
222
|
+
self.client_base._shutdown_event.clear()
|
|
223
|
+
self._long_term_retry_count = 0
|
|
224
|
+
|
|
225
|
+
SYLogger.info(
|
|
226
|
+
f"nacos:服务注册成功并通过验证: {self.service_name}")
|
|
227
|
+
return True
|
|
228
|
+
else:
|
|
229
|
+
raise RuntimeError("nacos:服务注册验证失败")
|
|
230
|
+
|
|
231
|
+
except Exception as e:
|
|
232
|
+
last_error = str(e)
|
|
233
|
+
retry_count += 1
|
|
234
|
+
first_attempt = False # 失败后标记为非首次
|
|
235
|
+
delay = min(self.register_retry_interval,
|
|
236
|
+
self.client_base.max_retry_delay)
|
|
237
|
+
|
|
238
|
+
SYLogger.warning(
|
|
239
|
+
f"nacos:服务注册尝试 {retry_count} 失败: {last_error},{delay}秒后重试")
|
|
240
|
+
time.sleep(delay)
|
|
241
|
+
|
|
242
|
+
if self.registered:
|
|
243
|
+
return True
|
|
244
|
+
|
|
245
|
+
if last_error:
|
|
246
|
+
SYLogger.error(f"nacos:服务注册失败,最终错误: {last_error}")
|
|
247
|
+
else:
|
|
248
|
+
SYLogger.error(f"nacos:服务注册失败,已达到最大重试次数: {self.service_name}")
|
|
249
|
+
|
|
250
|
+
return False
|
|
251
|
+
|
|
252
|
+
def deregister_service(self):
|
|
253
|
+
"""从Nacos注销服务"""
|
|
254
|
+
if not self.registered or not self.client_base.is_connected:
|
|
255
|
+
return
|
|
256
|
+
|
|
257
|
+
SYLogger.info("nacos:正在注销服务...")
|
|
258
|
+
try:
|
|
259
|
+
self.client_base.nacos_client.remove_naming_instance(
|
|
260
|
+
service_name=self.service_name,
|
|
261
|
+
ip=self.real_ip,
|
|
262
|
+
port=int(self.port),
|
|
263
|
+
cluster_name="DEFAULT"
|
|
264
|
+
)
|
|
265
|
+
self.registered = False
|
|
266
|
+
SYLogger.info(f"nacos:服务 {self.service_name} 已注销")
|
|
267
|
+
except Exception as e:
|
|
268
|
+
SYLogger.error(f"nacos:注销服务时发生错误: {e}")
|
|
269
|
+
finally:
|
|
270
|
+
self.client_base._shutdown_event.set()
|
sycommon/tools/env.py
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import os
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def _normalize_env_key(key: str) -> str:
|
|
5
|
+
"""
|
|
6
|
+
环境变量名标准化:
|
|
7
|
+
1. 转小写
|
|
8
|
+
2. 中划线(-)和下划线(_)统一替换为下划线(_)
|
|
9
|
+
:param key: 原始环境变量名
|
|
10
|
+
:return: 标准化后的key
|
|
11
|
+
"""
|
|
12
|
+
return key.lower().replace('-', '_')
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def check_env_flag(target_keys: list, default: str = 'false') -> bool:
|
|
16
|
+
"""
|
|
17
|
+
检查环境变量是否为"true"(自动兼容:大小写、中划线/下划线)
|
|
18
|
+
:param target_keys: 目标变量名列表(如 ['REGISTER-NACOS'],无需传双key)
|
|
19
|
+
:param default: 默认值(未找到变量时使用)
|
|
20
|
+
:return: 布尔值
|
|
21
|
+
"""
|
|
22
|
+
# 1. 标准化目标key(小写+统一下划线)
|
|
23
|
+
target_keys_normalized = [_normalize_env_key(k) for k in target_keys]
|
|
24
|
+
|
|
25
|
+
# 2. 遍历所有环境变量,标准化后匹配
|
|
26
|
+
for env_key, env_val in os.environ.items():
|
|
27
|
+
env_key_normalized = _normalize_env_key(env_key)
|
|
28
|
+
if env_key_normalized in target_keys_normalized:
|
|
29
|
+
# 3. 值去空格 + 转小写 判断
|
|
30
|
+
return env_val.strip().lower() == 'true'
|
|
31
|
+
|
|
32
|
+
# 4. 未找到变量时,判断默认值
|
|
33
|
+
return default.strip().lower() == 'true'
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def get_env_var(key: str, default='', case_insensitive: bool = True) -> str:
|
|
37
|
+
"""
|
|
38
|
+
获取环境变量值(自动兼容:大小写、中划线/下划线)
|
|
39
|
+
:param key: 目标环境变量名(如 'REGISTER-NACOS'/'version')
|
|
40
|
+
:param default: 无匹配时的默认值,默认空字符串
|
|
41
|
+
:param case_insensitive: 是否忽略变量名大小写(默认True,建议保持)
|
|
42
|
+
:return: 匹配到的环境变量值 / 默认值
|
|
43
|
+
"""
|
|
44
|
+
if case_insensitive:
|
|
45
|
+
# 标准化目标key(小写+统一下划线)
|
|
46
|
+
target_key_normalized = _normalize_env_key(key)
|
|
47
|
+
|
|
48
|
+
# 遍历环境变量,标准化后匹配
|
|
49
|
+
for env_key, env_val in os.environ.items():
|
|
50
|
+
env_key_normalized = _normalize_env_key(env_key)
|
|
51
|
+
if env_key_normalized == target_key_normalized:
|
|
52
|
+
return env_val
|
|
53
|
+
return default
|
|
54
|
+
else:
|
|
55
|
+
# 不忽略大小写时,仅自动兼容中划线/下划线
|
|
56
|
+
target_key_1 = key # 原始key
|
|
57
|
+
target_key_2 = key.replace(
|
|
58
|
+
'-', '_') if '-' in key else key.replace('_', '-') # 替换格式的key
|
|
59
|
+
val = os.getenv(target_key_1)
|
|
60
|
+
if val is not None:
|
|
61
|
+
return val
|
|
62
|
+
return os.getenv(target_key_2, default)
|
sycommon/tools/merge_headers.py
CHANGED
|
@@ -95,3 +95,23 @@ def merge_headers(
|
|
|
95
95
|
processed_headers[key_lower] = value
|
|
96
96
|
|
|
97
97
|
return processed_headers
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def get_header_value(headers: list, target_key: str, default=None):
|
|
101
|
+
"""
|
|
102
|
+
从列表中查找指定 header 的值
|
|
103
|
+
|
|
104
|
+
Args:
|
|
105
|
+
headers: header 列表,例如 [('Content-Type', 'application/json'), ...]
|
|
106
|
+
target_key: 要查找的 key
|
|
107
|
+
default: 如果没找到返回的默认值
|
|
108
|
+
"""
|
|
109
|
+
if not headers:
|
|
110
|
+
return default
|
|
111
|
+
|
|
112
|
+
for item in headers:
|
|
113
|
+
# 兼容 list 和 tuple,确保长度为2
|
|
114
|
+
if isinstance(item, (list, tuple)) and len(item) == 2 and item[0] == target_key:
|
|
115
|
+
return item[1]
|
|
116
|
+
|
|
117
|
+
return default
|