常见的序列化框架及Protobuf原理

常见的序列化框架

xml序列化

在java发展早期开始,为了统一接口,xml协议横空出世,良好的可读性,自由度极高的扩展性,成了很长一段时间的序列化标准规范。实现xml序列化/反序列化的方案有很多,最常见的是XStream 和 Java 自带的 XML 序列化和反序列化两种 ,并且还有基于xml协议的soap协议实现的webservice接口等。可以说xml序列化是开发中最常见也是发展时间最久的协议,并且支持跨进程和跨语言交互,但是缺陷也很明显,即xml规范下的每一个属性和值都是固定的标签形式,导致序列化后的字节流文件很大,远超于java自身的序列化方案,而且效率很低,一般建议使用在内部系统或者性能要求不高,但是对于接口的复杂度和准确性要求比较高的接口交互,或者适合多语言多进程之间交互的统一规范,不适合QPS过高的工程使用

JSON序列化

在xml序列化发展了多年后,也浮现了一些问题,比如开发并不简便,解析xml复杂度较高,还有xml的标准规范比较多,自由度过高,导致很难有效的指定格式校验等,于是一种新的轻量级的序列化交互的方案–JSON(JavaScript Object Notation)出现了,相对于xml来说,json格式语法简单,自由度较高,有很高的可读性,并且在JSON序列化后的字节流小于xml序列化的结果,解析起来更方便,于是基于JSON的接口成了新的标准规范之一,到现在也出现了很多JSON的序列化/反序列化的开源框架,比如开发中最常见到的Jackson、阿里巴巴开源的FastJson、谷歌的GSON等,而这三种框架各有优劣,通过测试一万个对象的序列化和反序列化的效率,对比如下:

序列化:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

反序列化:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

可以看出来序列化的时候,Gson的速度明显稍微慢了一些,Jackson反而最快,而在反序列化的时候,三个表现都很稳定,时间都差不多,但是当数据比较大的时候,测试结果又有所不同,测试结果和数据来自https://blog.csdn.net/Sword52888/article/details/81062575 提供的代码和脚本,可以得出对应结论:

  • 1、 当数据小于 100K 的时候,建议使用 Gson
  • 2、 当数据100K 与 1M 的之间时候,建议使用各个JSON引擎性能差不多
  • 3、 当数据大与 1M 的时候,建议使用 JackSon 与 FastJson

而在稳定性上面,默认情况下Gson在各种情况下的表现最好,Jackson配合对应的配置化也能达到很好的稳定性,而FastJson表现的不稳定,所以对于这几种json库的使用,建议环境较复杂场景下使用JackSon,加上自定义的配置化可以更灵活的处理更多的场景,但是在复杂度一般,仅仅在乎性能的场景下,建议使用FastJson,因为FastJson的api更易用,依赖少,简单场景下使用简单

Hessian序列化

Hessian是一个支持跨语言传输的二进制文本序列化协议,对比Java默认的序列化,Hessian的使用较简单,并且性能较高,现在的主流远程通讯框架几乎都支持Hessian,比如Dubbo,默认使用的就是Hessian,不过是Hessian的重构版

Avro序列化

Avro序列化设计初衷是为了支持大批量数据交换的应用,支持二进制序列化方式,并且自身提供了动态语言支持,可以更加便捷、快速处理大批量的Avro数据

Kyro序列化

Kyro序列化是主流的比较成熟的序列化方案之一,目前广泛使用在大数据组件中,比如Hive、Storm等,性能比起Hessian还要优越,但是缺陷较明显,不支持跨语言交互,在dubbo2.6.x版本开始已经加入了Kyro序列化的支持

Protobuf序列化

Protobuf是谷歌提出的序列化方案,不同的是此方案独立于语言、平台,谷歌提供了多个语言如java、c、go、python等语言的实现,也提供了多平台的库文件支持,使用比较广泛,优点在于性能开销很小,压缩率很高,但是缺陷也很明显,可读性很差,并且protobuf需要使用特定语言的库进行翻译转换,使用起来较为麻烦

Protobuf序列化的使用

首先现在使用Protobuf,有手动编译和maven依赖jar两种方案,实际开发中我们一般使用maven坐标引入jar,坐标如下:

com.dyuproject.protostuff protostuff-core 1.0.8 com.dyuproject.protostuff protostuff-runtime 1.0.8

编写一个便捷的序列化转换工具类:

package com.demo.utils;

import com.dyuproject.protostuff.LinkedBuffer;
import com.dyuproject.protostuff.ProtobufIOUtil;
import com.dyuproject.protostuff.runtime.RuntimeSchema;

public class SerializeUtils{
/**
*序列化方法
/
public static byte[] serialize(T t,Class clazz) {
return ProtobufIOUtil.toByteArray(t, RuntimeSchema.createFrom(clazz),
LinkedBuffer.allocate(LinkedBuffer.DEFAULT_BUFFER_SIZE));
}
/

**反序列化方法
*/
public static T deSerialize(byte[] data,Class clazz) {
RuntimeSchema runtimeSchema = RuntimeSchema.createFrom(clazz);
T t = runtimeSchema.newMessage();
ProtobufIOUtil.mergeFrom(data, t, runtimeSchema);
return t;
}

使用的时候直接使用工具类进行自动的转换传输即可

注:使用的时候注意jdk版本和jar版本的兼容问题,并且需要序列化的实体并不需要实现Serializable 接口

当然,我们接下来手动编译protobuf使用,了解下protobuf的语法以及原理

手动编译Protobuf

手动编译protobuf我们需要一个Protobuf编译器的支持,这里推荐直接点击地址,在github上下载:

https://github.com/google/protobuf/releases

或者直接百度云:http://pan.baidu.com/s/1gefsM9X 下载,这里博主选择直接百度云集成的环境下载

1:解压protoc-3.0.0-beta-2-win32会得到一个protoc.exe的文件.

2:解压protobuf-3.0.0-beta-2.(3.0.0-beta是版本号,可能会有所不同)

3.将protoc.exe文件放到2步骤解压后文件夹java/src/这个目录里面(src里面,不是跟src并级)

4.WINDOS+R 输入cmd命令并切换至3步骤的src目录的上级目录,就是java目录下会发现这个目录有个POM文件,使用maven编译命令编译(mvn install),然后会在java目录下生成target以及一个jar。OK到目前位置,安装算完成了

接下来是编译环节,将上面生成的那个jar和一开始的那个exe文件放到需要编译文件的同一目录下 ,使用编译指令(cmd):

protoc --java_out=xxx/xxx.proto

如果出现:Missing input file错误,那么就使用 以下指令:

protoc xxx/xxx.proto --java_out=./

接下来,我们开始编写一个protobuf的简单demo,后缀为proto,代码如下:

syntax=“proto2”;
package com.demo.serial;
option java_package = “com.demo.serial”;
option java_outer_classname=“UserProtos”;
message User {
required string name=1;
required int32 age=2;
}

首先我们先看看上面编写的内容分别代表什么意思:

syntax=“proto2”;

这里指定了protobuf编译的版本,目前主流为proto2,当然也有不少选择最新的proto3版本,而每个大版本之间的差异还是很大的,具体区别参见官方说明:https://developers.google.com/protocol-buffers/docs/proto3

接着是:

option java_package = “com.demo.serial”

这里指定的是上一行我们设置的package对应java文件里面的package名称

option java_outer_classname=“UserProtos”

这里指定了如果编译完毕生成的java类的名称

message User

这里的message代表给User类指定对应属性类型

required string name=1

这里出现了一个特殊的修饰符类型required,在protobuf中,有如下几种修饰符:

  • required: 格式良好的 message 必须包含该字段一次。
  • optional: 格式良好的 message 可以包含该字段零次或一次(不超过一次)。
  • repeated: 该字段可以在格式良好的消息中重复任意多次(包括零)。其中重复值的顺序会被保留。

注意:在proto3版本中,为了兼容性考虑,required修饰符已经取消

完成这些以后,我们使用指令:

protoc --java_out=xxx/xxx.proto

生成protobuf转换后的实体类,然后我们在pom中引入:

com.google.protobuf protobuf.java 3.7.0

然后进行序列化:

UserProtos.User user=UserProtos.User.newBuilder().setAge(300).setName(“Mic”).build();
byte[] bytes=user.toByteArray();
for(byte bt:bytes){
System.out.print(bt+" ");
}

我们将这个结果打印出来的字节如下:

10 3 77 105 99 16 -84 2

可以看出来序列化的数值看不明白,但是的确字节数很小,说明protobuf进行了算法压缩,那么我们就要了解下protobuf压缩算法相关的详细操作,首先我们要知道protobuf的type对应的各个语言的类型:

.proto TypeNotesC++ TypeJava TypePython Type[2]Go Type
doubledoubledoublefloat*float64
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则近万的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

img

img

img

img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)

总结

其实要轻松掌握很简单,要点就两个:

  1. 找到一套好的视频资料,紧跟大牛梳理好的知识框架进行学习。
  2. 多练。 (视频优势是互动感强,容易集中注意力)

你不需要是天才,也不需要具备强悍的天赋,只要做到这两点,短期内成功的概率是非常高的。

对于很多初中级Android工程师而言,想要提升技能,往往是自己摸索成长,不成体系的学习效果低效漫长且无助。

以上就是总结的关于在面试的一些总结,希望对大家能有些帮助,除了这些面试中需要注意的问题,当然最重要的就是刷题了,这里放上我之前整理的一份超全的面试专题PDF

还有 高级架构技术进阶脑图、Android开发面试专题资料,高级进阶架构资料 帮助大家学习提升进阶,也节省大家在网上搜索资料的时间来学习,也可以分享给身边好友一起学习。

【Android核心高级技术PDF文档,BAT大厂面试真题解析】

这里只是整理出来的部分面试题,后续会持续更新,希望通过这些高级面试题能够降低面试Android岗位的门槛,让更多的Android工程师理解Android系统,掌握Android系统。喜欢的话麻烦点击一个喜欢在关注一下~

《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》,点击传送门即可获取!

存中…(img-vivo4snA-1712406502946)]

这里只是整理出来的部分面试题,后续会持续更新,希望通过这些高级面试题能够降低面试Android岗位的门槛,让更多的Android工程师理解Android系统,掌握Android系统。喜欢的话麻烦点击一个喜欢在关注一下~

《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》,点击传送门即可获取!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值