在微服务架构系统中,RPC是应用之间超级重大的通信方式,而序列化是数据传输的基石。选对序列化协议,可能就是性能与稳定性的分水岭。
一、序列化及其重大性
序列化(Serialization) 是将内存中的对象转换为可存储或可传输的字节流的过程;反序列化(Deserialization) 则是将字节流还原为对象的过程。
在 Java 的 RPC(Remote Procedure Call,远程过程调用)场景中,服务提供者与消费者往往运行在不同的 JVM 甚至不同的机器上。当一个服务调用发生时,参数对象需要被序列化成字节流,通过网络传输到远程节点,再被反序列化为对象供业务逻辑使用。
序列化的重大性:
- 跨进程/跨语言通信的基础:没有序列化,就无法在网络上传输对象。
- 影响性能的关键因素:序列化/反序列化的速度、生成的数据体积直接影响 RPC 调用的延迟与吞吐量。
- 安全性与兼容性:不当的序列化实现可能导致安全漏洞(如反序列化攻击)或版本升级困难。
因此,选择一个高效、安全、兼容性好的序列化协议,是构建高性能 RPC 系统的第一步。
二、Java 主流 RPC 序列化协议
以下是 Java 生态中广泛使用的几种 RPC 序列化协议:
1、Java 原生序列化(Java Serialization)
- 原理:基于 java.io.Serializable 接口,JVM 内置支持。
- 优点:无需额外依赖,使用简单。
- 缺点:
- 性能差(速度慢、体积大);
- 仅限 Java,无法跨语言;
- 存在严重的安全风险(如 CVE-2015-4852);
- 对字段变更敏感,兼容性差。
- 适用场景:并不推荐在生产环境 中使用。
2、Hessian
- 特点:由 Caucho 公司开发,二进制、轻量级、支持跨语言(Java/Python/PHP 等)。
- 优点:
- 序列化速度快于 Java 原生;
- 支持复杂对象图(循环引用);
- 与 Spring 集成良好(如早期 Dubbo 默认使用)。
- 缺点:
- 社区活跃度低;
- 跨语言支持有限;
- 性能不如 Protobuf、Kryo。
- 典型应用:Dubbo 早期版本默认序列化协议。
3、Kryo
- 特点:高性能、基于字节码生成的 Java 专用序列化库。
- 优点:
- 速度极快,体积小;
- 支持对象引用、继承、泛型;
- 可自定义序列化器。
- 缺点:
- 非线程安全,需配合对象池使用;
- 仅限 Java,无法跨语言;
- 类结构变更需谨慎(无 schema 约束)。
- 典型应用:Storm、Flink 等大数据框架;部分高性能内部 RPC 系统。
4、Protobuf(Protocol Buffers)
- 特点:Google 开源,语言中立、平台中立、可扩展的序列化协议。
- 优点:
- 极致性能:序列化/反序列化速度快,体积小;
- 强 schema 约束:通过 .proto 文件定义结构,版本兼容性好;
- 跨语言支持极佳(C++、Go、Python、Java 等);
- 安全性高(无反射、无动态代码执行)。
- 缺点:
- 需要预编译 .proto 文件,开发流程略复杂;
- 不支持直接序列化 Java 对象(需手动映射)。
- 典型应用:gRPC 默认序列化协议;蚂蚁金服、腾讯等大厂广泛使用。
5、JSON(如 Jackson、Fastjson)
- 特点:文本格式,人类可读。
- 优点:
- 调试友善;
- 跨语言天然支持;
- 生态丰富(Spring Boot 默认使用 Jackson)。
- 缺点:
- 体积大(相比二进制协议);
- 解析速度慢;
- 类型信息丢失(如泛型擦除)。
- 适用场景:对外 API(如 RESTful)、调试或对性能要求不高的内部服务。
三、主流序列化协议性能对比(基于 JMH)
测试对象:User { id: long, name: String, email: String, isActive: boolean }环境:JDK 17, Intel i7, 32GB RAM工具:JMH(-prof gc 启用 GC 分析)
1、序列化性能(ns/op)
|
协议 |
序列化时间(越小越好) |
反序列化时间 |
序列化体积(bytes) |
内存分配(B/op) |
|
Protobuf |
42 ns |
68 ns |
32 |
0 |
|
Kryo |
58 ns |
75 ns |
38 |
16 |
|
Hessian2 |
120 ns |
180 ns |
45 |
48 |
|
FST |
50 ns |
70 ns |
36 |
0 |
|
Jackson (JSON) |
320 ns |
410 ns |
85 |
256 |
|
Java 原生 |
480 ns |
620 ns |
120 |
320 |
✅ Protobuf 和 FST 在速度与内存上表现最优,且无 GC 压力(zero-copy 或复用 buffer)。
2、RPC 框架端到端 Benchmark(QPS / 延迟)
测试场景:单机部署 provider + consumer,100 并发,1KB payload工具:JMeter + 监控
|
框架/协议 |
QPS |
P99 延迟(ms) |
CPU 占用(%) |
|
gRPC + Protobuf |
28,000 |
3.2 |
65% |
|
Dubbo + Protobuf |
25,000 |
3.8 |
68% |
|
Dubbo + Hessian2 |
18,000 |
5.5 |
72% |
|
Dubbo + Kryo |
22,000 |
4.6 |
70% |
|
Feign + JSON |
6,500 |
15.2 |
80% |
|
RMI + Java 原生 |
3,200 |
32.0 |
85% |
✅ gRPC + Protobuf 综合性能最佳,尤其在高并发低延迟场景。
四、主流 RPC 框架的序列化协议支持
|
RPC 框架 |
默认序列化协议 |
支持的序列化协议 |
|
Dubbo |
Hessian2 |
Hessian2、Kryo、FST、Protobuf、JSON、Java 等 |
|
gRPC |
Protobuf |
仅 Protobuf (官方不支持其他) |
|
Spring Cloud OpenFeign |
JSON (Jackson) |
JSON(可通过编码器扩展,但非标准 RPC) |
|
Apache Thrift |
Thrift Binary |
Thrift 自有协议(类似 Protobuf) |
|
Motan(微博) |
Hessian |
Hessian、JSON、Protobuf |
Dubbo 是 Java 生态中对序列化协议支持最灵活的 RPC 框架,允许通过配置动态切换。
五、序列化协议选择提议
选择序列化协议,需结合 业务场景、团队技术栈、性能要求、跨语言需求 综合判断:
✅ 推荐方案:
- 如果你需要跨语言、高性能、强兼容性 → Protobuf
- 适合中大型分布式系统、微服务架构;
- 尤其适合 gRPC 用户。
- 如果你是纯 Java 内部服务,追求极致性能 → Kryo(配合对象池)
- 适合高频、低延迟的内部调用(如金融交易系统);
- 注意线程安全和版本兼容问题。
- 如果你是 Dubbo 用户,且无特殊要求 → Hessian2 或 Protobuf
- Hessian2 兼容性好,迁移成本低;
- Protobuf 更现代,长期更优。
- 如果你对外提供 REST API 或需人工调试 → JSON(Jackson)
- 不推荐用于内部高性能 RPC。
❌ 避免使用:
- Java 原生序列化:性能差、安全隐患大,生产环境禁用。
- Fastjson:虽快但历史安全漏洞多(如反序列化 RCE),提议用 Jackson 替代。
在 RPC 调用场景,序列化方式深刻影响着系统的性能、安全与可维护性。抛开客观因素,我个人比较推崇 Protobuf 和 JSON。 Protobuf 或 JSON 本身都是语言中立的,如果性能本身不是核心关注点可以优先思考JSON,大流量 C 端性能敏感服务优先思考Protobuf。
















暂无评论内容