☰
bk-cmdb find_host_by_topo 接口实战:按拓扑节点查询主机(ESB 开放接口全解)
2026/10/14 18:12:20 网站建设 项目流程
  • 后端
  • 企业应用
  • 运维

【免费下载链接】bk-cmdb

蓝鲸智云配置平台(BlueKing CMDB)

项目地址:https://gitcode.com/gh_mirrors/bk/bk-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_idint是业务 ID
bk_obj_idstring是拓扑节点模型 ID,如集群(set)、模块(module)或其他 topo 节点上的模型,不可为 biz、host
bk_inst_idint是拓扑节点实例 ID
fieldsarray是主机属性列表,控制返回结果的主机里有哪些字段,能够加速接口请求和减少网络流量传输
pageobject是分页信息

说明:fields的作用是精确裁剪返回字段——你只声明需要的属性,服务端便只回传这些属性,从而显著降低响应体大小与网络传输开销。这也是该接口"面向大规模主机查询"场景的重要设计。

2.2 page 字段说明

字段类型必选描述
startint是记录开始位置
limitint是每页限制条数,最大 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 字段说明

字段类型描述
resultbool请求成功与否。true:请求成功;false:请求失败
codeint错误编码。0 表示 success,>0 表示失败错误
messagestring请求失败返回的错误信息
permissionobject权限信息
request_idstring请求链 id
dataobject请求返回的数据

4.3 data 字段说明

字段类型描述
countint记录条数(满足条件的总记录数,与分页无关)
infoarray主机实际数据(当前页数据)

4.4 data.info 字段说明

以下为系统内置的主机属性字段,返回内容取决于请求时fields中所声明的字段:

字段类型描述
bk_host_namestring主机名
bk_host_inneripstring内网 IP
bk_host_idint主机 ID
bk_cloud_idint管控区域
import_fromstring主机导入来源,以 API 方式导入为 3
bk_asset_idstring固资编号
bk_cloud_inst_idstring云主机实例 ID
bk_cloud_vendorstring云厂商
bk_cloud_host_statusstring云主机状态
bk_commentstring备注
bk_cpuintCPU 逻辑核心数
bk_cpu_architecturestringCPU 架构
bk_cpu_modulestringCPU 型号
bk_diskint磁盘容量(GB)
bk_host_outeripstring主机外网 IP
bk_host_innerip_v6string主机内网 IPv6
bk_host_outerip_v6string主机外网 IPv6
bk_isp_namestring所属运营商
bk_macstring主机内网 MAC 地址
bk_memint主机内存容量(MB)
bk_os_bitstring操作系统位数
bk_os_namestring操作系统名称
bk_os_typestring操作系统类型
bk_os_versionstring操作系统版本
bk_outer_macstring主机外网 MAC 地址
bk_province_namestring所在省份
bk_service_termint质保年限
bk_slastringSLA 级别
bk_snstring设备 SN
bk_statestring当前状态
bk_state_namestring所在国家
operatorstring主要维护人
bk_bak_operatorstring备份维护人

注意:此处的返回值仅对系统内置属性字段做了说明,其余返回值取决于用户自己定义的属性字段。也就是说,只要在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)完成,其执行步骤可以归纳为:

  1. 调用 CoreService 的GetDistinctHostIDByTopology获取该拓扑节点下去重后的全部主机 ID;
  2. 对主机 ID 列表排序,保证分页切片顺序稳定;
  3. 在内存中按page.start/page.limit对主机 ID 做切片:若start已不小于主机总数,则直接返回count为总数、info为空的响应;
  4. 用bk_host_id IN (切片后的 ID 列表)条件批量查询主机详情,并按fields裁剪返回字段;
  5. 返回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)

项目地址:https://gitcode.com/gh_mirrors/bk/bk-cmdb
点击查看免费下载

相关推荐

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询