Dubbo RPC中序列化必经且发生两次:客户端封装Invocation为字节流,服务端反序列化执行并返回再序列化;需双方协议与类结构完全一致。

在 Dubbo RPC 中,对象序列化不是可选项,而是每次远程调用必经的底层环节。它直接决定参数和返回值能否正确跨进程传输,也深刻影响性能、兼容性和调试效率。
序列化发生在调用链的哪几个位置
一次典型的 Dubbo 调用中,序列化/反序列化共发生两次:
- 客户端侧(消费者):调用方法时,代理将接口名、方法名、参数对象等封装为 Invocation 对象,并用配置的序列化器(如 Hessian2)将其转为字节流,再通过网络发送
- 服务端侧(提供者):收到字节流后,用相同序列化器还原为 Invocation 对象,执行实际方法;返回结果时再次序列化,发回给消费者
整个过程对业务代码完全透明,但要求双方使用**完全一致的序列化协议和类结构**,否则会抛出 ClassCastException 或反序列化失败异常。
如何选择并配置合适的序列化方式
Dubbo 支持多种序列化协议,选型需兼顾性能、可读性、跨语言需求和 JDK 兼容性:
Java Maven 项目审查工作流的通用输入处理。当 Java Maven 项目以 ZIP压缩包或 GitLab 仓库 URL 形式提供且需要...时使用。
立即学习“Java免费学习笔记(深入)”;
- Hessian2:Dubbo 默认方案(尤其 dubbo 协议下),Java 友好、兼容性强、无需实现 Serializable 接口,适合大多数 Java 内部服务通信
- Protobuf(triple 协议默认):高性能、体积小、强类型、天然跨语言,但需提前定义 .proto 文件,适合云原生或混合技术栈场景
- FastJSON2:生成可读 JSON 字符串,便于日志排查和网关透传,但性能略低于二进制协议,适合调试期或需要人工干预的链路
- Kryo/FST:纯 Java 高性能方案,序列化快、体积小,但不跨语言,且要求类无复杂依赖(如线程局部变量、不可序列化资源)
配置方式示例(application.yml):
dubbo:protocol:
name: dubbo
serialization: hessian2 # 或 kryo / fastjson2
# 若使用 triple 协议:
# name: triple
# serialization: protobuf
让对象可被正确序列化的关键实践
即使选对了协议,业务对象若设计不当,仍会触发运行时异常。需注意以下几点:
- 使用 Hessian2 时,类**不需要实现 Serializable**,但所有字段类型必须是 Hessian 支持的基础类型、集合、数组或已有对应序列化器的 POJO
- 避免在传输对象中包含 ThreadLocal、InputStream、Socket 等不可序列化资源;建议 DTO 类保持纯净,与领域模型分离
- 字段命名变更、删除或类型不兼容升级(如 String → Integer)会导致反序列化失败;建议通过 @Version 或接口多版本控制演进
- 若用 Protobuf,必须保证 provider 和 consumer 使用同一份生成的 Java 类(由 proto 编译器产出),且 .proto 文件语义一致
常见问题与快速定位建议
遇到序列化相关报错(如 “java.io.IOException: java.lang.ClassNotFoundException” 或 “com.alibaba.com.caucho.hessian.io.HessianProtocolException”),可按顺序检查:
- 确认 provider 和 consumer 的 dubbo.protocol.serialization 配置值是否完全一致(包括大小写)
- 检查传输对象类在双方 classpath 中是否存在、包路径是否一致、是否被混淆或裁剪(如 Android 或 GraalVM 场景)
- 启用 Dubbo 日志级别为 DEBUG,查看 org.apache.dubbo.common.serialize.Serialization 的日志输出,确认实际使用的序列化器类型
- 对复杂嵌套对象,可临时用 FastJSON2 序列化打印输出,验证结构是否符合预期

















