news 2026/10/12 3:31:33

蓝鲸配置平台 bk-cmdb 主机锁定接口 add_host_lock 实战指南:参数、幂等语义与底层实现

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
蓝鲸配置平台 bk-cmdb 主机锁定接口 add_host_lock 实战指南:参数、幂等语义与底层实现
  • 后端
  • 企业应用
  • 运维

【免费下载链接】bk-cmdb

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

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

本文以蓝鲸智云配置平台(BlueKing CMDB,bk-cmdb)开放 API 文档docs/apidoc/apigw/open/en/add_host_lock.md为核心,系统讲解「锁定主机(Lock hosts)」接口的调用方式、参数约束、响应格式,并结合开源仓库源码剖析其幂等实现、事务处理与权限校验链路。读者读完可准确调用该接口实现主机批量锁定,并理解锁定数据在cc_HostLock表中的存储形态,为上层运维流程(如变更保护、故障隔离)提供可靠依据。

一、接口功能与适用场景

锁定主机是 CMDB 对主机实例提供的一种保护性操作:调用方传入一批主机 ID,即可为这些主机添加"锁定"标记。被锁定的主机在业务层面通常意味着"禁止变更、禁止回收、暂停操作",常用于:

  • 变更窗口期的主机保护,防止自动化流程误操作;
  • 故障主机隔离,标记后避免被纳入正常调度;
  • 资源生命周期管理,锁定待下线/待回收资源。

该接口的官方定义(源自 add_host_lock.md)明确指出:

Lock hosts based on a list of host IDs. For newly added hosts, if the host has already been locked, it will also indicate successful locking。

即:接口按主机 ID 列表锁定主机;对于新加入列表的主机,即使其此前已经被锁定,接口依然返回锁定成功——这是理解该接口幂等语义的关键(详见下文第六节)。

二、接口基本信息

项目内容
接口名称add_host_lock(锁定主机)
引入版本v3.8.6
所需权限业务主机编辑权限(Business host editing permission)
请求方式POST
请求路径/api/v3/host/lock

从源码看,该路径在 host_server 服务初始化 中注册:

utility.AddHandler(rest.Action{Verb: http.MethodPost, Path: "/host/lock", Handler: s.LockHost}) utility.AddHandler(rest.Action{Verb: http.MethodDelete, Path: "/host/lock", Handler: s.UnlockHost}) utility.AddHandler(rest.Action{Verb: http.MethodPost, Path: "/host/lock/search", Handler: s.QueryHostLock})

权限控制方面,ac/parser/host.go 中针对/api/v3/host/lock(POST 锁定、DELETE 解锁)与/api/v3/host/lock/search(查询)均配置了主机实例资源的鉴权过滤,而 service/hostlock.go 中通过AuthorizeByHostsIDs校验「编辑」动作权限,无权限时返回ac.NoAuthorizeError及无权限提示信息,对应文档所述的"业务主机编辑权限"。

三、请求参数详解

3.1 参数总览

名称类型必填说明
id_listint 数组是主机 ID 列表(Host IDs)

3.2 参数约束(源码级验证)

请求体在服务端被反序列化为metadata.HostLockRequest,其定义见 src/common/metadata/hostlock.go:

type HostLockRequest struct { IDS []int64 `json:"id_list"` }

服务入口 LockHost 对参数做了第一层校验:

input := &metadata.HostLockRequest{} if err := ctx.DecodeInto(&input); nil != err { ctx.RespAutoError(err) return } if 0 == len(input.IDS) { blog.Errorf("lock host, id_list is empty,input:%+v, rid:%s", input, ctx.Kit.Rid) ctx.RespAutoError(ctx.Kit.CCError.Errorf(common.CCErrCommParamsNeedSet, "id_list")) return }

由此可确认两个硬性约束:

  1. id_list不能为空:空数组会直接返回参数错误(错误码CCErrCommParamsNeedSet,提示字段为id_list);
  2. 元素类型为整数(int64):非整数会导致 JSON 反序列化失败,同样走RespAutoError分支返回错误;
  3. 重复 ID 会被自动去重:核心实现中首先执行input.IDS = util.IntArrayUnique(input.IDS)(见 core/host/lock.go),因此传入[1, 1, 2]与[1, 2]效果等价。

四、请求示例

按照开放 API 文档,请求体为一个包含id_list字段的 JSON 对象:

{ "id_list":[1, 2, 3] }

实际调用(POST):

POST /api/v3/host/lock Content-Type: application/json { "id_list":[1, 2, 3] }

五、响应示例与响应参数

5.1 响应示例

成功响应(与文档一致):

{ "result": true, "code": 0, "message": "success", "data": null, "permission": null }

5.2 响应参数说明

名称类型说明
resultbool请求是否成功。true:成功;false:失败
codeint错误码。0 表示成功,>0 表示失败的具体错误码
messagestring请求失败时返回的错误信息
dataobject请求返回的数据(本接口成功时为 null)
permissionobject权限信息

需要注意:文档中的响应示例将data置为null,这与服务端实现一致——LockHost 服务处理函数 在成功时调用ctx.RespEntity(nil)返回空数据;核心层 coreservice 的 LockHost 同样以ctx.RespEntity(nil)结束,因此data字段为空是正常预期,业务方无需解析该字段。

若请求失败,code将返回非 0 错误码,message携带具体错误描述。常见的失败场景包括:id_list为空、主机 ID 不存在(见第六节)、鉴权失败(无业务主机编辑权限)等。

六、底层实现原理:幂等、存在性校验与事务

6.1 调用链全景

锁定主机请求在微服务架构中经历三层调用:

  1. host_server 服务层(service/hostlock.go):解析参数、校验权限、开启事务;
  2. host_server 逻辑层(logics/hostlock.go):通过CoreService().Host().LockHost发起对 coreservice 的 HTTP 调用;
  3. coreservice 核心层(core/host/lock.go):直接操作 MongoDB,完成实际的锁定写入。

其中逻辑层封装如下:

func (lgc *Logics) LockHost(kit *rest.Kit, input *metadata.HostLockRequest) errors.CCError { hostLockResult, err := lgc.CoreAPI.CoreService().Host().LockHost(kit.Ctx, kit.Header, input) if nil != err { ... return kit.CCError.Error(common.CCErrCommHTTPDoRequestFailed) } if !hostLockResult.Result { ... return kit.CCError.New(hostLockResult.Code, hostLockResult.ErrMsg) } return nil }

6.2 幂等语义:已锁定主机重复锁定仍返回成功

文档强调"if the host has already been locked, it will also indicate successful locking",其实现位于 core/host/lock.go:核心层先按主机 ID 查询cc_HostLock表中是否已存在锁定记录,仅对未锁定的主机追加写入:

for _, id := range input.IDS { conds := mapstr.MapStr{ common.BKHostIDField: id, } conds = util.SetQueryOwner(conds, kit.SupplierAccount) cnt, err := mongodb.Client().Table(common.BKTableNameHostLock).Find(conds).Count(kit.Ctx) ... if 0 == cnt { insertDataArr = append(insertDataArr, metadata.HostLockData{ User: user, ID: id, CreateTime: ts, OwnerID: httpheader.GetSupplierAccount(kit.Header), }) } }

也就是说:对已锁定主机,跳过写入但不报错,接口整体仍返回成功,实现"重复锁定幂等"。

6.3 主机存在性校验

在写入锁定之前,核心层会先校验主机是否真实存在(core/host/lock.go):

condition := mapstr.MapStr{ common.BKHostIDField: mapstr.MapStr{common.BKDBIN: input.IDS}, } condition = util.SetQueryOwner(condition, kit.SupplierAccount) hostInfos := make([]metadata.HostMapStr, 0) err := mongodb.Client().Table(common.BKTableNameBaseHost).Find(condition). Fields(common.BKHostIDField).Limit(limit).All(kit.Ctx, &hostInfos) ... diffID := diffHostLockID(input.IDS, hostInfos, kit.Rid) if 0 != len(diffID) { blog.Errorf("lock host, not found, id: %+v, rid: %s", diffID, kit.Rid) return kit.CCError.Errorf(common.CCErrCommParamsIsInvalid, fmt.Sprintf(" id_list %v", diffID)) }

diffHostLockID(同文件 L121-L139)将请求 ID 与基础主机表cc_HostBase中实际存在的主机 ID 求差集:只要存在任意一个主机 ID 在 CMDB 中不存在,整个请求即失败,并在错误信息中明确指出不存在的主机 ID。因此调用方需确保传入的 ID 均为主机表内有效 ID。

6.4 事务保证

服务层将核心写入包在事务中执行(service/hostlock.go):

txnErr := s.Engine.CoreAPI.CoreService().Txn().AutoRunTxn(ctx.Kit.Ctx, ctx.Kit.Header, func() error { err := s.Logic.LockHost(ctx.Kit, input) if nil != err { return err } return nil }) if txnErr != nil { ctx.RespAutoError(txnErr) return } ctx.RespEntity(nil)

任何一步失败都会触发事务回滚,保证"校验—写入"过程的一致性。

七、锁定数据的存储结构

锁定记录存储在 MongoDB 集合cc_HostLock中,表名常量定义见 src/common/tablenames.go:

BKTableNameHostLock = "cc_HostLock"

单条锁定记录(metadata.HostLockData,见 src/common/metadata/hostlock.go)包含四个字段:

字段(bson/json)类型说明
bk_host_idint64被锁定主机 ID
bk_userstring发起锁定操作的用户
create_timetime.Time锁定创建时间(UTC)
bk_supplier_accountstring供应商账号(多租户隔离字段)

存储层写入时(core/host/lock.go),用户信息取自请求 Header(httpheader.GetUser),时间统一取time.Now().UTC(),并以SetQueryOwner/SetModOwner注入供应商账号,实现多租户数据隔离。

该表由升级脚本自动创建并维护索引。升级代码见 upgrader/y3.9.202010211805/add_host_lock_table.go:若表不存在则创建,并为bk_host_id建立名为bk_host_id_1的非唯一索引。索引的规范化注册见 src/common/index/collections/hostlock.go,方便按主机 ID 快速查询锁定状态。

八、配套接口:解锁与锁定查询

该接口同属主机锁定 API 组,配套两个接口共同构成完整的锁定管理能力(路由注册见 service_initfunc.go):

操作方法路径服务处理函数
锁定主机(本接口)POST/api/v3/host/lockLockHost
解锁主机DELETE/api/v3/host/lockUnlockHost
查询主机锁定状态POST/api/v3/host/lock/searchQueryHostLock
  • 解锁:同样接收id_list参数,从cc_HostLock表批量删除锁定记录(core/host/lock.go),权限校验与事务机制与锁定一致;
  • 查询:返回每个主机 ID 的锁定状态(map[int64]bool),逻辑层 logics/hostlock.go 将未锁定主机置为false、已锁定主机置为true。

这三者共享同一套鉴权(业务主机编辑权限)与数据模型(cc_HostLock),建议联动使用。

九、调用注意事项

  1. 必填且非空:id_list为必填字段,空数组会返回参数校验错误;
  2. ID 必须真实存在:任一主机 ID 不存在即整体失败,且错误信息会列出不存在的 ID;建议调用前先通过主机查询接口确认 ID 有效性;
  3. 幂等友好:重复锁定已锁定主机不会报错,可安全重试;
  4. 权限前置:调用方需具备对应业务的主机编辑权限,无权限时返回permission信息(ac.NoAuthorizeError);
  5. 版本门槛:该接口自 v3.8.6 起提供,低版本环境不适用;
  6. 多租户隔离:锁定记录按bk_supplier_account隔离,跨供应商账号的 ID 校验与写入互不影响。

综合来看,add_host_lock 是 CMDB 主机保护机制的基础 API,其幂等写入、存在性校验、事务封装与多租户隔离的实现均可在 src/scene_server/host_server/service/hostlock.go、src/source_controller/coreservice/core/host/lock.go 与 src/common/metadata/hostlock.go 中追溯验证,是理解 CMDB 主机域写入类接口设计范式的良好范例。

  • 后端
  • 企业应用
  • 运维

【免费下载链接】bk-cmdb

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

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

相关推荐

上一篇:Hudi Notebooks 实战指南:基于 Docker Compose 搭建 Spark + Hudi + MinIO + Hive Metastore 数据湖开发环境
下一篇:缠论分析终极指南:5分钟掌握ChanlunX通达信插件免费开源方案

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

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

React 搜索框闪烁问题全解析:竞态条件、防抖与请求生命周期管理

2026年了,React 的数据获取链路早就被各种方案武装到了牙齿:路由级有加载态编排,服务端有流式渲染,请求库有缓存和重试,并发特性连渲染优先级都帮你排好了队。可真到了生产环境,用户对一个系统最直接的一句…

作者头像 李华
网站建设 2026/10/12 3:29:59

AI快速进步但不会通用超级智能:技术约束与工程实践判断

1. 为什么这个判断值得认真对待1.1 一个反直觉但越来越主流的观点AI 会快速进步,但不会走向通用超级智能——这个判断乍一听有点矛盾。既然进步快,为什么不会走到那一步?但如果你真的在一线做模型训练、做产品落地、做推理优化,你…

作者头像 李华
网站建设 2026/10/12 3:29:44

Hive性能优化与执行原理深度解析

1. 这不是背题手册,而是一份Hive生产环境“踩坑实录”你打开这份文档时,大概率正面临两类场景:要么是明天就要进面试间,手心冒汗地翻着零散笔记,对着“Hive和传统数据库区别”这种题反复默念;要么是刚在数仓…

作者头像 李华
网站建设 2026/10/12 3:28:57

知识蒸馏小模型72小时工程落地全链路实测

1. 项目概述:为什么一个“小模型发布72小时”的测试值得专门写一篇长文?“知识蒸馏小模型发布72小时,我替你试完了”——这个标题不是营销噱头,而是我过去三天的真实工作日志。它背后藏着当前AI落地最现实的矛盾:大模型…

作者头像 李华
网站建设 2026/10/12 3:28:21

Cortex 多租户认证与授权实战:基于 X-Scope-OrgID 的租户隔离方案

可观测性时序数据库后端指标监控 【免费下载链接】cortex A horizontally scalable, highly available, multi-tenant, long term Prometheus. 项目地址: https://gitcode.com/gh_mirrors/cortex6/cortex 点击查看 免费下载 本篇技术指南围绕 Cortex 的多租户认证与…

作者头像 李华
网站建设 2026/10/12 3:27:31

Chainer 实现 DCGAN 完整指南:从 GAN 原理到 CIFAR-10 图像生成

深度学习机器学习 【免费下载链接】chainer A flexible framework of neural networks for deep learning 项目地址: https://gitcode.com/gh_mirrors/ch/chainer 点击查看 免费下载 本教程基于 Chainer 官方仓库中的 DCGAN 示例(examples/dcgan 目录&a…

作者头像 李华