Dubbo Admin 泛化调用链路
记录 Dubbo Admin 从服务元数据和目标实例发起泛化调用的后端链路。
Dubbo Admin 泛化调用链路
[!abstract] 这次 PR 的核心不是单独新增 4 个接口,而是补齐 Dubbo Admin 的服务调试后端链路。它从
ServiceProviderMetadata出发,把“方法语义”和“实例调用目标”汇合到/service/generic/invoke。
项目背景
服务身份是 serviceName + version + group。方法和类型信息来自 ServiceProviderMetadata,用户选择 Instance,实际调用目标由对应的 RPCInstance 提供。实体关系见 Dubbo Admin 应用与实例模型。
2. PR 总览
这次 PR 在后端侧补齐了一条服务调试链路:先解析服务的方法和类型信息,再定位可选实例,最后把方法和实例汇合成一次真实的 Dubbo 泛化调用。
服务上下文
|
v
ServiceProviderMetadata
|
+----> 方法信息 -------------------+
| |
+----> providerAppName -> Instance -> RPCInstance
|
v
/service/generic/invoke
|
v
rawResult + elapsedMs
3. 接口设计
GET /service/methods
输入:mesh + serviceName + version + group
处理:查询 ServiceProviderMetadata,提取 methods,并按 methodName + signature 去重。
输出:方法列表,核心是 methodName、parameterTypes 和 signature。
GET /service/method/detail
输入:服务上下文,再加上 methodName + signature。
处理:精确定位目标方法,提取参数、返回值以及关联类型定义。
输出:方法详情与类型图。
GET /service/provider-instances
输入:mesh + serviceName + version + group
处理:先从 ServiceProviderMetadata 提取 providerAppName,再按 app 查询 Instance。
输出:控制台实例列表。这里返回的是 Instance,不是直接暴露底层 RPC endpoint。
POST /service/generic/invoke
输入:方法、实例、参数、超时、attachments。
处理:方法解析、参数解码、实例映射、泛化调用。
输出:rawResult + elapsedMs。
4. 泛化调用链路设计
这是这次 PR 最核心的接口。它真正把“方法语义”和“实例目标”汇合成一次调用。
请求体
(mesh, serviceName, version, group,
methodName, signature, instanceName,
args, timeoutMs, attachments)
|
v
1. 请求校验
|
v
2. 解析服务方法
ServiceProviderMetadata
|
v
3. 解码调用参数
args -> parameterTypes
|
v
4. 解析目标实例
Instance -> RPCInstance
|
v
5. 组合调用 target
endpoint / protocol / serialization
|
v
6. 发起 Dubbo Generic Invoke
|
v
7. 返回
rawResult + elapsedMs
请求输入
这个接口的输入可以分成四组:
- 服务身份:
mesh + serviceName + version + group - 方法身份:
methodName + signature - 调用目标:
instanceName - 调用参数:
args + timeoutMs + attachments
也就是说,这个接口并不是“给一个服务名直接调”,而是要求调用语义和调用目标都明确。
方法语义解析
后端首先会按 mesh + serviceKey 查询 ServiceProviderMetadata,再根据 methodName + signature 精确定位目标方法。
这一步的作用是确认两件事:
- 当前服务下,这个方法是否真实存在
- 这个方法的参数类型到底是什么
参数解码
在定位到目标方法之后,后端会先校验参数个数是否和 parameterTypes 对齐,然后再按参数类型去解码前端传来的 JSON 参数。
这里的重点不是“能接收 JSON”,而是“把 JSON 转换成 Dubbo 泛化调用能接受的参数对象”。例如基础数值类型、字符类型、数组类型,都会按目标参数类型做显式转换,而不是原样透传。
调用目标解析
调用目标的解析分两步:
- 先按
mesh + instanceName查询Instance - 再从
Instance推导和查询对应的RPCInstance
这一步很关键,因为控制台里给用户选的是 Instance,但真正可执行 RPC 调用的,是带有 endpoint、protocol、serialization 信息的 RPCInstance。
所以这条链路本质上是在做一层映射:
控制台实例 -> 注册中心实例 -> 真实调用目标
执行与返回
在拿到方法和目标实例之后,后端会进一步从 RPCInstance 中提取 endpoint、protocol、serialization,组合出候选 target,然后发起 Dubbo Generic Invoke。
执行前会设置 timeout,并把 attachments 放进调用上下文。执行后则会记录耗时,并把返回结果整理成前端更容易消费的 JSON 友好结构。
所以这个接口最终交付给前端的,并不是底层原始对象,而是:
rawResultelapsedMs
这里可以用两句话概括整个 invoke 接口:
ServiceProviderMetadata决定“调什么”Instance -> RPCInstance决定“对谁调”
5. 后续 TODO
删除没用的旧接口
现在服务调试相关能力已经有了一条更完整的主链路,后面可以继续清理历史残留接口,收敛 API 面,避免同类能力重复或分散。
给 invoke 设计 dubbo-go client 池
当前实现里每次调用都会新建 dubbo-go instance/client。后续可以设计一个 client 池,把创建和复用抽出来,减少重复初始化开销。