从零开始实现简单 RPC 框架 5:网络通信之序列化
我们在接下来会开始讲网络通信相关的内容了。既然是网络通信,那必然会涉及到序列化的相关技术。
下面是 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 对象序列化的二进制流可以被其他语言使用。
优点:接口易用、解析快、支持多语言
缺点:异常机制不完善,提示信息不足
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 框架 5:网络通信之序列化的更多相关文章
- 从零开始实现简单 RPC 框架 6:网络通信之 Netty
		网络通信的开发,就涉及到一些开发框架:Java NIO.Netty.Mina 等等. 理论上来说,类似于序列化器,可以为其定义一套统一的接口,让不同类型的框架实现,事实上,Dubbo 就是这么干的. ... 
- 从零开始实现简单 RPC 框架 7:网络通信之自定义协议(粘包拆包、编解码)
		当 RPC 框架使用 Netty 通信时,实际上是将数据转化成 ByteBuf 的方式进行传输. 那如何转化呢?可不可以把 请求参数 或者 响应结果 直接无脑序列化成 byte 数组发出去? 答:直接 ... 
- 从零开始实现简单 RPC 框架 2:扩展利器 SPI
		RPC 框架有很多可扩展的地方,如:序列化类型.压缩类型.负载均衡类型.注册中心类型等等. 假设框架提供的注册中心只有zookeeper,但是使用者想用Eureka,修改框架以支持使用者的需求显然不是 ... 
- 从零开始实现简单 RPC 框架 8:网络通信之 Request-Response 模型
		Netty 在服务端与客户端的网络通信中,使用的是异步双向通信(双工)的方式,即客户端和服务端可以相互主动发请求给对方,发消息后不会同步等响应.这样就会有一下问题: 如何识别消息是请求还是响应? 请求 ... 
- 从零开始实现简单 RPC 框架 9:网络通信之心跳与重连机制
		一.心跳 什么是心跳 在 TPC 中,客户端和服务端建立连接之后,需要定期发送数据包,来通知对方自己还在线,以确保 TPC 连接的有效性.如果一个连接长时间没有心跳,需要及时断开,否则服务端会维护很多 ... 
- 从零开始实现简单 RPC 框架 4:注册中心
		RPC 中服务消费端(Consumer) 需要请求服务提供方(Provider)的接口,必须要知道 Provider 的地址才能请求到. 那么,Consumer 要从哪里获取 Provider 的地址 ... 
- 从零开始实现简单 RPC 框架 3:配置总线 URL
		URL 的定义 URL 对于大部分程序猿来说都是很熟悉的,其全称是 Uniform Resource Locator (统一资源定位器).它是互联网的统一资源定位标志,也就是指网络地址. 一个标准的 ... 
- Java实现简单RPC框架(转)
		一.RPC简介 RPC,全称Remote Procedure Call, 即远程过程调用,它是一个计算机通信协议.它允许像本地服务一样调用远程服务.它可以有不同的实现方式.如RMI(远程方法调用).H ... 
- RPC笔记之初探RPC:DIY简单RPC框架
		一.什么是RPC RPC(Remote Procedure Call)即远程过程调用,简单的说就是在A机器上去调用B机器上的某个方法,在分布式系统中极其常用. rpc原理其实很简单,比较容易理解,在r ... 
随机推荐
- QT从入门到入土(三)——文件的读写操作
			引言 文件的读写是很多应用程序具有的功能,甚至某些应用程序就是围绕着某一种格式文件的处 理而开发的,所以文件读写是应用程序开发的一个基本功能. Qt 提供了两种读写纯文本文件的基本方法: 用 QFi ... 
- 「CF505E」 Mr. Kitayuta vs. Bamboos
			「CF505E」 Mr. Kitayuta vs. Bamboos 传送门 如果没有每轮只能进行 \(k\) 次修改的限制或者没有竹子长度必须大于 \(0\) 的限制那么直接贪心就完事了. 但是很遗憾 ... 
- Django基础07篇 ORM操作
			1.新增(类似数据库操作的insert) # 新增 #方式一: models.Category.objects.create(name='MySQL') #方式二: c = models.Catego ... 
- 你好,我是B树
			一.什么是B树? B树是一棵是具备以下特点的有根树. 1.节点属性 a)x.n:为节点中存储的关键字个数. b)x.key:为节点中存储的关键字.x.key1.x.key2 ... x.keyx.n ... 
- vite插件-自动生成vue组件文档
			特点 支持热更新 快速启动,依赖于 vite,无需另起服务 自动生成组件导航 ui 采用了vant-ui的样式 核心方法覆盖率达到了 92.86% 使用 yarn add vite-plugin-vu ... 
- Spring RestTemplate 之post请求
			●post请求:在RestTemplate中,POST请求可以通过如下三个方法来发起,但post提交方式又有两种 formData 和 payLoad,而且接口设计与传统的浏览器使用的提交方式又有差异 ... 
- win10实现倒计时锁屏,休眠
			@ECHO OFF&SETLOCAL ENABLEDELAYEDEXPANSION SET /a s=10+1FOR /l %%i in (1,1,!s!) do ( SET /a s-=1 ... 
- NestJS WebSocket 开始使用
			使用NestJs提供WebSocket服务. 本文会在新建项目的基础上增加2个类 Gateway 实现业务逻辑的地方 WebSocketAdapter WebSocket适配器 新建项目 新建一个项目 ... 
- 全站 HTTPS 就一定安全了吗?
			随着网络技术手段不断地更新迭代,互联网安全对于企业和个人的重要性都越来越高.因此越来越多的服务商都开始偏向为用户提供更安全的在线内容访问. 中间人攻击 为了保障网站内容安全,诞生了不少加密方式.目前应 ... 
- 2021 NOI冬令营
			2021 NOI冬令营 -- 本来想写得稍微文艺一点的,但是停课这么久已经退化到不会写文章了. 毕竟省选了我才来补的,时间也过去很久了. 毕竟这次我没有获得任何奖项. 我唯一的获得就是-- --好好看 ... 
