- 后端
- 企业应用
- 运维
【免费下载链接】bk-cmdb
蓝鲸智云配置平台(BlueKing CMDB)
本文以 BlueKing CMDB(bk-cmdb,蓝鲸智云配置平台)开放接口find_host_by_topo为核心,完整讲解其请求参数、返回结果、权限要求,并结合host_server服务端源码剖析"按拓扑节点查询主机"的底层实现原理(含 set/module/其他拓扑模型三种分支、去重分页与业务访问鉴权)。读完本文,你将能够准确调用该接口完成"某业务下某个集群、模块或任意拓扑节点下主机清单"的查询,并理解其分页与权限行为。
一、接口概览:能力、版本与权限
find_host_by_topo用于查询指定业务下、指定拓扑节点所挂载的主机。这里的"拓扑节点"可以是业务拓扑中的集群(set)、模块(module),也可以是挂载在拓扑上的其他自定义模型实例;但不能是业务(biz)或主机(host)本身。
- 版本要求:v3.8.13
- 权限要求:业务访问权限
- 开放形式:ESB 开放接口,POST 方法
在仓库的 ESB 接口定义 docs/apidoc/cc/cc.yaml 中,该接口的映射关系如下:
| 项目 | 值 |
|---|---|
| ESB 路径 | /v2/cc/find_host_by_topo/ |
| 内部目标路径(dest_path) | /api/v3/findmany/hosts/by_topo/biz/{bk_biz_id} |
| 内部 HTTP 方法 | POST |
| 接口类型(api_type) | query(查询类) |
同时,在 API 网关资源定义 docs/apidoc/apigw/open/bk_apigw_resources_bk-cmdb.yaml 中也能看到该资源的注册信息:operationId为find_host_by_topo,isPublic: false(非公开资源,需要申请权限),并配置了bk-rate-limit限流插件。也就是说,通过 ESB 或 API 网关调用时,需先完成应用认证与权限申请。
二、请求参数详解
调用该接口需携带公共参数(bk_app_code、bk_app_secret、bk_username、bk_token,即文档模板中的{{ common_args_desc }}),以及以下接口参数。
2.1 接口参数
| 字段 | 类型 | 必选 | 描述 |
|---|---|---|---|
| bk_biz_id | int | 是 | 业务 ID |
| bk_obj_id | string | 是 | 拓扑节点模型 ID,如集群(set)、模块(module)或其他 topo 节点上的模型,不可为 biz、host |
| bk_inst_id | int | 是 | 拓扑节点实例 ID |
| fields | array | 是 | 主机属性列表,控制返回结果的主机里有哪些字段,能够加速接口请求和减少网络流量传输 |
| page | object | 是 | 分页信息 |
说明:
fields的作用是精确裁剪返回字段——你只声明需要的属性,服务端便只回传这些属性,从而显著降低响应体大小与网络传输开销。这也是该接口"面向大规模主机查询"场景的重要设计。
2.2 page 字段说明
| 字段 | 类型 | 必选 | 描述 |
|---|---|---|---|
| start | int | 是 | 记录开始位置 |
| limit | int | 是 | 每页限制条数,最大 500 |
仓库中对应常量BKMaxInstanceLimit = 500(见 src/common/definitions.go),是此类批量查询接口的单页上限约束;同时分页对象BasePage的合法性校验(src/common/metadata/page.go 的IsIllegal)还要求start不能为负、limit必须大于 0 且不超过系统最大页大小BKMaxPageSize = 1000,超出会被判定为非法参数。
三、完整请求示例
{ "bk_app_code": "esb_test", "bk_app_secret": "xxx", "bk_username": "xxx", "bk_token": "xxx", "bk_biz_id": 5, "bk_obj_id": "xxx", "bk_inst_id": 10, "fields": [ "bk_host_id", "bk_cloud_id" ], "page": { "start": 0, "limit": 10 } }示例含义:查询业务 5 中,模型xxx的实例 10 下挂载的主机,只返回bk_host_id、bk_cloud_id两个字段,从第 0 条开始取 10 条。
四、返回结果示例与参数说明
4.1 返回结果示例
{ "result": true, "code": 0, "message": "success", "permission": null, "request_id": "e43da4ef221746868dc4c837d36f3807", "data": { "count": 2, "info": [ { "bk_cloud_id": 0, "bk_host_id": 1 }, { "bk_cloud_id": 0, "bk_host_id": 2 } ] } }4.2 response 字段说明
| 字段 | 类型 | 描述 |
|---|---|---|
| result | bool | 请求成功与否。true:请求成功;false:请求失败 |
| code | int | 错误编码。0 表示 success,>0 表示失败错误 |
| message | string | 请求失败返回的错误信息 |
| permission | object | 权限信息 |
| request_id | string | 请求链 id |
| data | object | 请求返回的数据 |
4.3 data 字段说明
| 字段 | 类型 | 描述 |
|---|---|---|
| count | int | 记录条数(满足条件的总记录数,与分页无关) |
| info | array | 主机实际数据(当前页数据) |
4.4 data.info 字段说明
以下为系统内置的主机属性字段,返回内容取决于请求时fields中所声明的字段:
| 字段 | 类型 | 描述 |
|---|---|---|
| bk_host_name | string | 主机名 |
| bk_host_innerip | string | 内网 IP |
| bk_host_id | int | 主机 ID |
| bk_cloud_id | int | 管控区域 |
| import_from | string | 主机导入来源,以 API 方式导入为 3 |
| bk_asset_id | string | 固资编号 |
| bk_cloud_inst_id | string | 云主机实例 ID |
| bk_cloud_vendor | string | 云厂商 |
| bk_cloud_host_status | string | 云主机状态 |
| bk_comment | string | 备注 |
| bk_cpu | int | CPU 逻辑核心数 |
| bk_cpu_architecture | string | CPU 架构 |
| bk_cpu_module | string | CPU 型号 |
| bk_disk | int | 磁盘容量(GB) |
| bk_host_outerip | string | 主机外网 IP |
| bk_host_innerip_v6 | string | 主机内网 IPv6 |
| bk_host_outerip_v6 | string | 主机外网 IPv6 |
| bk_isp_name | string | 所属运营商 |
| bk_mac | string | 主机内网 MAC 地址 |
| bk_mem | int | 主机内存容量(MB) |
| bk_os_bit | string | 操作系统位数 |
| bk_os_name | string | 操作系统名称 |
| bk_os_type | string | 操作系统类型 |
| bk_os_version | string | 操作系统版本 |
| bk_outer_mac | string | 主机外网 MAC 地址 |
| bk_province_name | string | 所在省份 |
| bk_service_term | int | 质保年限 |
| bk_sla | string | SLA 级别 |
| bk_sn | string | 设备 SN |
| bk_state | string | 当前状态 |
| bk_state_name | string | 所在国家 |
| operator | string | 主要维护人 |
| bk_bak_operator | string | 备份维护人 |
注意:此处的返回值仅对系统内置属性字段做了说明,其余返回值取决于用户自己定义的属性字段。也就是说,只要在
fields中声明了自定义的扩展属性(如机房、负责人、业务标签等),响应中同样会按声明返回。
五、源码级原理:接口是如何"按拓扑查主机"的
5.1 路由注册与处理器入口
该接口的 REST 路由注册在 src/scene_server/host_server/service/service_initfunc.go:
utility.AddHandler(rest.Action{Verb: http.MethodPost, Path: "/findmany/hosts/by_topo/biz/{bk_biz_id}", Handler: s.FindHostsByTopo})即内部路径/api/v3/findmany/hosts/by_topo/biz/{bk_biz_id}由 host_server 的FindHostsByTopo处理器处理(见 src/scene_server/host_server/service/findhost.go)。请求参数结构体定义在 src/common/metadata/hostserver.go:
type FindHostsByTopoOpt struct { ObjID string `json:"bk_obj_id"` InstID int64 `json:"bk_inst_id"` Fields []string `json:"fields"` Page BasePage `json:"page"` }5.2 参数校验规则
FindHostsByTopoOpt.Validate明确了以下约束:
bk_obj_id不能为空;bk_obj_id不能为biz(业务),与文档"不可为 biz"一致;bk_inst_id必须大于 0;fields不能为空(这是强制要求,若未声明字段将直接报错);page必须通过BasePage.IsIllegal校验(start非负、limit在合法范围内)。
此外,处理器还会解析路径参数bk_biz_id并校验其必须为正整数。
5.3 三种拓扑节点的处理分支
处理器 FindHostsByTopo 的核心逻辑是构造"去重主机 ID 查询条件"DistinctHostIDByTopoRelationRequest,按bk_obj_id分为三条路径:
- 当
bk_obj_id为 set(集群):直接把bk_inst_id放入SetIDArr,查询该集群直接挂载的主机; - 当
bk_obj_id为 module(模块):把bk_inst_id放入ModuleIDArr,查询该模块下挂载的主机; - 其他拓扑节点上的模型:调用
GetSetIDsByTopo,从该实例向下遍历其子拓扑、逐层收敛到 set 层级,得到一组 set ID 后再查询这些 set 下的主机;若遍历不到任何 set(例如传入的模型并非拓扑节点或实例无下级拓扑),返回空集合,接口直接返回空结果。
if option.ObjID == common.BKInnerObjIDSet { distinctHostCond.SetIDArr = []int64{option.InstID} } else if option.ObjID == common.BKInnerObjIDModule { distinctHostCond.ModuleIDArr = []int64{option.InstID} } else { setIDArr, err := s.Logic.GetSetIDsByTopo(ctx.Kit, option.ObjID, []int64{option.InstID}) ... distinctHostCond.SetIDArr = setIDArr }5.4 去重、排序与分页的落地实现
查询主机详情由findDistinctHostInfo(src/scene_server/host_server/service/findhost.go#L234-L286)完成,其执行步骤可以归纳为:
- 调用 CoreService 的
GetDistinctHostIDByTopology获取该拓扑节点下去重后的全部主机 ID; - 对主机 ID 列表排序,保证分页切片顺序稳定;
- 在内存中按
page.start/page.limit对主机 ID 做切片:若start已不小于主机总数,则直接返回count为总数、info为空的响应; - 用
bk_host_id IN (切片后的 ID 列表)条件批量查询主机详情,并按fields裁剪返回字段; - 返回
data.count(满足条件的总记录数)与data.info(当前页主机数据)。
理解这一点对调用方很重要:count是总条数而非本页条数,分页游标由客户端通过start递增推进(例如第 2 页应传start: 10, limit: 10)。
六、业务访问权限鉴权与 skipViewBizAuth 配置
该接口的权限说明为"业务访问权限"。在 v3.14.1 的变更记录(docs/support-file/changelog_user/ch/v3.14.1_2024-07-31.md)中明确提到:find_module_host_relation、find_host_by_service_template、find_host_by_set_template、list_biz_hosts、list_biz_hosts_topo、find_host_by_topo、list_host_total_mainline_topo这 7 个 ESB 接口统一增加了"业务访问"权限鉴权。
服务端的实现位于 src/scene_server/host_server/service/findhost.go 的authHostUnderBiz:鉴权启用后,会以host 实例 + Find 动作 + 业务 ID作为资源属性向权限中心发起鉴权,未通过则返回 403/无权限响应。
同时,该鉴权可以通过配置项跳过。配置模板 docs/support-file/config/templates/server#conf#common.yaml 中:
authServer: # 空间级权限版本中,find_module_host_relation、find_host_by_service_template、find_host_by_set_template、 # list_biz_hosts、list_biz_hosts_topo、find_host_by_topo、list_host_total_mainline_topo 这几个上 esb 接口, # 可以配置不进行业务访问鉴权 skipViewBizAuth: false默认skipViewBizAuth: false表示不跳过、正常鉴权;若将其置为true,则上述接口在空间级权限版本中不再校验"业务访问"权限。源码还显示,若权限中心组件未启用(AuthManager.Enabled()为 false),鉴权同样会直接放行。权限解析层面,src/ac/parser/host.go 通过正则^/api/v3/findmany/hosts/by_topo/biz/\d+$识别该路径并生成对应的资源属性。
七、调用注意事项与最佳实践
fields必须显式声明:服务端强制要求fields非空,建议只声明业务真正需要的属性(如bk_host_id、bk_host_innerip、bk_cloud_id),既减少传输流量,也规避多余字段带来的解析成本;bk_obj_id的取值范围:只能是 set、module 或挂载在业务拓扑上的其他模型实例,传biz会被参数校验直接拒绝;传host等不在拓扑上的模型时,通常因遍历不到 set 而返回空结果;- 分页上限:单页
limit最大 500;需要全量数据时应按count循环分页拉取,而非一次请求取回; count的语义:data.count为该拓扑节点下主机总数,用于分页循环的终止条件判断;- 权限与版本:接口版本要求 v3.8.13,且具备"业务访问"权限鉴权;在空间级权限版本下可通过
authServer.skipViewBizAuth配置调整鉴权行为,生产环境请按安全策略谨慎关闭; - 响应裁剪:返回字段中除系统内置属性外,还支持用户自定义属性,只要在
fields中声明即可随响应返回。
借助以上请求参数、返回格式与源码原理,你可以准确地在 ESB/API 网关上完成"按业务拓扑节点查主机"的对接开发,并基于find_host_by_topo组合出"集群-模块-主机"的分层资产盘点、变更巡检等上层应用。
- 后端
- 企业应用
- 运维
【免费下载链接】bk-cmdb
蓝鲸智云配置平台(BlueKing CMDB)
相关推荐
bk-cmdb find_host_by_topo 接口详解:查询拓扑节点下的主机
bk cmdb find_host_by_topo 接口详解:查询拓扑节点下的主机 本文基于 bk cmdb(蓝鲸智云配置平台)API 网关开放接口文档 fin
后端企业应用运维蓝鲸配置平台 bk-cmdb 按拓扑节点查询主机(find_host_by_topo)接口实战指南
蓝鲸配置平台 bk cmdb 按拓扑节点查询主机(find_host_by_topo)接口实战指南 导读 find_host_by_topo 是蓝鲸配置平台(b
后端企业应用运维bk-cmdb 业务主线拓扑节点简要关系查询接口(find_brief_biz_topo_node_relation)实战指南
bk cmdb 业务主线拓扑节点简要关系查询接口(find_brief_biz_topo_node_relation)实战指南 导读 本文围绕蓝鲸智云配置平台(
后端企业应用运维
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考