Dubbo 支持哪些序列化方式?


一则或许对你有用的小广告

欢迎加入小哈的星球,你将获得:专属的实战项目(4个项目都能学) / 1v1 提问 / 简历修改 / Java 学习路线 / 社群讨论 / 学习打卡 / 每月赠书

  • 《Spring AI 项目实战(问答机器人、RAG 智能客服、联网搜索)》已完结,基于 Spring AI + Spring Boot 3.x + JDK 21...,查看介绍

  • 《从零手撸:仿小红书(微服务架构)》 已完结,基于 Spring Cloud Alibaba + Spring Boot 3.x + JDK 17...,查看介绍;演示链接:http://116.62.199.48:7070/

  • 《从零手撸:前后端分离博客项目(全栈开发)》 2 期已完结,演示链接:http://116.62.199.48/

  • 新开坑项目:《从零手撸:秒杀系统高并发优化实战》 正在更新中...,查看介绍

截止目前,星球内专栏累计输出 150w+ 字,讲解图 5110+ 张,还在持续爆肝中.. 后续还会上新更多项目,已有 4700+ 小伙伴加入学习,欢迎点击围观

面试考察点

  1. 基础掌握度:面试官不仅仅想知道你能列举几种序列化方式,更想知道你是否理解每种方式的优缺点和适用场景,能否在项目中做出合理选型。

  2. 性能意识:序列化是 RPC 调用链路上最耗时的环节之一。面试官想看你是否具备性能优化的思维,是否知道不同序列化方式在速度、体积、兼容性上的差异。

  3. 架构视野:优秀的候选人应该能从 Dubbo 的 SPI 扩展机制角度理解序列化的可插拔设计,而不是死记硬背几个名字。

核心答案

Dubbo 支持多种序列化方式,通过 SPI 机制实现可插拔扩展。以下是主流的几种:

序列化方式 实现类 速度 体积 跨语言 推荐场景
Hessian2 Hessian2Serialization 中等 较小 支持 Dubbo 默认,通用场景
FastJson FastJsonSerialization 中等 中等 支持 需要可读性的场景
Kryo KryoSerialization 快 小 不支持 Java 纯内网高性能场景
FST FstSerialization 快 小 不支持 Java 纯内网高性能场景
Protobuf ProtobufSerialization 快 最小 支持 跨语言、对体积敏感
MessagePack — 较快 较小 支持 跨语言轻量场景
JDK JavaSerialization 慢 大 不支持 兼容性兜底(不推荐)

Dubbo 2.x 默认使用 Hessian2,Dubbo 3.x 开始推荐使用 Triple 协议 + Protobuf。

深度解析

一、为什么序列化这么重要?

RPC 调用的核心流程中,序列化和反序列化是必经环节,而且往往是性能瓶颈:

上图展示了 RPC 调用中各环节的耗时分布。可以看到:

  • 序列化 + 反序列化加起来能占到一次 RPC 调用耗时的 60% 左右,远超网络传输本身
  • 这也是为什么选择合适的序列化方式对系统性能影响巨大
  • 同样的业务逻辑,换一种序列化方式,吞吐量可能差出好几倍

二、主流序列化方式对比详解

1. Hessian2(默认)

Dubbo 默认的序列化方式,也是经过生产环境大规模验证的。

<!-- 默认就是 hessian2,可以不配 -->
<dubbo:protocol serialization="hessian2" />

优点:

  • 跨语言支持:Hessian 协议本身设计就支持多语言
  • 成熟稳定:在 Dubbo 生态里用了这么多年,坑基本踩平了
  • 体积适中:二进制格式,比 JDK 序列化小很多

缺点:

  • 性能比 Kryo、FST 这类要慢
  • 对复杂对象的支持偶尔会有坑(比如泛型擦除问题)

2. Kryo / FST(高性能之选)

如果你的服务是纯 Java 技术栈,不需要跨语言,Kryo 和 FST 是性能最优的选择。

<!-- 使用 Kryo 序列化 -->
<dubbo:protocol serialization="kryo" />

<!-- 使用 FST 序列化 -->
<dubbo:protocol serialization="fst" />

使用 Kryo 时有个细节需要注意——需要注册类:

// 注册类以获得更好的性能
public class KryoSerializationOptimizer implements SerializationOptimizer {
    @Override
    public Collection<Class> getSerializableClasses() {
        List<Class> classes = new ArrayList<>();
        classes.add(User.class);
        classes.add(Order.class);
        // 把你业务中常用的 DTO 都注册进来
        return classes;
    }
}

注册类之后,Kryo 会用整数 ID 代替完整的类名,序列化体积更小、速度更快。这个优化点很多同学不知道,面试的时候提一嘴,加分。

3. Protobuf(Dubbo 3.x 的推荐方案)

Dubbo 3.x 推出了 Triple 协议(基于 HTTP/2,兼容 gRPC),默认使用 Protobuf 序列化。

// 定义 proto 文件
syntax = "proto3";
package com.example;

message UserRequest {
    int64 id = 1;
}

message UserResponse {
    int64 id = 1;
    string name = 2;
    string email = 3;
}
// Dubbo 3.x 使用 Protobuf 的方式
@DubboService
public class UserServiceImpl implements UserService {
    @Override
    public UserResponse getUser(UserRequest request) {
        // 业务逻辑
    }
}

为什么 Dubbo 3.x 要转向 Protobuf?

  • 跨语言:gRPC 生态天然支持多语言,Dubbo 要融入云原生时代,跨语言是刚需
  • 高性能:Protobuf 的编解码速度和压缩率都是顶级的
  • IDL 定义:通过 .proto 文件明确定义接口,比 Java 接口更规范,天然支持版本演进
  • 云原生友好:Triple 协议兼容 gRPC,可以和 Kubernetes、Service Mesh 等基础设施更好地集成

4. JDK 序列化(别用)

<!-- 不推荐 -->
<dubbo:protocol serialization="java" />

面试的时候如果提一嘴 "JDK 序列化性能差、体积大、还有安全风险",面试官会认为你有实际经验。JDK 序列化的主要问题:

  • 性能非常慢,比 Hessian2 慢好几倍
  • 序列化后的体积很大
  • 存在反序列化安全漏洞风险
  • 无法跨语言

三、如何选型?

上图是选型决策树,简单总结一下就是:

  • 跨语言需求:Dubbo 3.x 首选 Protobuf + Triple 协议;Dubbo 2.x 用 Hessian2
  • 纯 Java 高性能:选 Kryo 或 FST,记得注册类优化
  • 通用稳妥:Hessian2,不折腾
  • JDK 序列化:永远别用

四、Dubbo SPI 扩展机制

Dubbo 的序列化之所以能做到可插拔,核心在于 SPI(Service Provider Interface)机制:

// Dubbo 的 Serialization SPI 接口
@SPI("hessian2")  // 默认使用 hessian2
public interface Serialization {
    byte getContentTypeId();
    ObjectOutput serialize(URL url, OutputStream output) throws IOException;
    ObjectInput deserialize(URL url, InputStream input) throws IOException;
}

这意味着你也可以实现自己的序列化方式:

// 自定义序列化实现
public class MySerialization implements Serialization {
    @Override
    public byte getContentTypeId() {
        return 20;  // 自定义 ID,避免冲突
    }

    @Override
    public ObjectOutput serialize(URL url, OutputStream output) {
        return new MyObjectOutput(output);
    }

    @Override
    public ObjectInput deserialize(URL url, InputStream input) {
        return new MyObjectInput(input);
    }
}

然后在 META-INF/dubbo/ 目录下配置 SPI:

com.alibaba.dubbo.common.serialize.Serialization
my=com.example.MySerialization

使用时指定即可:

<dubbo:protocol serialization="my" />

这块面试的时候可以顺带提一下 SPI 机制,体现你对 Dubbo 架构设计的理解。

面试高频追问

  1. Dubbo 3.x 为什么推荐 Protobuf?

    因为 Triple 协议基于 HTTP/2 且兼容 gRPC,Protobuf 是 gRPC 的标配序列化方案,性能好、跨语言、IDL 规范,适合云原生场景。

  2. 序列化对接口性能影响有多大?

    实测中,把 Hessian2 换成 Kryo,吞吐量能提升 30%~50%,延迟降低 20%~30%(数据跟对象复杂度有关)。对于高并发场景,这个提升非常可观。

  3. Kryo 的类注册有什么作用?

    不注册类时,Kryo 用完整类名做标识,体积大、速度慢。注册后用整数 ID 代替类名,体积更小,序列化/反序列化速度也更快。

  4. Dubbo 的序列化能动态切换吗?

    可以。通过 <dubbo:protocol> 或 <dubbo:service> 级别配置 serialization 参数,不同服务可以用不同的序列化方式。Dubbo 通过 SPI 机制运行时动态加载。

常见面试变体

  • "Dubbo 默认的序列化方式是什么?为什么选它?"
  • "Dubbo 3.x 的 Triple 协议用的什么序列化?和 Dubbo 协议有什么区别?"
  • "如何提升 Dubbo 的序列化性能?"
  • "Dubbo 的 SPI 机制是怎么实现的?"

记忆口诀

默认 Hessian2,跨语言上 Protobuf,纯 Java 选 Kryo,JDK 序列化千万别用。

总结

Dubbo 通过 SPI 机制支持多种序列化方式,2.x 默认 Hessian2,3.x 推荐 Protobuf + Triple。选型看三个维度:是否跨语言、性能要求、生态兼容。面试的时候把选型逻辑讲清楚,再顺带提一嘴 SPI 扩展机制和 Kryo 类注册优化,基本就够了。