目录

程序员子悠 · 好记性不如烂笔头

技术人生 X 人生技术

X

程序员常用的几种序列化方式,总有一个是你在用的

我们都知道程序在运行的过程中经常需要进行服务间的通信和交互,特别是在当下微服务的架构下,每个系统都会庞大那么为了提高服务间的通信效率以及数据传输的性能,我们往往都会将需要传输的数据进行序列化,然后再进行传输。

什么是序列化

关于序列化相信大家都很了解,在 Java 中我们经常就可以看到很多实体类或者 POJO 都会实现 Serializable 接口,有了解过 Serializable 接口的小伙伴应该都知道,这个接口是一个空接口,只是用来标记的。所谓序列化简单来说就是在传输对象之前将对象转换成二进制字节进行传输,接收端在收到二进制数据后再反序列化转化成普通对象。

所以说序列化最终的目的是为了对象可以跨平台存储和进行网络传输。之所以需要序列化是因为在网络传输的时候,我们需要经过 IO,而 IO 传输支持的就是字节数组这种格式,所以序列化过后可以更好的传输。另外反序列化就是根据字节数组反向生成对象,是一个逆向过程。

常见的序列化方式

既然知道了什么是序列化,那么接下来我们看看有哪些常见的序列化方式。

JSON

当下最流行的序列化方式无非是 JSON 了,而且 JSON 作为前后端交互使用最广泛的格式,形式如下。作为最通用的格式,各种语言都支持,并且可以支持复杂的对象。

{"name":"鸭血粉丝","age":4,"sex":"男"}

JSON 作为一个序列化方案,它的优点是可读性很高,跨平台跨语言支持;但是有个缺点那就是体积较大,很存在很多冗余内容,比如双引号,花括号。

相信JSON 大家在工作中使用的肯定会广泛,阿里提供的 fastjson 包是我们项目中必不可少的一个依赖。

<dependency>
   <groupId>com.alibaba</groupId>
   <artifactId>fastjson</artifactId>
</dependency>

XML

<?xml version="1.0"?>
<Person version="4.0">
	<name>鸭血粉丝</name>
	<age>4</age>
	<sex>男</sex>
</Person>

前些年不管是使用 SSM,还是使用 Spring 都会有很多 XML 的配置文件,现在很多被注解代替了,但是 XML 还是支持使用的。另外有一些广电或者银卡等老系统里面会有很多基于 XML 的协议开发的系统和服务。

阿粉之前做项目就遇到过银行的项目,里面都是很古老的 XML 协议,对接起来真是头疼呀~

通过上面例子我们可以看到,XML 协议的优缺点跟 JSON 类似,优点也是可读性很强,跨平台跨语言支持,缺点也是体积大,容易内容多。可以看到为了记录一个字段的值,每个标签都需要成对存在,过于冗余了。

Protobuf

Protobuf 是谷歌提出的一种序列化协议,Protobuf 是一种接口定义语言,它与语言和平台无关。它是一种序列化结构化数据并通过网络传输的方式,使用 Protobuf 传输二进制文件,与 JSON 的字符串格式相比,它提高了传输速度。

这里提到 Protobuf 是一种接口定义语言,说明也是一种语言,既然是语言那就有自己的关键字以及规则,所以对于Protobuf 协议,我们需要创建一个后缀为 .proto 的文件,在文件里面我们需要定义出我们的协议内容。

syntax = "proto2";
package com.demo;
message Request {
    required int32 version = 1;
    required string id = 2;
    message Model  {
        required int32 id = 1;
        required string pid = 2;
        optional int32 width = 3;
        optional int32 height = 4;
        optional int32 pos = 5;
    }
    repeated Model model = 3;
}

message 关键字表示定义一个结构体,required 表示必须,optional 表示可选,此外还有字段的名称和类型。这个原始的 proto 文件是通用的,只要定义一次就好,不管使用哪种语言都可以通过 proto 工具自动生成对应语言的代码。

比如要生成Java 代码,我们可以执行下面的命令

protoc --java_out=. demo.proto 就会在指定的目录下,生成对应的 Demo.java,想生成其他语言的代码,只需要修改命令执行的参数即可,生成的代码内容会有很多,可以不用管直接使用就行。

我们定义模型的结构一次,然后就可以使用生成的源代码轻松地使用 JavaPythonGoRubyC++ 等各种语言在各种数据流中写入和读取结构化数据。

Protobuf 的优点主要是性能高,体积小,缺点就是要学习一下特定的关键词以及要下载按照 Protobuf命令工具。

Thrift

Thrift 也是一种序列化协议,具体的使用方式跟 Protobuf类似,只不过 ThriftFacebook 提出来的一种协议。

Thrift是一种接口描述语言和二进制通讯协议,原由Facebook于2007年开发,2008年正式提交Apache基金会托管,成为Apache下的开源项目。

Thrift 是一个 RPC 通讯框架,采用自定义的二进制通讯协议设计。相比于传统的HTTP协议,效率更高,传输占用带宽更小。另外,Thrift是跨语言的。Thrift的接口描述文件,通过其编译器可以生成不同开发语言的通讯框架。

Thrift 的使用方式跟 Protobuf 类似,也是有一个 .thrift 后缀的文件,然后通过命令生成各种语言的代码,这里就不演示了。

除了上面提到的四种序列化方式之外,还有 HessianJDK 原生等序列化方式,就不一一介绍了。

序列化协议选择

前面提到是几种序列化的协议方式,那么对于我们平常项目中使用的时候,我们应该如何选择自己的协议呢?需要关注哪几个方面的内容呢?

每个协议有每个协议的特点,具体选择哪种协议我们要根据实际的场景来选择,比如说如果是前后端对接,那么自然是 JSON 最合适,应该网页的交互要求不需要太高,秒级别是可以接受的,所以我们可以更加关注可读性。但是如果是微服务之间的数据传输,那我们就可以选择 Protobuf 或者Thrift 这种更高效的协议来进行传输,因为这种场景我们对于协议序列化的体积和速度都有很高的要求。

总结

今天阿粉给大家介绍了几种序列化的协议,相信大家在日常工作中必然会用到,上面提到的协议你是否都用过呢?欢迎在评论区留言探讨。


标题:程序员常用的几种序列化方式,总有一个是你在用的
作者:zhuSilence
地址:https://home.zxsilence.cn/articles/2022/11/23/1669215632183.html