通过 External API 导出服务拓扑¶
本文说明如何使用 观测云 External API 获取服务节点和调用关系,并通过逐工作空间查询,汇总指定站点内的服务拓扑数据。
接口返回 JSON。生成 CSV、Excel 或应用依赖清单,需要由调用方整理返回结果。
适用范围¶
- 查询指定时间范围内采集到的 APM 服务拓扑,用于梳理服务之间的调用关系。
- 单个工作空间使用服务拓扑接口;站点内全部工作空间使用“分页列出空间 → 逐空间查询拓扑 → 汇总结果”。
- 导出结果受采集完整性、数据保留时间和部署版本影响,不代表全部历史依赖或未被采集的调用关系。
- 本文采用每次指定一个
workspaceUUID的方式。控制台跨空间选择器与此流程不同;不要将多个 UUID 或*拼入workspaceUUID。
如果需要分析不同工作空间之间的调用关系,还需确认现场已经具备对应的采集和跨空间拓扑能力,参见 APM 服务拓扑跨空间配置说明。逐空间汇总不会补出原始数据中不存在的跨空间调用边。
准备工作¶
- 确认当前站点的 External API Endpoint。通常为
https://external-api.guance.com,以实际部署地址为准,不使用控制台 front 或 OpenAPI Endpoint 替代。 - 准备 External API 的 AK/SK,按照接口签名认证生成请求头。不要使用工作空间 OpenAPI 的
DF-API-KEY替代签名。 - 在支持 External 只读账号的版本中,可以使用只读账号调用本文两个查询接口。账号由站点管理员配置。
- 固定一组
start、end,均为毫秒时间戳,且start < end。所有空间使用相同时间范围;签名头中的X-Df-Timestamp则是每次发起请求时的秒时间戳。 - 先选一个工作空间,用与控制台相同的时间范围和筛选条件验证返回,再开始批量导出。部署版新增分组等参数的支持情况,以现场版本为准。
第一步:分页获取工作空间¶
调用工作空间列出接口:
pageIndex 从 1 开始;pageSize 最大为 100。导出站点内全部空间时不传 search。
读取响应中的:
| 字段 | 用途 |
|---|---|
content.data[].uuid |
后续拓扑请求的 workspaceUUID |
content.data[].name |
为导出数据补充查询空间名称 |
content.pageInfo.totalCount |
符合条件的空间总数,用于判断是否需要继续翻页 |
每次将 pageIndex 加 1,直到已遍历完分页结果。按 UUID 去重,并保存本次实际查询的空间清单。如果尚未达到总数却返回空页,应记录异常并重新检查,不能直接宣告全部空间导出成功。导出期间空间发生新增或删除时,分页结果也可能变化。
第二步:获取每个空间的服务拓扑¶
调用 service map 接口:
示例时间范围为北京时间 2026-09-15 08:00 至 2026-09-16 08:00,请替换为实际需要且仍在数据保留期内的范围。
以下请求展示需要携带的签名头,不能直接使用占位符执行:
curl '<Endpoint>/api/v1/tracing/service_map_v2?workspaceUUID=wksp_example&start=1789430400000&end=1789516800000' \
-H 'X-Df-Access-Key: <AK>' \
-H 'X-Df-SVersion: v20240417' \
-H 'X-Df-Timestamp: <当前秒时间戳>' \
-H 'X-Df-Nonce: <本次请求的随机临时码>' \
-H 'X-Df-Signature: <根据最终请求路径计算的签名>'
每次请求都需要重新生成临时码、时间戳和签名。签名使用最终发送的原始路径与查询字符串;增加 groupBy 等参数或进行 URL 编码后,需要按最终路径重新签名。
选择查询范围¶
| 目标 | 参数设置 |
|---|---|
| 获取一个空间内所选时间范围的完整拓扑 | 只传 workspaceUUID、start、end,不传 centralService、search 或限制性 filters |
| 获取指定中心服务的拓扑 | 增加 centralService,例如 centralService=demo-web |
| 区分环境和版本 | 在支持该参数的版本增加 groupBy=env,version |
| 区分项目或 K8s 集群 | 按实际需要设置 groupBy=project、groupBy=cluster_name_k8s 或其组合 |
groupBy 会影响节点身份,所有空间应使用相同的分组口径。指定中心服务并启用分组时,可使用 centralWorkspaceUUID、centralEnv 等字段进一步定位中心节点,具体见接口参数说明。
控制台的单服务“上下游”视图包含中心服务限制,不能直接当作整个空间的拓扑。核对页面与接口时,应同时对齐时间、空间、分组和筛选条件;图形布局、节点颜色等展示属性不属于需要导出的业务关系。
导出直接读取 content.services 和 content.maps。不要依赖 serviceMapList=true 生成额外列表或下载文件。
第三步:保存节点、调用边和执行结果¶
每次请求先检查 HTTP 状态及响应中的 code、success、errorCode。成功后保存完整 JSON,并附带本次查询的空间 UUID、时间范围和分组参数。
| 字段 | 含义 |
|---|---|
content.services |
服务节点列表;保留节点名称、空间身份、节点 ID(如有)及 data |
content.maps |
有方向的调用边,source 为调用方、target 为被调用方 |
maps[].source_workspace_uuid / target_workspace_uuid |
边两端所属空间(返回时应保留) |
maps[].source_id / target_id |
边两端节点 ID(返回时应保留),可用于区分同名节点 |
maps[].avg_per_second、error_count、error_rate、p99 |
调用边可能返回的统计字段,以实际版本返回为准 |
测试环境实测响应的脱敏节选见 service map 响应示例。示例保留所选节点和调用边的字段与统计数值,不能替代现场响应核验。
建议输出两类文件:
- 原始 JSON:按查询空间分别保存,保留节点、边、统计值和响应
traceId,便于复查。 - 调用关系表:每行记录一条有方向的调用关系,至少包含查询空间、来源空间、来源服务、目标空间、目标服务、开始时间、结束时间;根据实际响应增加节点 ID 和分组维度。
汇总规则:
A → B与B → A是两条不同的关系。- 不同空间的同名服务不能仅按名称合并;优先使用“空间身份 + 节点 ID”,缺少 ID 时使用“空间身份 + 服务名 + 所选分组维度”。不能确认空间身份时,应标记待核对,不要根据查询空间猜测边另一端的所属空间。
- 同一调用边可能出现在多个空间的查询结果中。关系清单可以按上述节点身份组成的有向边去重,同时保留来源查询空间;原始 JSON 不去重。
- 不要直接累加重复边的请求数,也不要直接平均请求速率、错误率或 P99。需要全局统计值时,应另行确定聚合口径。
services和maps分别保存;仅从调用边提取节点,可能遗漏没有调用边的服务。- 字段缺失不能按
0处理。特别是统计字段,应区分“没有返回”与“返回零值”。
批量执行流程¶
以下是流程伪代码;签名客户端实现可复用接口签名认证中的 Python 示例。
固定 start、end 和 groupBy
分页读取 workspace/list,保存并按 uuid 去重得到空间清单
如果空间清单读取失败:停止,标记本次导出不完整
对空间清单中的每个空间串行执行:
重新生成签名,查询 service_map_v2
如果 HTTP 或业务状态失败:
记录失败空间、错误码和 traceId,继续其他空间
如果成功但 services/maps 结构异常:
保存原始响应,标记结构异常,不当作空拓扑
如果成功且结构正常:
保存原始 JSON
services 和 maps 都为空时,记录“该时间范围无拓扑数据”
否则按节点身份整理调用关系表
输出空间总数、成功数、无数据数、失败数及失败空间清单
存在失败或结构异常时:将结果标记为部分完成
对失败空间在同一时间范围内重试,再更新汇总结果
建议先串行查询,设置合理的请求超时;空间较多时根据现场负载控制并发。服务拓扑接口没有对外提供 pageIndex/pageSize 式分页参数,不能套用空间列表的翻页方式来获取更多调用边。数据量较大时应核对现场查询限制和返回完整性。
验证与排查¶
| 现象 | 检查方法 |
|---|---|
| 签名失败 | 检查 Endpoint、AK/SK、v20240417、系统时间,以及签名路径是否与最终 URL 编码和参数顺序一致 |
| 只导出一个服务附近的关系 | 检查是否复制了页面请求中的 centralService、搜索或筛选条件 |
| 与页面服务数量不一致 | 对齐空间、时间、分组、筛选及上下游/完整拓扑视图;页面展示还会处理节点和边 |
| 未看到跨空间调用边 | 检查采集、现场版本与跨空间拓扑配置,不应仅凭逐空间汇总推断跨空间关系完整 |
| 同名服务被合并 | 检查空间身份、节点 ID 和 groupBy 维度是否参与去重 |
| 空结果 | 先确认请求成功及结构正常,再检查时间范围、保留期和该空间是否有 APM 数据 |
| 部分空间请求失败 | 保留失败清单和 traceId,重试后再确认导出是否完成 |
发布到客户环境前,建议至少验证:一个有调用关系的空间、一个无拓扑数据的空间、空间列表分页、失败空间记录,以及不同空间同名服务的区分。