序列化:对象怎么在网络中传输?

简介: 本讲深入讲解RPC框架中的序列化机制,介绍为何需将对象转为二进制进行网络传输,并解析JDK原生、JSON、Hessian等常用序列化方式的原理与优劣,帮助你在不同场景下合理选择,提升系统性能与稳定性。

上一讲我讲解了在 RPC 框架中,如何设计可扩展的、向后兼容的协议,其关键点就是利用好 Header 中的扩展字段以及 Payload 中的扩展字段,通过扩展字段向后兼容。
那么承接上一讲的一个重点,今天我会讲解下 RPC 框架中的序列化。要知道,在不同的场景下合理地选择序列化方式,对提升 RPC 框架整体的稳定性和性能是至关重要的。
为什么需要序列化?
首先,我们得知道什么是序列化与反序列化。我们先回顾下 第 01 讲 介绍过的 RPC 原理的内容,在描述 RPC 通信流程的时候我说过:
网络传输的数据必须是二进制数据,但调用方请求的出入参数都是对象。对象是不能直接在网络中传输的,所以我们需要提前把它转成可传输的二进制,并且要求转换算法是可逆的,这个过程我们一般叫做 序列化。 这时,服务提供方就可以正确地从二进制数据中分割出不同的请求,同时根据请求类型和序列化类型,把二进制的消息体逆向还原成请求对象,这个过程我们称之为 反序列化。这两个过程如下图所示:

总结来说,序列化就是将对象转换成二进制数据的过程,而反序列就是反过来将二进制转换为对象的过程。那么 RPC 框架为什么需要序列化呢?还是请你回想下 RPC 的通信流程:

不妨借用个例子帮助你理解:比如发快递,我们要发一个需要自行组装的物件。发件人发之前,会把物件拆开装箱,这就好比序列化;这时候快递员来了,不能磕碰呀,那就要打包,这就好比将序列化后的数据进行编码,封装成一个固定格式的协议;过了两天,收件人收到包裹了,就会拆箱将物件拼接好,这就好比是协议解码和反序列化。
所以现在你清楚了吗?因为网络传输的数据必须是二进制数据,所以在 RPC 调用中,对入参对象与返回值对象进行序列化与反序列化是一个必须的过程。
有哪些常用的序列化?
那这么看来,你会不会觉得这个过程很简单呢?实则不然,很复杂。我们可以先看看都有哪些常用的序列化,下面我来简单地介绍下几种常用的序列化方式。
JDK 原生序列化
如果你会使用 Java 语言开发,那么你一定知道 JDK 原生的序列化,下面是 JDK 序列化的一个例子:
import java.io.*;
public class Student implements Serializable {
//学号
private int no;
//姓名
private String name;
public int getNo() {
return no;
}
public void setNo(int no) {
this.no = no;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Student{" +
"no=" + no +
", name='" + name + '\'' +
'}';
}
public static void main(String[] args) throws IOException, ClassNotFoundException {
String home = System.getProperty("user.home");
String basePath = home + "/Desktop";
FileOutputStream fos = new FileOutputStream(basePath + "student.dat");

    Student student = new Student();
    student.setNo(100);
    student.setName("TEST_STUDENT");

    ObjectOutputStream oos = new ObjectOutputStream(fos);
    oos.writeObject(student);
    oos.flush();
    oos.close();

    FileInputStream fis = new FileInputStream(basePath + "student.dat");
    ObjectInputStream ois = new ObjectInputStream(fis);
    Student deStudent = (Student) ois.readObject();
    ois.close();

    System.out.println(deStudent);
}

}
我们可以看到,JDK 自带的序列化机制对使用者而言是非常简单的。序列化具体的实现是由 ObjectOutputStream 完成的,而反序列化的具体实现是由 ObjectInputStream 完成的。
那么 JDK 的序列化过程是怎样完成的呢?我们看下下面这张图:
序列化过程就是在读取对象数据的时候不断加入特殊分隔符,这些分隔符用于在反序列化过程中截断用
● 头部数据用来声明序列化协议、序列化版本,用于高低版本向后兼容
● 对象数据主要包括类名、签名、属性名、属性类型及属性值,当然还有开头结尾等数据,除了属性值属于真正的对象值,其他都是为了反序列化用的元数据
● 存在对象引用、继承的情况下,就是递归遍历「写对象」逻辑
实际上任何一种序列化框架,核心思想就是设计一种序列化协议,将对象的类型、属性类型、属性值一一按照固定的格式写到二进制字节流中来完成序列化,再按照固定的格式一一读出对象的类型、属性类型、属性值,通过这些信息重新创建出一个新的对象,来完成反序列化。
JSON
JSON 可能是我们最熟悉的一种序列化格式了,JSON 是典型的 Key-Value 方式,没有数据类型,是一种文本型序列化框架,JSON 的具体格式和特性,网上相关的资料非常多,这里就不再介绍了。
他在应用上还是很广泛的,无论是前台 Web 用 Ajax 调用、用磁盘存储文本类型的数据,还是基于 HTTP 协议的 RPC 框架通信,都会选择 JSON 格式。但用 JSON 进行序列化有这样两个问题,你需要格外注意:
● JSON 进行序列化的额外空间开销比较大,对于大数据量服务这意味着需要巨大的内存和磁盘开销;
● JSON 没有类型,但像 Java 这种强类型语言,需要通过反射统一解决,所以性能不会太好。
所以如果 RPC 框架选用 JSON 序列化,服务提供者与服务调用者之间传输的数据量要相对较小,否则将严重影响性能。
Hessian
Hessian 是动态类型、二进制、紧凑的,并且可跨语言移植的一种序列化框架。Hessian 协议要比 JDK、JSON 更加紧凑,性能上要比 JDK、JSON 序列化高效很多,而且生成的字节数也更小。代码示例如下:

相关文章
|
人工智能 物联网
AI 绘画Stable Diffusion 研究(十七)SD lora 详解(上)
AI 绘画Stable Diffusion 研究(十七)SD lora 详解(上)
4043 0
|
前端开发 算法 开发工具
Git分支批量清理利器:自定义命令行插件实战
Git分支批量清理利器:自定义命令行插件实战
557 0
|
消息中间件 移动开发 JavaScript
JSBridge:混合开发中的双向通信[Android、iOS&JavaScript]
WebView 是移动端中的一个控件,它为 JS 运行提供了一个沙箱环境。WebView 能够加载指定的 url,拦截页面发出的各种请求等各种页面控制功能,JSB 的实现就依赖于 WebView 暴露的各种接口。由于历史原因,IOS以8为分界,Android以4.4为分界,分为高低两个版本。而它们的区别在于 —— 回调。高版本可以通过执行回调拿到 JS 执行完毕的返回值,然后准确进行下一步操作。而低版本无法执行回调!Hybrid App 的核心。
JSBridge:混合开发中的双向通信[Android、iOS&JavaScript]
|
安全 数据库 存储
数据库设计基石:一文搞懂 1NF、2NF、3NF 三大范式
数据库设计常遇数据冗余、增删改异常?根源往往是表结构不规范。本文带你轻松掌握数据库三大范式——1NF、2NF、3NF,从原子列到消除依赖,层层递进,提升数据一致性与可维护性,让数据库设计更高效、安全!#数据库 #范式设计
4846 0
|
Ubuntu Python
【Python】报错ModuleNotFoundError: No module named ‘XXX‘
【Python】报错ModuleNotFoundError: No module named ‘XXX‘
|
Shell 开发工具 git
解决Git中没有小绿勾与红叉叉的问题
找到下面这个地址:\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\ShellIconOverlayIdentifiers。后产生的,要在圈住的这几个在前面,添加空格(右击重命名加空格就能使它提到前面)关于要添加几个空格的问题,一般来说添加四个或者八个就可以。然后,重启电脑就能产生小绿勾和红叉叉的图标了。运行完重启电脑就好使。注意这一步一定要操作对,操作错误就会很多麻烦。寻找与自己电脑相配的软件版本就可以了。
2652 0
|
JavaScript
在Vue项目中vue-quill-editor的安装与使用【详细图解+过程+包含图片的缩放拖拽】
文章详细介绍了在Vue项目中安装和使用`vue-quill-editor`的步骤,包括如何通过npm安装、局部挂载、在Vue页面中引入和配置使用。同时,还提供了如何实现图片的缩放和拖拽功能的进阶教程,涉及到安装额外的插件`quill-image-drop-module`和`quill-image-resize-module`,以及对Webpack配置的调整。最后,文章还提供了实际效果展示和一些后续可能的拓展功能,如上传视频和将图片上传到服务器等。
在Vue项目中vue-quill-editor的安装与使用【详细图解+过程+包含图片的缩放拖拽】
|
人工智能 前端开发 API
基于Web Speech API给AI语言模型加上语音功能,距离MOSS又近了一步
基于Web Speech API给AI语言模型加上语音功能,距离MOSS又近了一步
956 0

热门文章

最新文章