Dubbo 支持哪些序列化方式?

#中间件#面试八股

Dubbo 支持哪些序列化方式?

结论先行:Dubbo 默认用 Hessian2,另支持 Fastjson2、Protobuf、Kryo、FST、Java 原生、Avro、MessagePack、Thrift 等,Dubbo 3 的 Triple 协议默认用 Protobuf。选型看三点:跨语言需求、性能与体积、以及“字段增删是否兼容”的演进要求。

一、常见实现对比

方式跨语言体积性能兼容性适用场景
Hessian2(默认)较好中中字段增删兼容,忽略未知字段Java 为主的内部服务
Protobuf强小高按字段号演进,兼容性最好跨语言、Triple/gRPC
Fastjson2弱中大高依赖字段名,较宽松调试友好、JSON 生态
Kryo弱小很高需注册类,版本敏感内部高频调用
FST弱小高需 JDK 兼容类替代 Java 原生
Java 原生弱大低serialVersionUID 严格几乎不推荐
Avro强小高Schema 演进强大数据管道

二、为什么默认是 Hessian2

Hessian2 是自描述二进制协议:每个字段带类型与名字,因此消费端可以在不知道对方类结构细节的情况下解析,字段增删通常不报错。它不需要预先编译 IDL,对 Java 生态最省事,代价是体积比 Protobuf 大、解析比手写编解码慢。

Hessian2 编码示意(对象 → 字节流)
[H][0x02] 版本
  'C' 类定义:类名长度 + 类名 + 字段数 + 字段名列表
  'O' 对象实例:按字段顺序写值(int/string/date 各有类型标记)

三、切换与配置

全局指定:

dubbo:
  protocol:
    name: dubbo
    serialization: hessian2     # 可选 fastjson2 / protobuf / kryo / java

方法级覆盖:

@DubboReference(serialization = "fastjson2", timeout = 800)
private OrderService orderService;

Protobuf 需要 IDL 与生成类:

syntax = "proto3";
option java_package = "com.demo.api";
message UserReq {
  int64 id = 1;
  string name = 2;
}
service UserService {
  rpc GetById (UserReq) returns (UserResp);
}

四、切换序列化时的兼容性红线

操作Hessian2ProtobufJava 原生
新增字段兼容兼容(新字段号)兼容(需同 serialVersionUID)
删除字段通常兼容保留字段号即可不兼容
改字段类型可能失败不兼容不兼容
改类名/包名失败由 IDL 决定失败

上线时必须“先升提供者、后升消费者”,或双跑两种序列化做灰度;不能一边 hessian2 一边 protobuf 混调同一接口。

常见追问

  • 追问:Hessian2 有哪些坑?它对某些集合类型、循环引用、大对象处理不好;序列化漏洞也出现过,所以要升级到修复版本并限制反序列化类。
  • 追问:为什么不用 Java 原生序列化?体积大、性能差、强依赖类结构、有反序列化漏洞面。
  • 追问:Triple 协议为什么用 Protobuf?它是 gRPC 兼容协议,靠 HTTP/2 + Protobuf 实现跨语言与流式调用。

小结

  • 默认 Hessian2,省事但体积与性能一般。
  • 跨语言选 Protobuf,内部极致性能选 Kryo/FST,调试友好选 JSON。
  • 换序列化前先确认字段演进策略与灰度顺序。
  • 序列化不是免费开关,它决定了接口的兼容边界。
笔记加载中…