⚾️ 问题描述

在一次 Dubbo 微服务调用中,服务 A 调用服务 B 接口,返回结果中的部分字段在 Consumer 侧(A 服务)丢失,表现为值为 null,但在 Provider 侧(B 服务)正常。这种现象对业务产生了干扰,因此需要深入排查。

🏉 环境与日志信息

所有微服务 JVM 版本

dubbo 配置

provider (B服务) 的 dubbo 配置
consumer (A服务)的 dubbo 配置

对应日志

B 服务上的日志打印
A 服务上的日志打印
 
其他相同时间段内的日志打印
 

DTO 类

🎱 初步分析

通过对比 Provider 与 Consumer 两侧的日志,发现 Provider 返回的日志完整,而 Consumer 却存在多个字段为 null 的情况,尤其是 codelevel 等核心字段。这种现象显然不是业务逻辑导致,而可能与序列化或 DTO 对象兼容性有关。

🤺 问题排查

在排查序列化问题之前,首先要明确在当前dubbo调用中,序列化协议使用的是什么。
首先看一下两个服务的相关配置
provider (A服务) 的 dubbo 配置
 
consumer (B服务)的 dubbo 配置
Provider 配置了 prefer.serialization=fastjson2,hessian2,但由于 Consumer 没有声明具体的 serialization,Dubbo 使用协议协商默认 fallback 为 Hessian2。
重要说明:Dubbo 协议协商中,Consumer 配置优先于 Provider,Provider 无法强制指定 Consumer 使用特定序列化方式。
 
在dubbo-admin 查看对应服务的序列化方式,进一步确认为 hessian2
 
notion image
 
通过查询,进一步明确 dubbo 3.2.0 使用的 dubbo-hessian-lite 为 3.2.13 版本。
 
为确认是否为 CopyOnWriteArrayList 等线程安全集合或 DTO 差异导致的问题,构造本地 Demo 进行验证,部分代码如下:
provider 模块
consumer 模块
 
demo运行结果显示,在dubbo3.2.0,dubbo-hessian-lite 3.2.13 版本中,DTO中的CopyOnWriteArrayList并不影响反序列化。
notion image
 
并且验证了以下几种情况,也并不影响序列化和反序列化。
1、consumer 中SystemDeviceErrorCodeListResponse.systemErrorCodeList和SystemDeviceErrorCodeListResponse.deviceErrorCodeList字段为List,provider 中为CopyOnWriteArrayList;
2、consumer 中DeviceErrorCodeDetailDTO缺少serialVersionUID

🚣 最终定位:DTO版本不一致导致

在进一步排查构建产物时发现,CI 环境中打包错误:某二方库引用了旧版本 DTO,字段定义与最新 Provider 版本不一致,导致 Consumer 反序列化出现字段为 null。
修复方式:统一依赖版本,确保构建产物使用最新 DTO 定义,问题消失。

🚴 总结与建议

  • Dubbo 序列化方式需双方明确配置,避免 fallback 导致兼容性问题;
  • CI 构建环境需加强依赖管理,防止错误引用旧版本类库;
  • 使用 JSON/Protobuf 等显式格式序列化方式,可减少兼容性隐患;
  • 尽量避免使用线程安全类(如 CopyOnWriteArrayList)做为 RPC 数据传输对象结构;
  • 建议建立字段兼容性校验机制,确保 CI 构建包字段定义一致。

🚥 参考文章

一次 Nacos 实例频繁掉线引发的 503 故障排查实录新手也能轻松搞定!Ubuntu 上部署 Rancher 全流程指南
Loading...