百积木文档
开发指南平台应用、模块与 Bundle 开发模块开发

模块服务间调用协议

通过模块属性绑定 ServiceReference,由生命周期回调接收访问引用并调用同一 Runtime 中的目标模块方法。

模块 A 拥有独立运行的 HTTP 后端,需要调用同一 Runtime 中模块 B 的公开方法时,使用完整的 ServiceReference 链路:模块 A 声明 Interface 属性,把该属性设置为指向模块 B 的 ServiceReference;Runtime 自动生成访问关系和 token,再通过生命周期回调把目标 URL 和 token 交付给 模块 A 的外部后端。

生命周期回调负责交付引用

生命周期 Endpoint 在部署和配置阶段接收平台展开的运行时引用,并把它同步到模块 A 后端的敏感配置。 后续业务调用由模块 A 后端发起,目标方法通过 Runtime 网关执行。

完整调用链

目标 Bundle 通过 dependencies 先安装
  -> 模块 A 声明 Interface 属性
  -> 模块 A 的属性设置为 ServiceReference(B)
  -> Runtime 自动生成来源服务到目标服务的访问关系和 token
  -> BEFORE_DEPLOY 或 ON_CONFIG_UPDATE 交付 ExternalServiceReference
  -> 模块 A 后端原子保存敏感运行配置
  -> 模块 A 后端通过 Runtime 网关调用 B 的目标方法
  -> Runtime 校验来源服务、目标服务和允许的方法
  -> 模块 B 执行方法并返回统一响应

Bundle dependencies 只保证目标 Bundle 进入安装闭包和先于调用 Bundle 安装,不选择目标服务,也不设置 调用模块属性。设置属性就是绑定,没有另一套需要开发者调用的授权接口。声明、默认绑定、安装后修改及 CLI 示例见 ServiceReference 声明、绑定与运行时交付

生命周期请求中的运行时引用

模块属性中的逻辑值:

{
  "@type": "ServiceReference",
  "serviceId": "<targetBusinessId>"
}

会在生命周期请求的 properties 中展开为:

{
  "@type": "ExternalServiceReference",
  "url": "https://<runtime-service-base>/<targetBusinessId>",
  "serviceId": "<targetBusinessId>",
  "token": "<opaque-reference-token>"
}
字段语义
@type固定为 ExternalServiceReference
urlRuntime 网关中的目标服务方法基地址;不是目标 Hosted Backend 的部署地址
serviceId目标服务的完整 businessId
token当前来源服务访问授权范围内目标方法的不透明凭据

urltoken 都由 Runtime 根据当前属性绑定生成。调用方不得根据工作区、Runtime、域名或 businessId 拼接 url,也不得生成或依赖 token 格式。ServiceReferenceMapServiceReferenceList 中嵌套的引用会递归展开,容器结构保持不变。

这条链路不使用 HTTP 方法属性映射。HTTP 模块不能通过 position: "property" 接收引用。

Hook 中的处理

平台在实际发起每个标准 Hook 前都会展开当前引用。外部后端应按 Hook 收敛自己的敏感配置:

Hook外部后端动作
BEFORE_DEPLOY校验字段,并在返回成功前原子保存最新整组引用
AFTER_DEPLOY确认运行实例已加载最新引用,不创建第二份引用
ON_CONFIG_UPDATE原子替换最新整组引用,不能只按字段补丁更新
BEFORE_STOP停止新的后台调用,并按本服务策略结束进行中的调用
BEFORE_DETACH停止使用当前 Runtime 的引用并删除本地副本
BEFORE_DELETE清除引用及该绑定产生的本地敏感配置

安装时,Runtime 在建立引用访问关系后才调用 BEFORE_DEPLOY;安装完成后通过正式模块属性命令修改绑定时, Runtime 更新访问关系后调用 ON_CONFIG_UPDATE。两个 Hook 都收到当前合并后的有效属性。后续回调可能带来 新的 urltoken,调用方不能把旧值视为长期固定配置。

保存引用

生命周期 Endpoint 可以与模块 A 后端位于同一服务,也可以把引用同步到模块 A 后端自己的受控配置系统。 无论采用哪种方式,都必须:

  • 按整组值原子替换,不做字段级拼接。
  • 只在服务端敏感配置中保存 token,不写入源码、Bundle、前端状态或客户端配置。
  • 不在日志、错误、指标和链路追踪中记录完整 properties、Authorization 值或 token。
  • 服务停止、解绑或删除后立即停止使用并清除本地引用。

调用具体方法

例如代码中的逻辑调用是:

xiaoxiangService.listManagedShops(params)

外部后端使用生命周期回调收到的引用,把接口方法转换为以下 HTTP 请求:

POST {reference.url}/listManagedShops
Authorization: Bearer {reference.token}
Content-Type: application/json

请求体顶层字段与目标方法当前 paramDefinitions 一一对应。目标方法声明一个名为 params 的参数时:

{
  "params": {
    "status": "ACTIVE"
  }
}

平台当前不生成语言级代理对象;xiaoxiangService.listManagedShops(params) 表示上面的标准 HTTP 调用, 不是另一个未发布的 SDK。调用方应从 Runtime 回读目标方法定义,不能自行复制一份可能漂移的方法签名。 响应按 CModel 错误模型 处理。

调用方不得解析逻辑 ServiceReference,不直接请求目标 Hosted Backend 的 Controller 或部署地址。

上下文、权限和重试

引用 token 证明当前来源服务被允许调用当前目标服务的方法,但不自动代表某个最终用户:

  • Runtime、工作区和来源服务身份由引用调用链确定,不从普通业务参数中接受同名字段。
  • 生命周期请求中的操作 userId 不能保存后用于业务调用。
  • 普通请求体或自定义头中的用户编号不是平台已验证的用户上下文。
  • 目标方法需要最终用户权限而可信用户上下文缺失时,必须拒绝,不能回退到安装用户或固定管理员。

调用方先检查 HTTP 状态,再检查 CModel errorCode。连接中断或超时时执行结果可能未知;只有目标方法 本身声明幂等,或请求携带该方法规定的幂等键时,才允许自动重试。旧 token 返回未授权时不循环重试, 应等待生命周期链路同步新引用并原子替换本地配置。

可执行的端到端步骤

  1. 在 Bundle dependencies 中声明并安装目标 Bundle 的精确版本。
  2. 在模块 A 当前版本中声明 xiaoxiangServiceInterface 属性,并安装模块 A。
  3. 回读模块 B 的完整 businessIdlistManagedShops 方法及 paramDefinitions
  4. 使用正式的 baijimu runtime app properties update 命令,把模块 A 的 xiaoxiangService 设置为 指向模块 B 的 ServiceReference;完整参数见 ServiceReference 页面,不要自行拼接平台接口路径。
  5. 在模块 A 的生命周期 Endpoint 接收 ON_CONFIG_UPDATE,校验并原子保存 ExternalServiceReference,不要输出 token。
  6. 由模块 A 后端按上述 JSON POST 请求调用 listManagedShops,检查 HTTP 状态和 CModel 响应。
  7. 修改或清除属性后,确认新的 ON_CONFIG_UPDATE 已生效,旧引用不再用于新调用。

如果第 5 步没有收到引用,应检查属性更新操作结果、目标 businessId、属性定义、生命周期 Endpoint 和 Hook 支持范围;不能用硬编码地址或非公开凭据绕过交付链路。

本页内容