从零开始实现简单 RPC 框架 5:网络通信之序列化
2021-08-27 09:19
836 查看
我们在接下来会开始讲网络通信相关的内容了。既然是网络通信,那必然会涉及到序列化的相关技术。
下面是
ccx-rpc序列化器的接口定义。
/** * 序列化器 */ public interface Serializer { /** * 序列化 * * @param object 要序列化的对象 * @return 字节数组 */ byte[] serialize(Object object); /** * 反序列化 * * @param bytes 字节数组 * @param clazz 要反序列化的类 * @param <T> 类型 * @return 反序列化的对象 */ <T> T deserialize(byte[] bytes, Class<T> clazz); }
接口只包含序列化、反序列化两个最基础的方法。不同的序列化器只需要实现这个接口即可,再配合
SPI就可以使用了。 下面是
ccx-rpc的一小段反序列化代码:
// 获取序列化类型 SerializeType serializeType = SerializeType.fromValue(codec); // 获取序列化器 Serializer serializer = ExtensionLoader.getLoader(Serializer.class).getExtension(serializeType.getName()); // 根据消息类型选择反序列化的 Class Class<?> clazz = messageType == MessageType.REQUEST.getValue() ? RpcRequest.class : RpcResponse.class; // 进行反序列化 Object object = serializer.deserialize(decompressedBytes, clazz);
序列化算法有多种多样,各有千秋,我们需要结合自己的业务,选择合适的序列化算法。
序列化算法的选择通常有下列一些常用的指标:
- 通用性:是否跨语言,跨平台。如果 RPC 调用涉及到其他语言、平台,这个指标不可忽视。
- 性能:通常指解析速度、序列化后的大小。序列化后的数据一般用于存储或网络传输,其大小是一个很重要的指标;解析的速度无需多言,当然是越快越好。
- 可扩展性:系统升级不可避免,某一实体的属性变更,会不会导致反序列化异常,也应该纳入序列化算法的考量范围。
- 易用性:API 使用是否复杂,会影响开发效率。
下面我们来看一下常见的序列化算法。
常见序列化算法
1. Java 序列化
Java 序列化大家都很熟悉了,使用起来也不算复杂。先实现
Serializable,生成序列号
serialVersionUID,最后调用
java.io.ObjectOutputStream的
writeObject()/
readObject()进行序列化与反序列化。
说实话,Java 序列化虽然知道,但是还没真正去用过,这个使用步骤还是临时搜的。。。
Java 序列化有个致命缺点:那就是不跨语言,而且性能也不太行。所以 Java 序列化很少人用,也成为了我们最熟悉的陌生人。
2. FastJson
FastJson是阿里开源的
JSON解析库。正如其名,“快”是其主要卖点。从官方的测试结果来看,
FastJson确实是最快的,比
Jackson快 20% 左右,但是近几年
FastJson的安全漏洞比较多,而且版本升级可能会存在较大的兼容问题,所以在选择的时候,还是需要谨慎一些。
JSON的优点就是可读性高,但是其序列化结果的体积比较大。
3. Jackson
Jackson相对
FastJson的功能比较多,安全漏洞也比较少,社区活跃。虽然性能相对于
Jackson稍差,但是用着安心。 但是其序列化结果的体积比较大,对 RPC 框架来说,还是不大适合的。
4. Kryo
Kryo是一个高效的 Java 序列化/反序列化库,其特点是 API 代码简单,序列化速度快,并且序列化之后得到的数据比较小。 优点:接口易用、解析快、体积小 缺点:只支持 Java、增删字段会异常
5. Hessian
Hessian是一种支持动态类型、跨语言的序列化协议,Java 对象序列化的二进制流可以被其他语言使用。 优点:接口易用、解析快、支持多语言 缺点:类需要实现
Serializable接口、异常机制不完善,提示信息不足
6. Protobuf
Google 公司开发的一套灵活、高效、自动化的、用于对结构化数据进行序列化的协议。相比于常用的
JSON格式,
Protobuf有更高的转化效率,时间效率和空间效率都是
JSON的 5 倍左右。
Protobuf可用于通信协议、数据存储等领域,它本身是语言无关、平台无关、可扩展的序列化结构数据格式。目前
Protobuf提供了
C++、
Java、
Python、
Go等多种语言的 API。 优点:解析快、体积小、支持多语言。 缺点:需要先定义
proto结构,使用相对麻烦,不过 Java 可以使用
Protostuff解决这个问题。
总结
在上文,我们介绍了序列化器的定义,很简单,只有序列化,反序列化两个方法。 然后,介绍了常见的序列化算法,例如Java 序列化、FastJson、Jackson、Kryo、Hessian、Protobuf 等。这些算法各有优缺点,大家在使用时,可以结合自己的业务情况进行选择。
ccx-rpc 代码已经开源 Github:https://github.com/chenchuxin/ccx-rpc Gitee:https://gitee.com/imccx/ccx-rpc
相关文章推荐
- 从零开始实现简单 RPC 框架 6:网络通信之 Netty
- 从零开始实现简单 RPC 框架 9:网络通信之心跳与重连机制
- 从零开始实现简单 RPC 框架 8:网络通信之 Request-Response 模型
- 从零开始实现简单 RPC 框架 7:网络通信之自定义协议(粘包拆包、编解码)
- go实现一个简单的游戏服务器框架(lotou)网络通信
- 从零开始实现简单 RPC 框架 2:扩展利器 SPI
- 从零开始实现简单 RPC 框架 3:配置总线 URL
- 基于Netty的RPC简单框架实现(三):Kryo实现序列化
- 从零开始实现简单 RPC 框架 1:RPC 框架的结构和设计
- 【远程调用框架】如何实现一个简单的RPC框架(四)优化二:改变底层通信框架
- 基于Netty的RPC简单框架实现(四):Netty实现网络传输
- C#实现简单的网络通信
- Java实现一个简单的RPC框架(六) 注册机制
- 用libev的c语言版本实现简单的网络通信服务器
- 强大的网络通信框架(不实现缓存)--第三方开源--AsyncHttpClient
- linux网络编程之用socket实现简单客户端和服务端的通信(基于UDP)
- 从零开始写Go网络通信框架(1)——基本的Socket Client/Server的编写
- 多线程和网络通信实现的简单多线程上传
- 一个简单RPC框架是如何炼成的(III)——实现带参数的RPC调用
- 实现采用客户/服务器通信模式,基于TCP网络通信协议的多客户端简单应用