[Bug] Metadata revision mismatch between dubbo-go v3.3 and Java Dubbo 3.3 (SHA-512 vs MD5, divergent toDescString)
- Dominant language
- Go
- Stars
- 5k
- Forks
- 1k
- Avg merge
- 2d 8h
- Merged PRs (30d)
- 31
Description
## 背景
dubbo-go 是 Apache Dubbo 的 Go 实现。Consumer 以 `revision`(元数据修订 hash)对 Provider 元数据进行去重缓存:相同 revision 的实例共用一份元数据,避免重复调用 MetadataService。缓存键见 `registry/servicediscovery/service_instances_changed_listener_impl.go:266` 的 `metadataCacheKey(app, registryId, revision)`。
## 问题描述
Go 与 Java Provider 暴露“相同”服务时,各自算出的 revision 不同(长度、内容均异)。Consumer 按 revision 分键缓存,同一应用被缓存为两份,丧失去重收益,跨语言互通场景元数据拉取次数翻倍。
## 根因分析(v3.3 源码比对,3 处不一致)
1. **Hash 算法**:Go 用 SHA-512(128 hex),Java 用 MD5(32 hex 小写)。
- Java:`RevisionResolver.calRevision` → `md5Utils.getMd5(metadata)`
- Go:`CalRevision(...)` → SHA-512(`metadata/info/metadata_info.go`)
2. **toDescString 格式**:Go 用 `|` 分隔并独立追加 methods;Java 用 `matchKey+port+path+无分隔符 params`。
- Java:`getMatchKey() + port + path + new TreeMap<>(getParams())`
- Go:`"name|group|version|protocol|port|path|params|methods"`
3. **methods 是否参与序列化**:Go 参与;Java 不参与(params 仅含 `method.key` 参数,不含 methods 列表)。
- Go:`NewServiceInfoWithURL` 将 MethodsKey 写入 params,且 `toDescString` 单独拼接 methods。
注:`matchKey` 格式 `serviceKey:protocol` 两边一致,无需改。
## 影响
跨语言互通场景元数据拉取次数翻倍、注册中心/MetadataService 压力上升。v3 应用级服务发现已大幅缓解早期应用注册时机差异(v1.5 时代),但 revision 不一致仍在。
## 复现步骤
1. 启动 Java 与 dubbo-go Provider 暴露同接口同配置的 `com.foo.Bar`;
2. 分别读取两端 `calRevision` / `CalRevision` 输出;
3. 比对:长度(128 vs 32 hex)与内容均不同 → 不一致。
## 建议修复方案
- `toDescString()` 改为 Java 格式:`matchKey + port + path + sortedParams`(排除 methods、无分隔符、不单独拼接)。
- `CalRevision` 由 SHA-512 改为 MD5(UTF-8 字节 MD5,32 hex 小写)。
- `NewServiceInfoWithURL` 使 params 与 Java 一致(methods 不入序列化;`GetMethods` 保留读取途径)。
- 新增跨语言 golden vector 测试:固定一组 service,断言 Go `CalRevision` 输出 == 已知 Java MD5 常量(取自 Java 单测),作为回归守护。
## 验收标准
- [ ] Go 与 Java 对相同服务的 revision 一致(32 hex、值相同)。
- [ ] 跨语言 golden vector 测试通过。
- [ ] 纯 Go 集群在 develop 分支完成一次性元数据重新拉取验证,无功能回退。
- [ ] 兼容性说明写入 changelog / PR 描述。
## 兼容性说明
改动会使所有 dubbo-go 应用 revision 变化,纯 Go 集群需一次性重新拉取元数据(短暂),但与 Java 互通为硬约束,应在 develop 分支(未正式发布)尽快修正。
Contributor guide
Assessment
This issue has not been assessed yet.