模块服务间调用协议
通过模块属性绑定 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 |
url | Runtime 网关中的目标服务方法基地址;不是目标 Hosted Backend 的部署地址 |
serviceId | 目标服务的完整 businessId |
token | 当前来源服务访问授权范围内目标方法的不透明凭据 |
url 和 token 都由 Runtime 根据当前属性绑定生成。调用方不得根据工作区、Runtime、域名或
businessId 拼接 url,也不得生成或依赖 token 格式。ServiceReferenceMap 和
ServiceReferenceList 中嵌套的引用会递归展开,容器结构保持不变。
这条链路不使用 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 都收到当前合并后的有效属性。后续回调可能带来
新的 url 或 token,调用方不能把旧值视为长期固定配置。
保存引用
生命周期 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 返回未授权时不循环重试,
应等待生命周期链路同步新引用并原子替换本地配置。
可执行的端到端步骤
- 在 Bundle
dependencies中声明并安装目标 Bundle 的精确版本。 - 在模块 A 当前版本中声明
xiaoxiangService的Interface属性,并安装模块 A。 - 回读模块 B 的完整
businessId、listManagedShops方法及paramDefinitions。 - 使用正式的
baijimu runtime app properties update命令,把模块 A 的xiaoxiangService设置为 指向模块 B 的ServiceReference;完整参数见 ServiceReference 页面,不要自行拼接平台接口路径。 - 在模块 A 的生命周期 Endpoint 接收
ON_CONFIG_UPDATE,校验并原子保存ExternalServiceReference,不要输出 token。 - 由模块 A 后端按上述 JSON
POST请求调用listManagedShops,检查 HTTP 状态和 CModel 响应。 - 修改或清除属性后,确认新的
ON_CONFIG_UPDATE已生效,旧引用不再用于新调用。
如果第 5 步没有收到引用,应检查属性更新操作结果、目标 businessId、属性定义、生命周期 Endpoint 和
Hook 支持范围;不能用硬编码地址或非公开凭据绕过交付链路。