- 后端
- 企业应用
- 运维
【免费下载链接】bk-cmdb
蓝鲸智云配置平台(BlueKing CMDB)
在蓝鲸智云配置平台(bk-cmdb)的进程管理场景中,服务实例(ServiceInstance)是承载主机上进程实例的运行时载体。本文基于开放 API 文档 list_service_instance,完整讲解list_service_instance接口的入参、分页、标签过滤与响应结构,并结合 bk-cmdb 仓库源码(proc_server 路由、metadata 查询模型、coreservice 存储层)还原其完整调用链与底层实现,帮助你在集成或排查该接口时做到"参数知其然、行为知其所以然"。
接口定位与调用方式
list_service_instance用于根据业务 id 查询服务实例列表,也可以叠加模块 id、主机 id 列表、名称模糊搜索、标签过滤等条件进一步收敛结果,是进程管理相关开放 API 中检索频率最高的一类接口。
从 API 网关定义 bk_apigw_resources_bk-cmdb.yaml 可以看到该接口的元信息:
- operationId:
list_service_instance,描述为"查询服务实例列表"; - 后端转发:网关将请求以
POST方法转发至后端路径/api/v3/findmany/proc/service_instance; - 权限模型:
isPublic: false、allowApplyPermission: true,即非公开资源,需要按资源维度申请list_service_instance权限;在 definition.yaml 中,list_service_instance被列入了多个内部应用(如 NodeManager、BCS 等)的资源授权清单; - 限流:配置了
bk-rate-limit插件,默认速率period: 1, tokens: 100,即每秒 100 个 token 的令牌桶限流,批量调用方需注意控制并发。
输入参数
接口的请求体参数如下(继承自原始文档):
| 参数名称 | 参数类型 | 必选 | 描述 |
|---|---|---|---|
| bk_biz_id | int | 是 | 业务id |
| bk_module_id | int | 否 | 模块ID |
| bk_host_ids | int array | 否 | 主机id列表,最多支持1000个主机id |
| selectors | int | 否 | label过滤功能,operator可选值:=,!=,exists,!,in,notin |
| page | object | 否 | 分页参数 |
| search_key | string | 否 | 名字过滤参数,可填写进程名称包含的字符用于模糊搜索 |
补充说明:原始文档中
selectors的参数类型标注为int属于笔误,从源码看其实际类型是 selector 对象数组(见 metadata.ListServiceInstanceOption 中Selectors selector.Selectors字段),每个元素包含key、operator、values三个字段。
page 分页参数
| 参数名称 | 参数类型 | 必选 | 描述 |
|---|---|---|---|
| start | int | 是 | 记录开始位置 |
| limit | int | 是 | 每页限制条数,最大500 |
分页约束在源码中可以得到印证:
- 上限 500 对应全局常量
BKMaxLimitSize = 500(src/common/definitions.go),BasePage.Validate会对越界的分页参数返回错误(src/common/metadata/page.go); bk_host_ids"最多支持 1000 个主机 id" 对应BKMaxPageSize = 1000,处理器SearchServiceInstancesInModule中显式检查len(input.HostIDs) > common.BKMaxPageSize,超出时直接返回参数超限错误(serviceinstance.go)。
selectors 标签过滤
selectors用于基于服务实例的 labels(标签)做条件过滤。从源码 selector.go 可以看到:
- 支持的 operator 全集为
=(Equals)、!=(NotEquals)、exists、!(DoesNotExist)、in、notin,与文档描述一致; - 校验规则:
in/notin的values不能为空;exists/!的values必须为空;=/!=的values长度必须恰好为 1; - 最终通过
ToMgoFilter转换为 MongoDB 查询条件,作用在labels.<key>字段上:in→$in、notin→$nin、exists/!→$exists、=→ 精确相等、!=→$ne;多个 selector 之间以$and连接。
也就是说,标签过滤是在服务实例自身携带的 labels 字段上生效,而不是对bk_host_id等内置字段生效,调用时key必须与实例上已打标的标签键匹配。
调用示例
{ "bk_biz_id": 1, "page": { "start": 0, "limit": 1 }, "bk_module_id": 56, "bk_host_ids":[26,10], "search_key": "", "selectors": [{ "key": "key1", "operator": "notin", "values": ["value1"] },{ "key": "key1", "operator": "in", "values": ["value1", "value2"] }] }结合源码可以确认请求体与后端模型的映射关系。proc_server 侧的入参结构体为 metadata.GetServiceInstanceInModuleInput:
type GetServiceInstanceInModuleInput struct { BizID int64 `json:"bk_biz_id"` ModuleID int64 `json:"bk_module_id"` HostIDs []int64 `json:"bk_host_ids"` Page BasePage `json:"page"` SearchKey *string `json:"search_key"` Selectors selector.Selectors `json:"selectors"` }其中search_key在后端以指针类型接收,空字符串与不传在反序列化后的语义上等价于"不做名称过滤",因此示例中传"search_key": ""不会触发模糊搜索。
响应结构与参数说明
响应示例(继承自原始文档):
{ "result": true, "code": 0, "message": "success", "permission": null, "data": { "count": 1, "info": [ { "bk_biz_id": 1, "id": 72, "name": "t1", "bk_host_id": 26, "bk_module_id": 62, "creator": "admin", "modifier": "admin", "create_time": "2019-06-20T22:46:00.69+08:00", "last_time": "2019-06-20T22:46:00.69+08:00", "bk_supplier_account": "0" } ] } }响应参数说明
| 参数名称 | 参数类型 | 描述 |
|---|---|---|
| result | bool | 请求成功与否。true:请求成功;false请求失败 |
| code | int | 错误编码。 0表示success,>0表示失败错误 |
| message | string | 请求失败返回的错误信息 |
| permission | object | 权限信息 |
| data | object | 请求返回的数据 |
data 字段说明
| 参数名称 | 参数类型 | 描述 |
|---|---|---|
| count | integer | 总数 |
| info | array | 返回结果 |
info 字段说明
| 参数名称 | 参数类型 | 描述 |
|---|---|---|
| id | int | 服务实例ID |
| name | string | 服务实例名称 |
| bk_biz_id | int | 业务ID |
| bk_module_id | int | 模块ID |
| bk_host_id | int | 主机ID |
| creator | string | 本条数据创建者 |
| modifier | string | 本条数据的最后修改人员 |
| create_time | string | 创建时间 |
| last_time | string | 更新时间 |
| bk_supplier_account | string | 开发商账号 |
info 中的每个元素对应存储模型 metadata.ServiceInstance,其中id是服务实例主键,name在响应中即服务实例名称(源码注释表明服务实例与主机、模块、进程模板存在绑定关系)。需要注意count是符合过滤条件的总数,而不是当前页返回条数,分页遍历时应以count与page.start + page.limit的推进配合使用。
底层实现:从路由到 MongoDB 查询
下面按请求处理顺序拆解该接口的完整调用链,便于排查"查不到数据"这类问题。
1. 路由注册与权限校验
接口路由在 proc_server 中注册为POST /findmany/proc/service_instance,绑定处理器SearchServiceInstancesInModule(service.go)。权限层面,serviceinstance.go 定义了findServiceInstancePattern:资源类型为meta.ProcessServiceInstance,动作FindMany,业务 id 从请求体bk_biz_id提取(DefaultBizIDGetter),因此调用方必须同时具备该业务的访问权限与list_service_instance的资源权限。
2. 处理器层:参数校验与查询选项组装
SearchServiceInstancesInModule 的处理逻辑:
- 反序列化入参后,若
bk_host_ids长度超过BKMaxPageSize(1000)直接报错; - 通过
input.Page.Validate(false)校验分页参数,非法时返回CCErrCommPageLimitIsExceeded; - 组装 ListServiceInstanceOption:始终带上
BusinessID;bk_module_id非 0 时转换为ModuleIDs: []int64{input.ModuleID};search_key、selectors、bk_host_ids原样透传。
3. coreservice 存储层:过滤条件的组装与执行
请求经 coreAPI 到达 coreservice 的 processOperation.ListServiceInstance,这是理解各参数底层行为的关键代码:
- 必选校验:
BusinessID == 0时返回CCErrCommParamsInvalid,对应文档中bk_biz_id的必选要求; - 租户隔离:过滤条件固定包含
bk_biz_id与bk_supplier_account(开发商账号,即响应中的bk_supplier_account字段),从源码结构看,服务实例数据是按供应商账号维度隔离的; - 主机过滤:
bk_host_ids映射为bk_host_id: {$in: [...]},是"这些主机上任意一个存在服务实例即命中"的语义; - 模块过滤:
bk_module_id同样走$in(内部以数组表达,支持单值); - 名称模糊搜索:
search_key被包装成正则.*<search_key>.*作用在name字段上($like),因此它是子串包含语义而非前缀匹配,且未转义正则元字符,调用方传特殊符号时应留意匹配范围可能比预期宽; - 标签过滤:先执行
Selectors.Validate()(operator 非法、values 数量不合规都会在此拦截并返回CCErrCommParamsInvalid),通过后ToMgoFilter()生成labels.<key>上的条件并与基础过滤合并; - 查询执行:先
Find(filter).Count()得到总数,再Fields(...).Sort(page.Sort).Start(page.Start).Limit(page.Limit).All()分页拉取实例,数据表为cc_ServiceInstance(tablenames.go),最终组装成MultipleServiceInstance{Count, Info}返回,对应响应中的data.count与data.info。
4. 内部复用与相关接口
同一个ListServiceInstance存储方法在仓库中被大量内部逻辑复用,从源码结构看,它不仅是开放 API 的后端,也是进程管理各功能的公共查询底座:
- 创建服务实例前先按模块查已存在的实例做去重排除(serviceinstance.go);
- 服务模板下发、进程模板差异计算等流程按
service_template_id+ 模块维度分页拉取实例(processinstance.go)。
与之相邻、可按场景替换使用的兄弟接口同样可在 bk_apigw_resources_bk-cmdb.yaml 中查到:
| 接口 | 后端路径 | 适用场景 |
|---|---|---|
list_service_instance_by_host | /api/v3/findmany/proc/service_instance/with_host | 已知单台主机,查其关联的服务实例 |
list_service_instance_by_set_template | /api/v3/findmany/proc/service/set_template/list_service_instance/biz/{bk_biz_id} | 按集群模板(set_template)反查服务实例 |
list_service_instance_detail | /api/v3/findmany/proc/service_instance/details | 需要联动进程实例关系等详情时 |
实践要点小结
- 必选与上限:
bk_biz_id必选;bk_host_ids单次最多 1000 个;page.limit最大 500,且start、limit均不能为负; - search_key 是模糊包含:底层为
.*<key>.*正则匹配实例名称,做精确查找时应结合模块/主机条件收敛; - selectors 只过滤 labels:过滤字段是
labels.<key>,key必须与服务实例上已存在的标签键一致,且各 operator 对values数量有严格校验; - 数据隔离:查询结果天然限定在
bk_biz_id与当前供应商账号范围内,跨业务、跨开发商的数据查不到属于预期行为; - 限流:网关侧默认 100 req/s 的令牌桶,大租户批量翻页建议按
count规划分页并在客户端侧做速率控制。
参考文件
- API 文档:list_service_instance、open API 网关定义、资源授权定义
- 路由与处理器:路由注册、SearchServiceInstancesInModule、权限配置
- 数据模型:ListServiceInstanceOption、GetServiceInstanceInModuleInput / ServiceInstance
- 存储实现:processOperation.ListServiceInstance、selector 过滤实现、分页校验
- 后端
- 企业应用
- 运维
【免费下载链接】bk-cmdb
蓝鲸智云配置平台(BlueKing CMDB)
相关推荐
蓝鲸配置平台 bk-cmdb 服务实例列表查询接口(list_service_instance)详解
蓝鲸配置平台 bk cmdb 服务实例列表查询接口(list_service_instance)详解 本指南基于蓝鲸智云配置平台(BlueKing CMDB,b
后端企业应用运维蓝鲸配置平台 bk-cmdb API 指南:按服务实例查询进程实例列表(list_process_instance)
蓝鲸配置平台 bk cmdb API 指南:按服务实例查询进程实例列表(list_process_instance) 导读 list_process_insta
后端企业应用运维bk-cmdb 服务分类列表查询接口 list_service_category 详解:从 API 网关到 Mongo 查询的完整链路
bk cmdb 服务分类列表查询接口 list_service_category 详解:从 API 网关到 Mongo 查询的完整链路 本篇基于蓝鲸智云配置平台
后端企业应用运维
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考