Repository navigation
metadata #3300
Replies: 3 comments
|
文章的宏观主线基本是对的,尤其是“应用级发现里 registry 负责给实例,metadata 负责把实例恢复成服务语义”这条线;但有几处说法讲得太顺了,落到 dubbo-go 现实现状上会失真。 主要偏差
有一处值得单独强调
|
|
按 Provider 启动 -> 注册 -> metadata 发布/暴露 -> consumer 拉取 -> URL 恢复 这条时序重新梳一遍。 先定一个一句话
这条主线文章是说对了的。 一、metadata 模块里真正存的是什么 它维护的不是一个单一对象,而是按
这里有个很重要的点: 二、Provider 启动时 metadata 做了什么
对应代码主链路在 service_discovery_registry.go。 先看注册单个服务:
见 service_discovery_registry.go#L225。 之后注册应用实例:
见 service_discovery_registry.go#L85。 三、revision 在 dubbo-go 里到底是什么 当前 revision 计算在 service_revision_customizer.go: 它把每个 URL 变成候选字符串,核心只用了:
然后排序后做 CRC32 累加。 这意味着:
所以更准确的说法是:
四、MetadataService 是什么,不是什么
RPC 暴露只是它的一种外化形式:
但要注意一个边界:
所以更准确的话应该是: metadata 在 dubbo-go 中既可能以“provider 暴露的 RPC 服务”形式被访问,也可能以“metadata center 存储”形式被访问,取决于 storage type。 五、实例 metadata 里到底写了哪些东西 当前至少还有这些关键字段:
对应代码:
这说明 dubbo-go 的实例级 metadata 不是“只有 revision 和入口地址”,而是已经有一套最小可运行的实例语义模型,只是比 Java 侧还薄。 六、接口 -> 应用 mapping 在这里扮演什么角色 因为 service discovery 看到的是“应用实例”,但 consumer 常常还是按“接口”发起订阅,所以必须先回答: “这个接口由哪些应用提供?” 这层抽象就是 它的语义很清楚:
但这块有一个比文章更现实的约束: mapping 在 dubbo-go 里不是纯本地能力,它强依赖 metadata report。 这点在 service_discovery_registry.go#L254 很明显。 七、Consumer 运行时到底怎么把实例恢复成服务 URL consumer 订阅链路大致是:
核心逻辑在 service_instances_changed_listener_impl.go。 其中最关键两步:
见: 所以可以把 consumer 侧理解成一句话: consumer 不是直接消费“注册中心给的实例地址”,而是消费“实例 + metadata 还原出的服务 URL”。 八、远端拉取 metadata 时,实际有两条路
而且 triple 下会优先区分:
这不是单纯“远程访问 metadata”,而是“按实例声明的 metadata 版本和存储类型选择访问路径”。 九、和文章相比,我建议你脑子里换成这版模型
最后给一个最简版时序
|
|
一个“dubbo-go metadata 全链路时序图”: 下面这张图按 dubbo-go 当前实现画,把 flowchart TD
A["Provider 导出服务 URL"] --> B["metadata.AddService(registryId, url)<br/>本地收集 exported URLs"]
A --> C["serviceNameMapping.Map(url)<br/>登记 接口 -> 应用 映射"]
B --> D["生成 MetadataInfo<br/>services / exported URLs / app"]
D --> E["计算 revision<br/>dubbo.metadata.revision"]
E --> F["创建 ServiceInstance"]
F --> G["写入实例 metadata<br/>storage-type / revision / meta-v / endpoints / metadata-service.url-params"]
G --> H{"metadata-type ?"}
H -->|local| I["导出本地 MetadataService RPC<br/>dubbo / tri v1 / tri v2"]
H -->|remote| J["PublishAppMetadata(app, revision, MetadataInfo)<br/>发布到 metadata report"]
I --> K["注册应用实例到 Service Discovery"]
J --> K
L["Consumer 按接口订阅"] --> M{"provided-by 是否显式配置?"}
M -->|是| N["直接得到应用集合"]
M -->|否| O["serviceNameMapping.Get(url, listener)<br/>从 metadata report 查询/监听 接口 -> 应用"]
N --> P["订阅这些应用实例变化"]
O --> P
K --> P
P --> Q["拿到 ServiceInstance 列表"]
Q --> R["读取实例 metadata 中的 revision"]
R --> S{"storage-type ?"}
S -->|remote| T["GetMetadataFromMetadataReport(revision, instance)"]
S -->|local| U["GetMetadataFromRpc(revision, instance)<br/>调用 provider MetadataService"]
T --> V["得到 MetadataInfo"]
U --> V
V --> W["遍历 MetadataInfo.Services"]
W --> X["instance.ToURLs(serviceInfo)<br/>实例 + 服务语义 => 最终 URL"]
X --> Y["形成 consumer 可调用 URL 列表"]
如果你想更直观一点,也可以把它压成一句话:
再补一张“模块职责图”,方便和上面的时序图对着看: flowchart LR
A["Service Discovery"] -->|"应用实例列表"| B["Consumer"]
C["Metadata Report"] -->|"app metadata / mapping"| B
D["Provider MetadataService"] -->|"local metadata RPC"| B
E["Provider 本地 metadata"] -->|"生成 revision / services"| A
E -->|"发布 app metadata"| C
E -->|"导出 MetadataService"| D
E -->|"登记 接口 -> 应用"| C
最容易记混的边界是这三个:
|
Uh oh!
There was an error while loading. Please reload this page.
ref:https://caicaiis.cc/4/dubbo-go-metadata/
All reactions