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 类注册优化,基本就够了。