问题描述
近期涂鸦智能的筒子反馈:dubbogo 客户端使用 Triple 协议发往 dubbo (Java) 服务端的某些 attachment 会发送丢失现象,并报了 issue:
https://github.com/apache/dubbo-go/issues/2752
问题简述:服务端无法从附件中获取键名为 remote.application 的值。
具体来说,在使用 Dubbo-go 客户端调用 Dubbo-java 服务时,发现通过 context 设置的 attachment 中,"remote.application" 键值对在服务端无法获取,而 "remote.application1" 和 "remote.application2" 可以正常获取。
这里先给出结论:这不是一个 bug,之所以 attachment 中 key 为 "remote.application" 的 item 在 dubbo server 端被过滤掉,是因为该 key 是 dubbo(Java) attachment 中的保留字段,不允许用户使用。
下面给出问题复现,以及问题分析过程。
环境准备
- 服务端:Dubbo-Java v3.3.0
- 客户端:Dubbo-go v3.2.0-rc2
- 协议:triple
- 注册中心:Zookeeper
参考:https://github.com/apache/dubbo-go-samples
- 代码:Dubbo java and go interoperability, protobuf and triple protocol
- 文档:基于 protobuf 实现 triple 协议互通(适用于两边都用 protobuf 开发的场景)
Client 端
先下载 dubbo-go-samples 工程,在工程根目录下执行如下命令,以更新 dubbo-go-sample 依赖的 dubbogo 版本。
java_interop/protobuf-triple/go/go-client/cmd/client.go:
Server 端
java_interop/protobuf-triple/java/java-server/pom.xml:
java_interop/protobuf-triple/java/java-server/src/main/java/org/apache/dubbo/sample/GreeterImpl.java:
运行
Go client 调用 java server
- java-server 目录中:
- go-client 目录中:
- 结果输出
服务端:
客户端:
注意到 java-server 无法从 go-server 传递的 attachment 获取 "remote.application" 键。
问题分析
在这个场景中涉及到 ClientAttachment 和 ServerAttachment:
- ClientAttachmen:Go 客户端写入参数
- ServerAttachment:Java 服务端读取参数
调用流程:
- client 端:Method Invoke 发起调用 $\rightarrow$ 写入 RpcClientAttachment $\rightarrow$ 封装进 Invocation $\rightarrow$ 序列化传输
- server 端:解析 Invocation $\rightarrow$ 生成 Method Invoke 参数和 RpcServerAttachment $\rightarrow$ 真实调用
$\rightarrow$ 处理后生成 Result(包含 Response 和 Context)$\rightarrow$ 序列化返回。
参考 官方文档:
Triple 协议会将 attachment 转换为 HTTP header 传输,使用 Wireshark 抓包分析,确认 "remote.application" 确实被正确封装在 HTTP header 中,说明 Go 客户端的 ClientAttachment → Invocation → 网络传输链路是正常的。
关注 Java 服务端的 org.apache.dubbo.rpc.protocol.tri.h12.AbstractServerTransportListener 服务端是请求处理的核心类,负责接收和处理 HTTP 请求,并构建 RPC 调用对象。
调用 StreamUtils.toAttachments() 之前,Header 中是包含 "remote.application" 的。
调用 StreamUtils.toAttachments() 之后,RpcInvocation 类型对象 inv 的成员变量 Map<String,Object>attachments 不包含 "remote.application"。
StreamUtils#toAttachments(HttpHeaders headers):
StreamUtils#putAttachment(Map<String, Object> attachments, String key, Object value):
进一步查看 TripleHeaderEnum :
为了防止业务层误用或覆盖这个键值,Dubbo 将其加入了排除列表,导致即使在 attachment 中设置了这个键值对,在转换时也会被过滤掉。