news 2026/10/13 2:07:56

蓝鲸智云配置平台 bk-cmdb:list_biz_hosts_topo 业务主机与拓扑查询接口实战指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
蓝鲸智云配置平台 bk-cmdb:list_biz_hosts_topo 业务主机与拓扑查询接口实战指南
  • 后端
  • 企业应用
  • 运维

【免费下载链接】bk-cmdb

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

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

导读

list_biz_hosts_topo是蓝鲸智云配置平台(BlueKing CMDB,即 bk-cmdb)对外提供的 OpenAPI 网关接口之一,用于按业务 ID 一次性查询该业务下的主机明细及其所属的集群、模块拓扑关系,并支持对集群、模块、主机三个维度的属性进行组合过滤。读完本文,你将掌握该接口的完整请求参数结构、querybuilder组合查询规则的写法(含嵌套与操作符取值)、返回数据结构语义,以及它在host_server服务内部的完整执行链路与底层实现原理,可直接据此编写可运行的调用代码。

本文对应接口文档为 docs/apidoc/apigw/open/zh/list_biz_hosts_topo.md,英文版见 docs/apidoc/apigw/open/en/list_biz_hosts_topo.md。接口文档按 API Gateway 资源文档规范组织,存放于仓库的 API Gateway 接口文档目录,参见 docs/apidoc/apigw/README.md。

接口概述

项说明
接口名称list_biz_hosts_topo
请求方法POST
路由(host_server 内部)/hosts/app/{bk_biz_id}/list_hosts_topo
权限业务访问权限(Business Access Permission)
核心能力按业务查询主机明细 + 主机所属集群/模块拓扑,三个维度可叠加过滤

该接口的路由注册位于 src/scene_server/host_server/service/service_initfunc.go,处理函数为ListBizHostsTopo,定义于 src/scene_server/host_server/service/findhost.go。

输入参数说明

顶层参数

参数名称参数类型必选描述
pageobject是分页查询条件,返回的主机数据按照bk_host_id排序
bk_biz_idint是业务 ID(同时作为 URL 路径参数{bk_biz_id})
set_property_filterobject否集群属性组合查询条件
module_property_filterobject否模块属性组合查询条件
host_property_filterobject否主机属性组合查询条件
fieldsarray是主机属性列表,控制返回结果的主机里有哪些字段,能够加速接口请求和减少网络流量传输

需要说明的是,bk_biz_id同时出现在请求体与路径中。从源码看,处理函数优先从路径参数解析业务 ID(findhost.go),因此调用时务必保证路径与请求体中的业务 ID 一致。

page 分页参数

参数名称参数类型必选描述
startint是记录开始位置
limitint是每页限制条数,最大 500

分页校验在参数结构体ListBizHostsTopoParameter.Validate中完成(src/common/metadata/hostserver.go):page.limit必须设置(不能为 0),且不能超过常量common.BKMaxInstanceLimit(即 500),否则返回参数校验错误。返回的主机数据按bk_host_id排序。

set_property_filter / module_property_filter / host_property_filter

这三个参数结构完全一致,分别作用于集群、模块、主机三层维度,用于"根据某层属性字段筛选出该层实例,再定位其下/其上的主机"。

  • 组合支持AND和OR两种方式,可以嵌套,最多嵌套 2 层;
  • 过滤规则为四元组field、operator、value。
组合节点(condition / rules)
参数名称参数类型必选描述
conditionstring否组合查询条件,取值AND/OR
rulesarray否规则数组,元素可以是原子规则,也可以是嵌套的组合节点
原子规则(rules 元素)
参数名称参数类型必选描述
fieldstring是字段名
operatorstring是操作符,可选值equal,not_equal,in,not_in,less,less_or_equal,greater,greater_or_equal,between,not_between
value-否操作数,不同 operator 对应不同的 value 格式

组装规则的完整语法与操作符语义,可参考 src/common/querybuilder/README.md,以及对应实现 src/common/querybuilder/types.go 与 src/common/querybuilder/parser.go。

组合查询规则(querybuilder)详解

接口文档中提到的三个*_property_filter参数在底层均由configcenter/src/common/querybuilder包解析。QueryFilter的 JSON/BSON 反序列化即调用ParseRule将请求数据解析为规则树(parser.go),因此文档给出的嵌套 JSON 可以直接被接口解析。

规则模型:原子规则与组合规则

从源码(types.go)可以看到,规则树由两种节点组成:

  • 原子规则(AtomRule):叶子节点,由field、operator、value三元组构成,是任何过滤规则的基础;
  • 组合规则(CombinedRule):非叶子节点,由condition(AND/OR)与rules(可继续嵌套的规则数组)构成,组合的节点可以是原子规则或组合规则。

每个节点实现了统一的Rule接口:GetDeep()返回规则深度、Validate()做合法性校验、ToMgo()将规则转换为 MongoDB 查询条件、Match()用于内存匹配。这就是"查询条件本质上是过滤规则树"的底层模型。

嵌套深度限制的真相

文档说"最多嵌套 2 层",其实现依据是MaxDeep = 3常量(types.go),注释明确说明:"嵌套层级的深度按树的高度计算,查询条件最大深度为 3 即最多嵌套 2 层"。在 ListBizHostsTopoParameter.Validate 中,三个 filter 分别调用GetDeep()并与MaxDeep比较,超限即返回host_property_filter.rules/set_property_filter.rules/module_property_filter.rules超限错误。

操作符说明

接口文档给出的操作符可选值为:equal、not_equal、in、not_in、less、less_or_equal、greater、greater_or_equal、between、not_between。

需要指出的是,src/common/querybuilder/README.md 中明确说明:该模块不支持between与not_between运算符,这类运算可以基于基本比较运算符组合实现。与此同时,实现还额外支持时间操作符(datetime_less等,仅支持 RFC3339 格式)、字符串操作符(begins_with、contains、ends_with等)、空值操作符(is_null、is_not_null)、字段存在操作符(exist、not_exist)以及数组空值操作符(is_empty、is_not_empty),详见 README 的 Operator 章节 与 types.go 的校验与转换实现。

各操作符与 value 格式的对应关系如下:

操作符含义value 格式
equal相等比较基本数据类型(数值/bool/字符串)
not_equal不等比较基本数据类型(数值/bool/字符串)
in字段值在指定集合中同类型基本数据类型组成的数组
not_in字段值不在指定集合中同类型基本数据类型组成的数组
less字段值 < value数值
less_or_equal字段值 <= value数值
greater字段值 > value数值
greater_or_equal字段值 >= value数值
is_empty / is_not_empty数组为空 / 非空不接受参数
is_null / is_not_null字段值为 null / 非 null不接受参数
exist / not_exist字段存在 / 不存在不接受参数
begins_with / not_begins_with以某字符串开头 / 不以某字符串开头非空字符串
contains / not_contains包含 / 不包含某字符串非空字符串
ends_with / not_ends_with以某字符串结尾 / 不以某字符串结尾非空字符串
datetime_less / datetime_less_or_equal / datetime_greater / datetime_greater_or_equal时间早于 / 不晚于 / 晚于 / 不早于RFC3339 格式字符串

校验规则可参见 types.go 的validateValueByOperator:数组类操作符要求数组元素类型一致(接口通过RuleOption{NeedSameSliceElementType: true}开启该校验),数值类操作符要求 value 为数值,字符串类操作符要求非空字符串。转换到 MongoDB 查询条件时,equal/not_equal/in/not_in会先调用ConvertIpv6ToFullWord做 IPv6 全字格式转换(types.go),这保证了 IPv6 地址字段过滤的正确性。

调用示例

以下为接口文档给出的完整请求体(可直接用于 POST 调用):

{ "page": { "start": 0, "limit": 10 }, "bk_biz_id": 3, "fields": [ "bk_host_id", "bk_cloud_id", "bk_host_innerip", "bk_os_type", "bk_mac" ], "set_property_filter": { "condition": "AND", "rules": [ { "field": "bk_set_name", "operator": "not_equal", "value": "test" }, { "condition": "OR", "rules": [ { "field": "bk_set_id", "operator": "in", "value": [ 1, 2, 3 ] }, { "field": "bk_service_status", "operator": "equal", "value": "1" } ] } ] }, "module_property_filter": { "condition": "OR", "rules": [ { "field": "bk_module_name", "operator": "equal", "value": "test" }, { "condition": "AND", "rules": [ { "field": "bk_module_id", "operator": "not_in", "value": [ 1, 2, 3 ] }, { "field": "bk_module_type", "operator": "equal", "value": "1" } ] } ] }, "host_property_filter": { "condition": "AND", "rules": [ { "field": "bk_host_innerip", "operator": "equal", "value": "127.0.0.1" }, { "condition": "OR", "rules": [ { "field": "bk_os_type", "operator": "not_in", "value": [ "3" ] }, { "field": "bk_cloud_id", "operator": "equal", "value": 0 } ] } ] } }

示例语义拆解

  • page:从第 0 条开始,每页最多返回 10 条,按bk_host_id排序;
  • bk_biz_id:业务 ID 为 3;
  • fields:只返回bk_host_id、bk_cloud_id、bk_host_innerip、bk_os_type、bk_mac五个主机字段,减少网络传输;
  • set_property_filter:集群名不等于test,且(集群 ID 在 1/2/3 中 或 服务状态等于1);
  • module_property_filter:模块名等于test,或(模块 ID 不在 1/2/3 中 且 模块类型等于1);
  • host_property_filter:内网 IP 等于127.0.0.1,且(系统类型不在["3"]中 或 管控区域等于0)。

该示例同时演示了三个 filter 各自带一层嵌套(AND下挂OR,或OR下挂AND),正好落在"最多嵌套 2 层"的约束之内。

响应示例

{ "result": true, "code": 0, "message": "success", "permission": null, "data": { "count": 3, "info": [ { "host": { "bk_cloud_id": 0, "bk_host_id": 1, "bk_host_innerip": "192.168.15.18", "bk_mac": "", "bk_os_type": null }, "topo": [ { "bk_set_id": 11, "bk_set_name": "set1", "module": [ { "bk_module_id": 56, "bk_module_name": "m1" } ] } ] }, { "host": { "bk_cloud_id": 0, "bk_host_id": 2, "bk_host_innerip": "192.168.15.4", "bk_mac": "", "bk_os_type": null }, "topo": [ { "bk_set_id": 11, "bk_set_name": "set1", "module": [ { "bk_module_id": 56, "bk_module_name": "m1" } ] } ] }, { "host": { "bk_cloud_id": 0, "bk_host_id": 3, "bk_host_innerip": "192.168.15.12", "bk_mac": "", "bk_os_type": null }, "topo": [ { "bk_set_id": 10, "bk_set_name": "空闲机池", "module": [ { "bk_module_id": 54, "bk_module_name": "空闲机" } ] } ] } ] } }

从响应可以看到:每台主机通过host对象携带其实际属性数据,通过topo数组携带所属的集群与模块信息;未分配具体业务模块的主机(如第 3 台)会出现在"空闲机池 / 空闲机"这类默认拓扑节点下。

响应参数说明

公共响应包装

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

data

参数名称参数类型描述
countint记录条数
infoarray主机数据和拓扑信息

data.info

参数名称参数类型描述
hostdict主机实际数据
topoarray主机拓扑信息

data.info.host(系统内置主机属性)

参数名称参数类型描述
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中,同样会返回。

data.info.topo

参数名称参数类型描述
bk_set_idint主机所属的集群 ID
bk_set_namestring主机所属的集群名字
modulearray主机所属的集群下模块信息

data.info.topo.module

参数名称参数类型描述
bk_module_idint模块 ID
bk_module_namestring模块名字

上述响应结构在源码中对应 src/common/metadata/hostserver.go 的HostTopoResult、HostTopo、Topo、Module四个结构体,其 JSON tag 与文档参数一一对应。

源码级执行链路解析

接口处理函数ListBizHostsTopo的内部流程可以划分为六个阶段,对应 findhost.go:

  1. 路径参数解析与鉴权:从路径中解析bk_biz_id(为 0 或非法时直接报参数错误),随后调用authHostUnderBiz校验当前用户的业务访问权限,无权限时返回RespNoAuth;
  2. 请求体反序列化与校验:将请求体解析为meta.ListBizHostsTopoParameter,调用其Validate方法校验分页参数与三个过滤条件(hostserver.go);
  3. 集群维度预过滤:调用parseHostsTopoFilter(findhost.go)将set_property_filter通过ToMgo()转换为 MongoDB 条件,并与bk_biz_id组成 AND 条件查询集群实例,得到符合条件的setIDs与setMap(ID 到名称的映射)。若配置了该过滤条件但结果为空,直接返回count=0的空列表,避免后续查询;
  4. 模块维度预过滤:同样的逻辑处理module_property_filter,得到moduleIDs与moduleMap;
  5. 主机查询:以bizID + setIDs + moduleIDs + host_property_filter组装meta.ListHosts查询条件,调用CoreService().Host().ListHosts查询主机列表。注意这里会把fields与bk_host_id合并后传给底层(保证后续拓扑组装有主机 ID 可用),并设置 MongoDB 从节点读偏好(SecondaryPreferredMode);
  6. 拓扑组装:调用rearrangeBizHostTopo(findhost.go)补齐拓扑信息——先按主机 ID 集合查询"主机-模块"关系(GetHostRelations),生成主机ID -> 集群ID -> 模块ID列表的映射;再对尚未出现在setMap/moduleMap中的集群、模块实例做一次补充查询(getOtherInstInfo,findhost.go);最后按HostTopoResult{count, info:[{host, topo:[{bk_set_id, bk_set_name, module:[{bk_module_id, bk_module_name}]}]}]}的格式组装输出。

其中集群/模块实例的查询由GetInstIDNameInfo完成(src/scene_server/host_server/logics/instance.go):按objID解析实例 ID 与名称字段(如 set 的bk_set_id/bk_set_name),一次查询出ID -> 名称映射,供拓扑输出使用。

客户端调用方式

在 Go 侧,apimachinery 提供了封装好的客户端方法ListBizHostsTopo(src/apimachinery/hostserver/apis.go),其内部即向/hosts/app/%d/list_hosts_topo发起 POST 请求。

仓库的集成测试 src/test/host_server/host_test.go 给出了典型的调用与断言模式:先通过TransferHostModule将主机转移至目标模块,再调用ListBizHostsTopo并断言响应中同时包含count、两台主机的bk_host_id、所属bk_set_id与bk_module_id。这也验证了该接口"主机 + 拓扑一次返回"的核心行为。

使用建议与注意事项

  1. 善用 fields 裁剪字段:文档明确说明fields用于控制返回的主机字段,能加速接口请求并减少网络流量。只声明本次业务需要的字段即可,服务端还会在内部追加bk_host_id用于拓扑组装。
  2. 保持分页参数在约束内:page.limit必填且最大 500,start从 0 开始;结果按bk_host_id排序,适合游标式翻页。
  3. 三过滤器是"逐层收窄"关系:从执行链路看,集群过滤与模块过滤会先各自筛出符合条件的实例 ID 集合,再与主机属性过滤一起作为主机查询的约束条件,三者共同决定最终返回的主机集合;而返回的topo则是主机实际所属的完整集群/模块关系。
  4. 注意嵌套深度与操作符边界:组合条件最多嵌套 2 层(源码层面对应MaxDeep=3的树高限制);同时按 src/common/querybuilder/README.md 的说明,between/not_between未被该模块实现,如需区间查询请用greater_or_equal+less_or_equal组合表达。
  5. 权限前置:接口要求业务访问权限,无权限的调用会在进入数据查询前被拦截(findhost.go)。

相关资源索引

  • 接口中文文档:docs/apidoc/apigw/open/zh/list_biz_hosts_topo.md
  • 接口英文文档:docs/apidoc/apigw/open/en/list_biz_hosts_topo.md
  • 组合查询规则说明:src/common/querybuilder/README.md
  • querybuilder 规则模型与操作符实现:src/common/querybuilder/types.go、src/common/querybuilder/parser.go
  • 接口处理实现:src/scene_server/host_server/service/findhost.go
  • 参数与响应结构体:src/common/metadata/hostserver.go
  • 客户端封装:src/apimachinery/hostserver/apis.go
  • 集成测试:src/test/host_server/host_test.go
  • 后端
  • 企业应用
  • 运维

【免费下载链接】bk-cmdb

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

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

相关推荐

上一篇:order-book-dynamics性能调优:10个提升预测准确率的技巧
下一篇:import-http vs Deno:现代JavaScript模块加载方案对比分析

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

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/13 2:07:04

Windows本地部署OpenClaw+DeepSeek+飞书AI质检流水线

简介&#xff1a;本资源是一套面向AI开发者与企业办公自动化实践者的Windows本地AI助手部署方案&#xff0c;解决在私有环境中通过飞书远程调用本地大模型&#xff08;DeepSeek&#xff09;执行文件管理、智能对话与自动化操作的核心需求。资源包共3个文件&#xff0c;含1个.in…

作者头像 李华
网站建设 2026/10/13 2:06:58

一句话逆向工程:REA 接入 Claude Code 的完整实测

一句话逆向工程&#xff1a;REA 接入 Claude Code 的完整实测 【免费下载链接】rea Reverse engineer anything with agents, from app behavior down to native binaries. 项目地址: https://gitcode.com/GitHub_Trending/rea2/rea 对 Claude Code 说一句"分析 No…

作者头像 李华
网站建设 2026/10/13 2:06:31

Spring Formatter深度解析:双向格式化与国际化实践

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/13 2:04:12

Matlab手写逻辑回归:自定义数据格式与训练集个数实现

之前做用户流失预测和信用评分时&#xff0c;我第一版模型经常直接用逻辑回归&#xff0c;原因很直接&#xff1a;可解释性强、训练快、而且能输出概率。这两年Matlab用得比较多&#xff0c;发现网上很多“逻辑回归分类预测”的教程代码&#xff0c;要么只跑自带数据集&#xf…

作者头像 李华