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.
@@ -0,0 +1,138 @@
1
+ import threading
2
+ from typing import List, Dict
3
+ from sycommon.logging.kafka_log import SYLogger
4
+
5
+
6
+ class NacosServiceDiscovery:
7
+ """Nacos服务发现类 - 负责服务实例发现和轮询"""
8
+
9
+ def __init__(self, client_base):
10
+ self.client_base = client_base
11
+
12
+ # 轮询管理
13
+ self._round_robin_index = 0
14
+ self._round_robin_lock = threading.Lock()
15
+
16
+ # 连接监控配置
17
+ self.connection_check_interval = self.client_base.nacos_config.get(
18
+ 'connectionCheckInterval', 30)
19
+ self._monitor_thread_started = False
20
+ self._monitor_thread_lock = threading.Lock()
21
+
22
+ def discover_services(self, service_name: str, group: str = "DEFAULT_GROUP", version: str = None) -> List[Dict]:
23
+ """发现服务实例列表 (与Java格式兼容)"""
24
+ if not self.client_base.ensure_client_connected():
25
+ return []
26
+
27
+ return self.get_service_instances(service_name, group, version)
28
+
29
+ def get_service_instances(self, service_name: str, group: str = "DEFAULT_GROUP", target_version: str = None) -> List[Dict]:
30
+ """
31
+ 获取服务实例列表,并按照以下优先级规则筛选:
32
+ 1. 相同版本号的实例
33
+ 2. 无版本号的实例
34
+ 3. 所有实例中轮询
35
+ """
36
+ try:
37
+ namespace_id = self.client_base.nacos_config['namespaceId']
38
+ instances = self.client_base.nacos_client.list_naming_instance(
39
+ service_name,
40
+ namespace_id=namespace_id,
41
+ group_name=group,
42
+ healthy_only=True,
43
+ )
44
+
45
+ if not instances or 'hosts' not in instances:
46
+ SYLogger.info(f"nacos:未发现 {service_name} 的服务实例")
47
+ return []
48
+
49
+ all_instances = instances.get('hosts', [])
50
+ all_instances = [
51
+ instance for instance in all_instances
52
+ if instance.get('enabled', True)
53
+ ]
54
+ SYLogger.info(
55
+ f"nacos:共发现 {len(all_instances)} 个 {service_name} 服务实例")
56
+
57
+ version_to_use = target_version
58
+
59
+ if version_to_use:
60
+ same_version_instances = [
61
+ instance for instance in all_instances
62
+ if instance.get('metadata', {}).get('version') == version_to_use
63
+ ]
64
+
65
+ if same_version_instances:
66
+ SYLogger.info(
67
+ f"nacos:筛选出 {len(same_version_instances)} 个与当前版本({version_to_use})匹配的实例")
68
+ return same_version_instances
69
+
70
+ no_version_instances = [
71
+ instance for instance in all_instances
72
+ if 'version' not in instance.get('metadata', {})
73
+ ]
74
+
75
+ if no_version_instances:
76
+ SYLogger.info(
77
+ f"nacos:未找到相同版本({version_to_use})的实例,筛选出 {len(no_version_instances)} 个无版本号的实例")
78
+ return no_version_instances
79
+
80
+ SYLogger.info(
81
+ f"nacos:使用轮询方式从 {len(all_instances)} 个实例中选择")
82
+
83
+ with self._round_robin_lock:
84
+ selected_index = self._round_robin_index % len(all_instances)
85
+ self._round_robin_index = (
86
+ selected_index + 1) % len(all_instances)
87
+
88
+ return [all_instances[selected_index]]
89
+
90
+ except Exception as e:
91
+ SYLogger.error(f"nacos:服务发现失败: {service_name}: {str(e)}")
92
+ return []
93
+
94
+ def monitor_connection(self, registration):
95
+ """连接监控线程"""
96
+ with self._monitor_thread_lock:
97
+ if self.client_base._shutdown_event.is_set() or self._monitor_thread_started:
98
+ SYLogger.warning("nacos:监控线程已启动/已关闭,拒绝重复启动")
99
+ return
100
+ self._monitor_thread_started = True
101
+
102
+ check_interval = self.connection_check_interval
103
+ SYLogger.info(
104
+ f"nacos:连接监控线程启动 - 线程ID: {threading.current_thread().ident}")
105
+
106
+ while not self.client_base._shutdown_event.is_set():
107
+ try:
108
+ if not self.client_base.is_connected:
109
+ SYLogger.warning("nacos:客户端未连接,尝试重新初始化")
110
+ self.client_base.ensure_client_connected()
111
+ else:
112
+ current_registered = registration.check_service_registered()
113
+
114
+ if current_registered != registration.registered:
115
+ registration.registered = current_registered
116
+ if not current_registered:
117
+ SYLogger.warning("nacos:服务实例未注册,触发单次重新注册")
118
+ retry_thread = threading.Thread(
119
+ target=registration.register,
120
+ args=(True,),
121
+ daemon=True,
122
+ name="NacosSingleRetryThread"
123
+ )
124
+ retry_thread.start()
125
+ else:
126
+ SYLogger.info("nacos:服务实例已注册,触发单次验证")
127
+ registration.verify_registration()
128
+
129
+ self.client_base._shutdown_event.wait(check_interval)
130
+
131
+ except Exception as e:
132
+ SYLogger.error(f"nacos:连接监控异常: {str(e)}")
133
+ self.client_base._shutdown_event.wait(5)
134
+
135
+ with self._monitor_thread_lock:
136
+ self._monitor_thread_started = False
137
+ SYLogger.info(
138
+ f"nacos:连接监控线程退出 - 线程ID: {threading.current_thread().ident}")
@@ -0,0 +1,252 @@
1
+ import threading
2
+ import time
3
+ import atexit
4
+ from sycommon.logging.kafka_log import SYLogger
5
+
6
+
7
+ class NacosServiceRegistration:
8
+ """Nacos服务注册类 - 负责服务注册、注销和状态验证"""
9
+
10
+ def __init__(self, client_base, service_name: str, real_ip: str, port: int, version: str):
11
+ self.client_base = client_base
12
+ self.service_name = service_name
13
+ self.real_ip = real_ip
14
+ self.port = port
15
+ self.version = version
16
+
17
+ # 注册配置
18
+ self.register_retry_interval = self.client_base.nacos_config.get(
19
+ 'registerRetryInterval', 15)
20
+ self.long_term_retry_delay = self.client_base.nacos_config.get(
21
+ 'longTermRetryDelay', 30)
22
+ self.max_long_term_retries = self.client_base.nacos_config.get(
23
+ 'maxLongTermRetries', -1)
24
+
25
+ # 验证配置
26
+ self.registration_verify_count = self.client_base.nacos_config.get(
27
+ 'registrationVerifyCount', 1)
28
+ self.registration_verify_interval = self.client_base.nacos_config.get(
29
+ 'registrationVerifyInterval', 1)
30
+ self.registration_post_delay = self.client_base.nacos_config.get(
31
+ 'registrationPostDelay', 3)
32
+
33
+ # 状态管理
34
+ self.registered = False
35
+ self._long_term_retry_count = 0
36
+ self._verify_lock = threading.Lock()
37
+ self._last_verify_time = 0
38
+ self._atexit_registered = False
39
+
40
+ def _cleanup_stale_instance(self):
41
+ """清理可能存在的残留实例"""
42
+ if not self.client_base.is_connected:
43
+ return
44
+
45
+ try:
46
+ self.client_base.nacos_client.remove_naming_instance(
47
+ service_name=self.service_name,
48
+ ip=self.real_ip,
49
+ port=int(self.port),
50
+ cluster_name="DEFAULT"
51
+ )
52
+ SYLogger.warning(f"nacos:清理残留实例: {self.real_ip}:{self.port}")
53
+ except Exception as e:
54
+ SYLogger.error(f"nacos:清理残留实例异常: {e}")
55
+
56
+ def check_service_registered(self) -> bool:
57
+ """检查服务是否已注册(基于实例列表)"""
58
+ if not self.client_base.enable_register_nacos:
59
+ return True
60
+
61
+ if not self.client_base.ensure_client_connected():
62
+ return False
63
+
64
+ try:
65
+ namespace_id = self.client_base.nacos_config['namespaceId']
66
+ instances = self.client_base.nacos_client.list_naming_instance(
67
+ service_name=self.service_name,
68
+ namespace_id=namespace_id,
69
+ group_name="DEFAULT_GROUP",
70
+ healthy_only=True,
71
+ )
72
+
73
+ found = False
74
+ for instance in instances.get('hosts', []):
75
+ if (instance.get('ip') == self.real_ip and
76
+ instance.get('port') == int(self.port)):
77
+ SYLogger.info(f"nacos:找到已注册实例: {self.real_ip}:{self.port}")
78
+ found = True
79
+ break
80
+
81
+ if not found:
82
+ SYLogger.warning(f"nacos:未找到注册实例: {self.real_ip}:{self.port}")
83
+
84
+ self.registered = found
85
+ return found
86
+ except Exception as e:
87
+ SYLogger.error(f"nacos:检查服务注册状态失败: {e}")
88
+ return False
89
+
90
+ def verify_registration(self) -> bool:
91
+ """多次验证服务是否成功注册(加锁防止重复执行)"""
92
+ if self._verify_lock.locked():
93
+ SYLogger.warning("nacos:注册验证已在执行中,跳过重复调用")
94
+ return self.registered
95
+
96
+ with self._verify_lock:
97
+ current_time = time.time()
98
+ if current_time - self._last_verify_time < 15: # 15秒冷却
99
+ return True
100
+
101
+ success_count = 0
102
+ verify_count = self.registration_verify_count
103
+ SYLogger.info(
104
+ f"nacos:开始验证服务注册状态,共验证 {verify_count} 次,间隔 {self.registration_verify_interval} 秒")
105
+
106
+ self._last_verify_time = current_time
107
+
108
+ for i in range(verify_count):
109
+ if self.check_service_registered():
110
+ success_count += 1
111
+
112
+ if i < verify_count - 1:
113
+ self.client_base._shutdown_event.wait(
114
+ self.registration_verify_interval)
115
+ if self.client_base._shutdown_event.is_set():
116
+ SYLogger.warning("nacos:应用正在关闭,终止注册验证")
117
+ break
118
+
119
+ pass_threshold = verify_count / 2
120
+ result = success_count >= pass_threshold
121
+
122
+ if result:
123
+ SYLogger.info(
124
+ f"nacos:服务注册验证成功,{success_count}/{verify_count} 次验证通过")
125
+ else:
126
+ SYLogger.error(
127
+ f"nacos:服务注册验证失败,仅 {success_count}/{verify_count} 次验证通过")
128
+
129
+ return result
130
+
131
+ def register(self, force: bool = False) -> bool:
132
+ """注册服务到Nacos"""
133
+ if self.registered and not force and self.check_service_registered():
134
+ return True
135
+
136
+ if self.registered and not force:
137
+ self.registered = False
138
+ SYLogger.warning("nacos:本地状态显示已注册,但Nacos中未找到服务实例,准备重新注册")
139
+
140
+ metadata = {
141
+ "ignore-metrics": "true",
142
+ }
143
+ if self.version:
144
+ metadata["version"] = self.version
145
+
146
+ for attempt in range(self.client_base.max_retries):
147
+ if not self.client_base.ensure_client_connected():
148
+ return False
149
+
150
+ try:
151
+ self.client_base.nacos_client.add_naming_instance(
152
+ service_name=self.service_name,
153
+ ip=self.real_ip,
154
+ port=int(self.port),
155
+ metadata=metadata,
156
+ cluster_name="DEFAULT",
157
+ healthy=True,
158
+ ephemeral=True,
159
+ heartbeat_interval=15 # 心跳间隔默认15秒
160
+ )
161
+ SYLogger.info(
162
+ f"nacos:服务 {self.service_name} 注册请求已发送: {self.real_ip}:{self.port}")
163
+
164
+ if not self._atexit_registered:
165
+ atexit.register(self.deregister_service)
166
+ self._atexit_registered = True
167
+
168
+ return True
169
+ except Exception as e:
170
+ if "signal only works in main thread" in str(e):
171
+ return True
172
+ elif attempt < self.client_base.max_retries - 1:
173
+ SYLogger.warning(
174
+ f"nacos:服务注册失败 (尝试 {attempt+1}/{self.client_base.max_retries}): {e}")
175
+ time.sleep(self.client_base.retry_delay)
176
+ else:
177
+ SYLogger.error(f"nacos:服务注册失败,已达到最大重试次数: {e}")
178
+ return False
179
+
180
+ def register_with_retry(self) -> bool:
181
+ """带重试机制的服务注册(基于实例列表检查)"""
182
+ retry_count = 0
183
+ last_error = None
184
+ self.registered = False
185
+
186
+ while (not self.registered) and (self.max_long_term_retries < 0 or retry_count < self.max_long_term_retries):
187
+ if self.registered:
188
+ return True
189
+
190
+ try:
191
+ register_success = self.register(force=True)
192
+ if not register_success:
193
+ raise RuntimeError("nacos:服务注册请求失败")
194
+
195
+ SYLogger.info(
196
+ f"nacos:服务注册请求已发送,延迟 {self.registration_post_delay} 秒后开始验证")
197
+ time.sleep(self.registration_post_delay)
198
+
199
+ registered = self.verify_registration()
200
+ self.registered = registered
201
+
202
+ if self.registered:
203
+ self.client_base._client_initialized = True
204
+ self.client_base._shutdown_event.set()
205
+ self.client_base._shutdown_event.clear()
206
+ self._long_term_retry_count = 0
207
+
208
+ SYLogger.info(
209
+ f"nacos:服务注册成功并通过验证: {self.service_name}")
210
+ return True
211
+ else:
212
+ raise RuntimeError("nacos:服务注册验证失败")
213
+
214
+ except Exception as e:
215
+ last_error = str(e)
216
+ retry_count += 1
217
+ delay = min(self.register_retry_interval,
218
+ self.client_base.max_retry_delay)
219
+
220
+ SYLogger.warning(
221
+ f"nacos:服务注册尝试 {retry_count} 失败: {last_error},{delay}秒后重试")
222
+ time.sleep(delay)
223
+
224
+ if self.registered:
225
+ return True
226
+
227
+ if last_error:
228
+ SYLogger.error(f"nacos:服务注册失败,最终错误: {last_error}")
229
+ else:
230
+ SYLogger.error(f"nacos:服务注册失败,已达到最大重试次数: {self.service_name}")
231
+
232
+ return False
233
+
234
+ def deregister_service(self):
235
+ """从Nacos注销服务"""
236
+ if not self.registered or not self.client_base.is_connected:
237
+ return
238
+
239
+ SYLogger.info("nacos:正在注销服务...")
240
+ try:
241
+ self.client_base.nacos_client.remove_naming_instance(
242
+ service_name=self.service_name,
243
+ ip=self.real_ip,
244
+ port=int(self.port),
245
+ cluster_name="DEFAULT"
246
+ )
247
+ self.registered = False
248
+ SYLogger.info(f"nacos:服务 {self.service_name} 已注销")
249
+ except Exception as e:
250
+ SYLogger.error(f"nacos:注销服务时发生错误: {e}")
251
+ finally:
252
+ self.client_base._shutdown_event.set()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sycommon-python-lib
3
- Version: 0.1.56b7
3
+ Version: 0.1.56b8
4
4
  Summary: Add your description here
5
5
  Requires-Python: >=3.11
6
6
  Description-Content-Type: text/markdown
@@ -1,7 +1,7 @@
1
1
  command/cli.py,sha256=bP2LCLkRvfETIwWkVD70q5xFxMI4D3BpH09Ws1f-ENc,5849
2
2
  sycommon/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
3
  sycommon/services.py,sha256=vcO2vbe2U1CA4ykLdH1rnxgqUIouukE-wTRsjRl2kBI,11683
4
- sycommon/config/Config.py,sha256=-LzOgnpA0GKgNexG-tmpLspkJipjtq2GcToaZbyGncg,3854
4
+ sycommon/config/Config.py,sha256=Q-HGp-10uTTCOAwnxwT4g-hrOWGDWl7bFPYZZHOmiOo,3742
5
5
  sycommon/config/DatabaseConfig.py,sha256=ILiUuYT9_xJZE2W-RYuC3JCt_YLKc1sbH13-MHIOPhg,804
6
6
  sycommon/config/EmbeddingConfig.py,sha256=gPKwiDYbeu1GpdIZXMmgqM7JqBIzCXi0yYuGRLZooMI,362
7
7
  sycommon/config/LLMConfig.py,sha256=yU-aIqePIeF6msfRVEtGq7SXZVDfHyTi6JduKjhMO_4,371
@@ -49,7 +49,12 @@ sycommon/notice/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
49
49
  sycommon/notice/uvicorn_monitor.py,sha256=VryQYcAtjijJuGDBimbVurgwxlsLaLtkNnABPDY5Tao,7332
50
50
  sycommon/rabbitmq/rabbitmq_client.py,sha256=jClUm9Ao9vZ2IZg7IXIEaDbYYnV8qtmtm77vdmwpKE4,22599
51
51
  sycommon/rabbitmq/rabbitmq_pool.py,sha256=5ruFVViSCKA7ToZmR2dZIkP0zT0ZcfsnkSGbrdkg0Tk,16141
52
- sycommon/rabbitmq/rabbitmq_service.py,sha256=RkEWzCu2DkjV6G-hZ8FQTdewvkBiPAZezrO7GzKBkiI,39046
52
+ sycommon/rabbitmq/rabbitmq_service.py,sha256=XSHo9HuIJ_lq-vizRh4xJVdZr_2zLqeLhot09qb0euA,2025
53
+ sycommon/rabbitmq/rabbitmq_service_client_manager.py,sha256=VL6hGaU5VXldLn5bmn3N6Lu3tBDD0zYB6aWurKJpAFM,8270
54
+ sycommon/rabbitmq/rabbitmq_service_connection_monitor.py,sha256=uvoMuJDzJ9i63uVRq1NKFV10CvkbGnTMyEoq2rgjQx8,3013
55
+ sycommon/rabbitmq/rabbitmq_service_consumer_manager.py,sha256=qvq6dB30DkJrpk2OQ7PsWPXbp-7ILiMNt0sjZbfOzUs,11449
56
+ sycommon/rabbitmq/rabbitmq_service_core.py,sha256=_9gqc7BOhrzfeYS557yIOfyCAraAKh-3ClMpKHn9ufY,4753
57
+ sycommon/rabbitmq/rabbitmq_service_producer_manager.py,sha256=FKljvWhxuVq3QwBf-Ny7n5JvO3zyJ2B4K1SGb6fG2e0,9960
53
58
  sycommon/sentry/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
54
59
  sycommon/sentry/sy_sentry.py,sha256=S2Np_6WmWkI9X76Q67RWZthhCz02tKCfvdhKI57587w,1373
55
60
  sycommon/sse/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -60,15 +65,20 @@ sycommon/synacos/example.py,sha256=61XL03tU8WTNOo3FUduf93F2fAwah1S0lbH1ufhRhRk,5
60
65
  sycommon/synacos/example2.py,sha256=adUaru3Hy482KrOA17DfaC4nwvLj8etIDS_KrWLWmCU,4811
61
66
  sycommon/synacos/feign.py,sha256=frB3D5LeFDtT3pJLFOwFzEOrNAJKeQNGk-BzUg9T3WM,8295
62
67
  sycommon/synacos/feign_client.py,sha256=ExO7Pd5B3eFKDjXqBRc260K1jkI49IYguLwJJaD2R-o,16166
63
- sycommon/synacos/nacos_service.py,sha256=8RFvOpeKFqYDj1kzzdjZqBBUZMf_VcFeIyeO9uPf_AU,37194
68
+ sycommon/synacos/nacos_client_base.py,sha256=l5jpall6nEt0Hy07Wk-PVU0VN0BmD_Mmtldmtyvvksg,4526
69
+ sycommon/synacos/nacos_config_manager.py,sha256=IzSOSocJJrLnvVUKOXE2bq0ZDm9Na9esZLomZzOFtGo,4319
70
+ sycommon/synacos/nacos_heartbeat_manager.py,sha256=_87KaKRA7kkq39rOc4ViYd20H-Y7iu4jMrq_n-ul8wg,5381
71
+ sycommon/synacos/nacos_service.py,sha256=EPDNBAPwPP4EPIEIjuvD9_CmLRNNmhd_heCpxJD6wbM,6068
72
+ sycommon/synacos/nacos_service_discovery.py,sha256=wTkUgauO8aFHKotnm6mFHlY2_yXHfltlPlBzg2XBOGE,5837
73
+ sycommon/synacos/nacos_service_registration.py,sha256=TwhBZsQszkaSDo_zVQmQxkFlC6K3YHBK8hXpChZ9if8,9872
64
74
  sycommon/synacos/param.py,sha256=KcfSkxnXOa0TGmCjY8hdzU9pzUsA8-4PeyBKWI2-568,1765
65
75
  sycommon/tools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
66
76
  sycommon/tools/docs.py,sha256=OPj2ETheuWjXLyaXtaZPbwmJKfJaYXV5s4XMVAUNrms,1607
67
77
  sycommon/tools/merge_headers.py,sha256=HV_i52Q-9se3SP8qh7ZGYl8bP7Fxtal4CGVkyMwEdM8,4373
68
78
  sycommon/tools/snowflake.py,sha256=lVEe5mNCOgz5OqGQpf5_nXaGnRJlI2STX2s-ppTtanA,11947
69
79
  sycommon/tools/timing.py,sha256=OiiE7P07lRoMzX9kzb8sZU9cDb0zNnqIlY5pWqHcnkY,2064
70
- sycommon_python_lib-0.1.56b7.dist-info/METADATA,sha256=LNeEx8_l2ZYTYjb3NE5Uh8Epgrywk-O_p4zt6_JNy-k,7269
71
- sycommon_python_lib-0.1.56b7.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
72
- sycommon_python_lib-0.1.56b7.dist-info/entry_points.txt,sha256=q_h2nbvhhmdnsOUZEIwpuoDjaNfBF9XqppDEmQn9d_A,46
73
- sycommon_python_lib-0.1.56b7.dist-info/top_level.txt,sha256=98CJ-cyM2WIKxLz-Pf0AitWLhJyrfXvyY8slwjTXNuc,17
74
- sycommon_python_lib-0.1.56b7.dist-info/RECORD,,
80
+ sycommon_python_lib-0.1.56b8.dist-info/METADATA,sha256=orC9Ba1jsx2gISka8fQbouH2xI2fc86ZlZm0bN-11MI,7269
81
+ sycommon_python_lib-0.1.56b8.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
82
+ sycommon_python_lib-0.1.56b8.dist-info/entry_points.txt,sha256=q_h2nbvhhmdnsOUZEIwpuoDjaNfBF9XqppDEmQn9d_A,46
83
+ sycommon_python_lib-0.1.56b8.dist-info/top_level.txt,sha256=98CJ-cyM2WIKxLz-Pf0AitWLhJyrfXvyY8slwjTXNuc,17
84
+ sycommon_python_lib-0.1.56b8.dist-info/RECORD,,