fix: list nacos registrations across visible namespaces

This commit is contained in:
ZuoZuo 2026-04-22 01:36:05 +08:00
parent 52182a13ad
commit 17117b57b3
2 changed files with 105 additions and 83 deletions

View File

@ -233,7 +233,7 @@ def list_services(namespace_id: str) -> list[str]:
{
"pageNo": str(page_no),
"pageSize": str(NACOS_PAGE_SIZE),
"namespaceId": namespace_id,
"namespaceId": namespace_id or None,
},
)
@ -269,7 +269,7 @@ def list_instances(namespace_id: str, service_name: str, group_name: str) -> lis
{
"serviceName": service_name,
"groupName": group_name,
"namespaceId": namespace_id,
"namespaceId": namespace_id or None,
"healthyOnly": "false",
},
)
@ -300,8 +300,35 @@ def build_nacos_payload() -> dict[str, Any]:
namespaces = list_namespaces()
# 解析目标 namespace。
namespace_id, namespace_name = resolve_namespace(namespaces)
# 拉取目标 namespace 下所有服务。
raw_services = list_services(namespace_id)
# 先把命名空间归一化。
normalized_namespaces = [
{
"namespaceId": str(item.get("namespace") or item.get("namespaceId") or "").strip(),
"name": str(item.get("namespaceShowName") or item.get("namespace") or "").strip(),
"configCount": int(item.get("configCount") or 0),
"type": int(item.get("type") or 0),
"visible": True,
}
for item in namespaces
]
# 建立当前可见 namespace id 集合。
visible_ids = {item["namespaceId"] for item in normalized_namespaces}
# 建立当前可见 namespace 名称集合。
visible_names = {item["name"] for item in normalized_namespaces}
# 如果配置里的 namespace 不在可见列表里,就补一个兜底项。
if (namespace_id and namespace_id not in visible_ids) or (namespace_name and namespace_name not in visible_names):
normalized_namespaces.append(
{
"namespaceId": namespace_id,
"name": namespace_name,
"configCount": 0,
"type": 0,
"visible": False,
}
)
# 归一化后的服务列表。
services: list[dict[str, Any]] = []
@ -314,92 +341,88 @@ def build_nacos_payload() -> dict[str, Any]:
# 统计全健康服务数量。
healthy_service_total = 0
# 逐个服务拉实例详情。
for raw_name in raw_services:
# 解析 group 和真正的 serviceName。
group_name, service_name = split_grouped_service_name(raw_name)
# 拉取当前服务实例。
instance_items = list_instances(namespace_id, service_name, group_name)
# 归一化实例结构。
normalized_instances: list[dict[str, Any]] = []
# 逐个 namespace 读取服务和实例。
for namespace in normalized_namespaces:
# 当前 namespace 的服务列表。
raw_services = list_services(namespace["namespaceId"])
# 当前服务健康实例数。
healthy_total = 0
# 当前服务启用实例数。
enabled_total = 0
# 逐个服务拉实例详情。
for raw_name in raw_services:
# 解析 group 和真正的 serviceName。
group_name, service_name = split_grouped_service_name(raw_name)
# 拉取当前服务实例。
instance_items = list_instances(namespace["namespaceId"], service_name, group_name)
# 归一化实例结构。
normalized_instances: list[dict[str, Any]] = []
# 逐个实例整理字段。
for item in instance_items:
# 读取 healthy 标记。
healthy = nacos_truthy(item.get("healthy", False))
# 读取 enabled 标记。
enabled = nacos_truthy(item.get("enabled", True))
# 当前服务健康实例数。
healthy_total = 0
# 当前服务启用实例数。
enabled_total = 0
# 统计健康实例数。
if healthy:
healthy_total += 1
# 逐个实例整理字段。
for item in instance_items:
# 读取 healthy 标记。
healthy = nacos_truthy(item.get("healthy", False))
# 读取 enabled 标记。
enabled = nacos_truthy(item.get("enabled", True))
# 统计启用实例数。
if enabled:
enabled_total += 1
# 统计健康实例数。
if healthy:
healthy_total += 1
# 追加归一化实例结构。
normalized_instances.append(
# 统计启用实例数。
if enabled:
enabled_total += 1
# 追加归一化实例结构。
normalized_instances.append(
{
"ip": str(item.get("ip") or "").strip(),
"port": int(item.get("port") or 0),
"healthy": healthy,
"enabled": enabled,
"ephemeral": nacos_truthy(item.get("ephemeral", True)),
"weight": float(item.get("weight") or 0.0),
"clusterName": str(item.get("clusterName") or NACOS_DISCOVERY_CLUSTER_NAME).strip(),
"metadata": item.get("metadata") or {},
}
)
# 当前服务实例总数。
current_total = len(normalized_instances)
# 汇总到全局实例总数。
instance_total += current_total
# 汇总到全局健康实例总数。
healthy_instance_total += healthy_total
# 汇总到全局启用实例总数。
enabled_instance_total += enabled_total
# 计算当前服务级别。
level = build_service_level(current_total, healthy_total, enabled_total)
# 全健康服务才记入 healthy_service_total。
if level == "ok":
healthy_service_total += 1
# 追加当前服务结构。
services.append(
{
"ip": str(item.get("ip") or "").strip(),
"port": int(item.get("port") or 0),
"healthy": healthy,
"enabled": enabled,
"ephemeral": nacos_truthy(item.get("ephemeral", True)),
"weight": float(item.get("weight") or 0.0),
"clusterName": str(item.get("clusterName") or NACOS_DISCOVERY_CLUSTER_NAME).strip(),
"metadata": item.get("metadata") or {},
"namespaceId": namespace["namespaceId"],
"namespaceName": namespace["name"],
"rawServiceName": raw_name,
"serviceName": service_name,
"groupName": group_name,
"level": level,
"instanceTotal": current_total,
"healthyTotal": healthy_total,
"unhealthyTotal": current_total - healthy_total,
"enabledTotal": enabled_total,
"disabledTotal": current_total - enabled_total,
"instances": normalized_instances,
}
)
# 当前服务实例总数。
current_total = len(normalized_instances)
# 汇总到全局实例总数。
instance_total += current_total
# 汇总到全局健康实例总数。
healthy_instance_total += healthy_total
# 汇总到全局启用实例总数。
enabled_instance_total += enabled_total
# 计算当前服务级别。
level = build_service_level(current_total, healthy_total, enabled_total)
# 全健康服务才记入 healthy_service_total。
if level == "ok":
healthy_service_total += 1
# 追加当前服务结构。
services.append(
{
"rawServiceName": raw_name,
"serviceName": service_name,
"groupName": group_name,
"level": level,
"instanceTotal": current_total,
"healthyTotal": healthy_total,
"unhealthyTotal": current_total - healthy_total,
"enabledTotal": enabled_total,
"disabledTotal": current_total - enabled_total,
"instances": normalized_instances,
}
)
# 命名空间列表也做一层归一化。
normalized_namespaces = [
{
"namespaceId": str(item.get("namespace") or item.get("namespaceId") or "").strip(),
"name": str(item.get("namespaceShowName") or item.get("namespace") or "").strip(),
"configCount": int(item.get("configCount") or 0),
"type": int(item.get("type") or 0),
}
for item in namespaces
]
# 返回完整 Nacos 监控结构。
return {
"ok": True,
@ -458,4 +481,3 @@ def get_nacos_payload() -> dict[str, Any]:
# 返回缓存或最新构建结果。
return NACOS_CACHE.get_or_build(builder)

View File

@ -226,7 +226,7 @@
<header class="nacos-service-head">
<div>
<h4>{{ service.serviceName }}</h4>
<p>{{ service.groupName }}</p>
<p>{{ service.namespaceName || 'public' }} · {{ service.groupName }}</p>
</div>
<span :class="['badge', service.level === 'ok' ? 'ok' : service.level === 'warn' ? 'warn' : 'bad']">
{{ service.instanceTotal }} / {{ service.healthyTotal }}