- 后端
- 企业应用
- 运维
【免费下载链接】bk-cmdb
蓝鲸智云配置平台(BlueKing CMDB)
本篇文章以 update_process_instance.md(中文版见 update_process_instance.md)为骨架,结合 bk-cmdb 仓库中 proc_server、apimachinery、ac/parser、common/metadata 等源码与测试用例,完整讲解"批量更新进程实例"这一开放接口的调用方式、字段约束、底层实现与排障要点。读完你将掌握:如何构造合法的更新请求、进程实例与进程模板的关系如何影响可编辑字段、接口内部的事务与审计机制,以及常见错误的定位方法。
一、接口概览:用途、路径与权限
"批量更新进程信息"是 bk-cmdb 对外提供的进程实例(Process Instance)管理类接口,用于在不经过服务实例模板同步流程的情况下,直接对业务下已有的进程实例进行批量修改,典型场景包括:
- 一次性调整某业务多个主机上进程的启动命令、工作目录、启动用户、优先级等属性;
- 修正进程别名(
bk_process_name)、功能名(bk_func_name)等标识信息; - 批量变更进程的绑定信息(
bind_info,即 IP/端口/协议),作为后续 GSE 进程托管配置的数据来源。
该接口的核心定位与相关约束如下:
| 项 | 说明 |
|---|---|
| 开放网关资源路径 | PUT /api/v3/update/proc/process_instance(见 bk_apigw_resources_bk-cmdb.yaml 中的update_process_instance定义) |
| 内部服务路径 | proc_server 注册的PUT /update/proc/process_instance(见 service.go) |
| 所需权限 | 服务实例编辑权限 |
| 单次最大处理数 | processes数组最多 100 条 |
| 幂等性 | 按bk_process_id精确匹配更新,未指定的字段保持不变 |
权限说明:在权限解析层,该接口被注册为updateProcessInstances,资源类型为ProcessServiceInstance(服务实例),动作(Action)为meta.Update,业务 ID 通过DefaultBizIDGetter从请求参数中提取(见 processinstance.go)。也就是说,调用者必须在蓝鲸权限中心拥有对应服务实例的编辑(update)权限,否则请求会被拒绝并返回权限信息。
二、请求参数详解
1. 顶层参数
| 参数名称 | 参数类型 | 必选 | 描述 |
|---|---|---|---|
| processes | array | 是 | 进程信息数组,最大值为 100,对应源码中BKMaxUpdateOrCreatePageSize = 100的上限校验(见 definitions.go) |
| bk_biz_id | int | 是 | 业务 ID,更新请求必须显式声明所属业务 |
在 Go 服务端,顶层入参对应UpdateRawProcessInstanceInput结构体(见 process.go):
type UpdateRawProcessInstanceInput struct { BizID int64 `json:"bk_biz_id"` Processes []Process `json:"-"` Raw []map[string]interface{} `json:"processes"` }注意:processes数组的每个元素是一个开放结构(map[string]interface{}),而不是强类型对象,因此字段可按需传、可部分更新。
2. processes 字段说明(完整表)
下表完整继承自原文档,并补充了字段取值范围(来源于进程模型的属性定义 objAttDescData.go):
| 参数名称 | 参数类型 | 必选 | 描述 |
|---|---|---|---|
| process_template_id | int | 否 | 进程模板 ID,当进程实例由模板创建时用于定位模板 |
| auto_start | bool | 否 | 是否自动拉起 |
| auto_time_gap | int | 否 | 拉起间隔(单位秒,属性约束 1~10000,见 update_process_property.go) |
| bk_biz_id | int | 否 | 业务 ID(更新时以顶层 bk_biz_id 为准) |
| bk_func_id | string | 否 | 功能 ID(GSE Kit 功能标识) |
| bk_func_name | string | 否 | 进程名称(功能名称) |
| bk_process_id | int | 否 | 进程 ID,实际更新时的定位键,必须提供且有效 |
| bk_process_name | string | 否 | 进程别名 |
| bk_supplier_account | string | 否 | 开发商账号 |
| face_stop_cmd | string | 否 | 强制停止命令 |
| pid_file | string | 否 | PID 文件路径 |
| priority | int | 否 | 启动优先级(属性约束 1~100) |
| proc_num | int | 否 | 启动数量(属性约束 1~1000000) |
| reload_cmd | string | 否 | 进程重载命令 |
| restart_cmd | string | 否 | 重启命令 |
| start_cmd | string | 否 | 启动命令 |
| stop_cmd | string | 否 | 停止命令 |
| timeout | int | 否 | 操作超时时长(属性约束 1~1000000) |
| user | string | 否 | 启动用户 |
| work_path | string | 否 | 工作路径 |
| process_info | object | 否 | 进程信息(嵌套对象形式,可携带 bind_info 等复合结构) |
| bind_info | array | 否 | 进程绑定信息,元素含enable、ip、port、protocol、template_row_id等 |
关于"必选"字段的说明:表格中bk_process_id标记为"否",仅表示它作为进程属性之一并非每次都必须变更;但更新操作必须以bk_process_id作为目标定位键。服务端在 updateProcessInstances 中会校验process.ProcessID == 0直接返回参数错误(CCErrCommParamsInvalid),并通过进程-服务实例关系表确认这些进程真实存在于该业务下,不存在则报CCErrCommParamsIsInvalid并给出缺失的进程 ID 列表。
3. bind_info 绑定信息的校验规则
bind_info是进程实例较复杂的复合字段,服务端在validateProcessInstance(见 processinstance.go)中对每个绑定项执行三重校验,源码可佐证:
- IP:必须匹配 IPv4 格式正则
^((1?\d{1,2}|2[0-4]\d|25[0-5])[.]){3}(1?\d{1,2}|2[0-4]\d|25[0-5])$,为空则报CCErrCommParamsNeedSet,格式非法报CCErrCommParamsInvalid; - 端口:通过
PropertyPortValue.Validate()(见 process.go),支持逗号分隔多端口、start-end区间写法,要求区间起点不大于终点、且各端口区间互不重叠; - 协议:
ProtocolType枚举校验(见 process.go),取值1=TCP、2=UDP、3=TCP6、4=UDP6,同时通过ValidateBindIPMatchProtocol校验绑定方式与协议族匹配(IPv4 绑定不能配 TCP6/UDP6)。
三、调用示例(可直接复制验证)
以下请求完整继承自原文档,为便于对照,已在行内补充关键字段注释:
{ "bk_biz_id": 1, "processes": [ { "bk_process_id": 43, "description": "", "start_cmd": "", "restart_cmd": "", "pid_file": "", "auto_start": false, "timeout": 30, "auto_time_gap": 60, "reload_cmd": "", "bk_func_name": "java", "work_path": "/data/bkee", "stop_cmd": "", "face_stop_cmd": "", "bk_process_name": "job_java", "user": "", "proc_num": 1, "priority": 1, "bk_biz_id": 2, "bk_func_id": "", "bind_info": [ { "enable": false, "ip": "127.0.0.1", "port": "100", "protocol": "1", "template_row_id": 1 } ] } ] }几点实战提醒:
- 示例中
processes[0].bk_biz_id为 2 与顶层bk_biz_id: 1不一致,服务端以顶层业务 ID 为准进行数据归属校验,条目内的bk_biz_id会被强制改写(见 processinstance.goprocess.BusinessID = bizID); - 不打算修改的字段可以不出现在条目中,服务端按
bk_process_id读取旧值并仅对传入字段做覆盖; - 若想把某字段清空,可在条目中显式传入
null,服务端会提取这些"置空字段"并在更新数据中将其设为nil(见 processinstance.go),这适用于清空pid_file、user等可编辑文本属性。
四、响应示例与参数说明
{ "result": true, "code": 0, "message": "success", "permission": null, "data": [43] }响应参数完整说明如下(继承自原文档):
| 参数名称 | 参数类型 | 描述 |
|---|---|---|
| result | bool | 请求成功与否。true:请求成功;false:请求失败 |
| code | int | 错误编码。0 表示 success,>0 表示失败错误 |
| message | string | 请求失败返回的错误信息 |
| permission | object | 权限信息 |
| data | object | 请求返回的数据 |
其中data是本次成功更新的进程 ID 数组([]int64),即各条目中bk_process_id的去重集合,由服务端ctx.RespEntity(result)返回(见 processinstance.go)。如果你的调用方需要记录"哪些进程被更新",直接取用该数组即可,无需再次查询。
五、源码级实现原理与调用链
从调用方视角到数据落库,该接口的完整链路如下:
- 网关层:蓝鲸 API 网关将
PUT /api/v3/update/proc/process_instance转发至 proc_server 内部路径(网关资源定义见 bk_apigw_resources_bk-cmdb.yaml); - 路由注册:proc_server 在 service.go 中注册
PUT /update/proc/process_instance -> UpdateProcessInstances; - 权限校验:ac/parser 按 processinstance.go 的规则做服务实例 update 权限鉴权;
- 服务层处理:
UpdateProcessInstances(见 processinstance.go)先校验processes非空且不超过 100 条,再生成更新前审计快照,随后在数据库事务中执行updateProcessInstances并保存审计日志; - 并发更新:内部对每个进程 ID 并发执行更新,通过容量为 10 的 channel 信号量(
pipeline := make(chan bool, 10))控制并发度(见 processinstance.go),任一条失败都会记录并整体返回首个错误; - 逻辑层落库:
Logic.UpdateProcessInstance(见 processinstance.go)删除bk_supplier_account后,构造UpdateOption{Data, Condition: {bk_process_id: procID}}调用 coreservice 的UpdateInstance,最终写入 MongoDB 的process集合; - 客户端封装:调用方(如测试或上层模块)可通过 apimachinery 客户端
UpdateProcessInstance(见 instance.go)发起请求,内部使用 HTTP PUT 访问/update/proc/process_instance。
值得关注的是审计日志:更新前先通过generateUpdateProcessAudit(见 processinstance.go)读取进程更新前的快照、进程-服务实例关系与变更字段集合,生成AuditUpdate类型日志,与更新动作在同一事务中提交,从而保证"谁在何时改了什么、改前改后值"均可追溯。
六、模板进程与原生进程:可编辑字段的差异
这是使用本接口最容易踩坑的点。bk-cmdb 中进程实例分为两类来源:
- 模板进程:由服务模板/进程模板同步创建(
ProcessTemplateID != ServiceTemplateIDNotSet); - 原生进程:直接在服务实例下手动创建(
ProcessTemplateID == ServiceTemplateIDNotSet)。
updateProcessInstances会根据进程-服务实例关系中的ProcessTemplateID走两条不同分支(见 processinstance.go):
- 原生进程:允许更新全部进程属性,仅剔除
bk_process_id、bk_supplier_account、create_time、last_time等系统字段; - 模板进程:必须通过
processTemplate.ExtractInstanceUpdateData提取模板允许编辑的字段做增量更新,模板不允许的字段会被忽略;置空字段也需经processTemplate.GetEditableFields过滤,防止把模板锁定的字段清掉。
因此,对模板进程调用本接口修改模板管控的属性(如start_cmd)通常不会生效,正确做法是改进程模板并执行服务实例同步(sync系列接口),仓库错误码中也有对应的保护逻辑:错误1108035 CCErrProcEditProcessInstanceCreateByTemplateForbidden(见 errInfo.go)即表示"由模板创建的进程实例不允许直接编辑"。
七、常见错误与排障
结合源码与测试用例(no_service_template_test.go),总结以下高频失败场景:
| 错误现象 | 触发原因 | 定位方法 |
|---|---|---|
processes为空 | 请求体缺少processes或为空数组 | 服务端直接返回参数错误,检查请求体 |
| 超过 100 条 | 数组长度 >BKMaxUpdateOrCreatePageSize | 分批调用(每批 ≤100) |
bk_process_id缺失/为 0 | 条目内未提供有效进程 ID | 该字段是更新定位键,必须携带 |
| 进程不存在 | bk_process_id不属于该业务 | 服务端报CCErrCommParamsIsInvalid并列出缺失 ID |
| 更新同名进程失败 | 进程别名/功能名+启动参数与同模块其他进程冲突 | 见测试"update process instance with same name"用例 |
| 名称/功能名为空 | bk_process_name或bk_func_name传了空字符串 | 服务端校验长度非空(validateProcessInstance) |
| bind_info 校验失败 | IP 格式错误、端口区间非法/重叠、协议枚举非法 | 参照上文"bind_info 校验规则"逐项核对 |
| 模板进程编辑被拒 | 对模板创建的进程实例直接改模板字段 | 错误 1108035,改走模板同步流程 |
| 业务 ID 不一致 | 条目内bk_biz_id与顶层不一致 | 顶层为准,条目内字段会被覆盖 |
另外注意:测试用例(no_service_template_test.go)还展示了同一路径族下的姊妹接口UpdateProcessInstancesByIDs(PUT /update/proc/process_instance/by_ids),它接收process_ids+update_data结构,适合"对同一批进程统一改同一批属性"的场景,与本接口"逐条精细更新"形成互补,可按需选用。
八、小结
批量更新进程实例(update_process_instance)是 bk-cmdb 进程实例管理体系中"脱离模板、按 ID 直改"的高频接口:它支持最多 100 条进程的批量局部更新、按bk_process_id精确定位、内置字段置空与 bind_info 校验、事务化提交与更新审计,同时对模板进程设置了可编辑字段边界。掌握本文的参数约束与源码行为,即可在实际业务中安全、高效地完成进程属性的批量维护。
- 后端
- 企业应用
- 运维
【免费下载链接】bk-cmdb
蓝鲸智云配置平台(BlueKing CMDB)
相关推荐
蓝鲸配置平台(bk-cmdb)批量更新 Kubernetes Workload 接口实战指南
蓝鲸配置平台(bk cmdb)批量更新 Kubernetes Workload 接口实战指南 导读 本文围绕 bk cmdb(蓝鲸智云配置平台)API 网关提供
后端企业应用运维Elementor 编辑器通知系统:@elementor/editor-notifications 包版本演进与实现全解析
Elementor 编辑器通知系统:@elementor/editor notifications 包版本演进与实现全解析 本文以 @elementor/edi
后端企业应用运维Matter 项目 Tracing 子系统详解:运行时可配置的追踪与指标日志架构
Matter 项目 Tracing 子系统详解:运行时可配置的追踪与指标日志架构 Matter(原 Project CHIP)在 src/tracing htt
后端企业应用运维
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考