今天分享一道读者面试招银网络科技遇到的面试真题。

下面是正文。

序列化和反序列化相关概念

什么是序列化?什么是反序列化?

如果我们需要持久化 Java 对象比如将 Java 对象保存在文件中,或者在网络上传输 Java 对象,这些场景都需要用到序列化。

简单来说:

  • 序列化:将数据结构或对象转换成二进制字节流的过程
  • 反序列化:将在序列化过程中所生成的二进制字节流的过程转换成数据结构或者对象的过程

对于 Java 这种面向对象编程语言来说,我们序列化的都是对象(Object)也就是实例化后的类(Class),但是在 C++这种半面向对象的语言中,struct(结构体)定义的是数据结构类型,而 class 对应的是对象类型。

维基百科是如是介绍序列化的:

序列化(serialization)在计算机科学的数据处理中,是指将数据结构或对象状态转换成可取用格式(例如存成文件,存于缓冲,或经由网络中发送),以留待后续在相同或另一台计算机环境中,能恢复原先状态的过程。依照序列化格式重新获取字节的结果时,可以利用它来产生与原始对象相同语义的副本。对于许多对象,像是使用大量引用的复杂对象,这种序列化重建的过程并不容易。面向对象中的对象序列化,并不概括之前原始对象所关系的函数。这种过程也称为对象编组(marshalling)。从一系列字节提取数据结构的反向操作,是反序列化(也称为解编组、deserialization、unmarshalling)。

综上:序列化的主要目的是通过网络传输对象或者说是将对象存储到文件系统、数据库、内存中。

https://www.corejavaguru.com/java/serialization/interview-questions-1

实际开发中有哪些用到序列化和反序列化的场景?

  1. 对象在进行网络传输(比如远程方法调用 RPC 的时候)之前需要先被序列化,接收到序列化的对象之后需要再进行反序列化;
  2. 将对象存储到文件中的时候需要进行序列化,将对象从文件中读取出来需要进行序列化。
  3. 将对象存储到缓存数据库(如 Redis)时需要用到序列化,将对象从缓存数据库中读取出来需要反序列化。

序列化协议对应于 TCP/IP 4 层模型的哪一层?

我们知道网络通信的双方必须要采用和遵守相同的协议。TCP/IP 四层模型是下面这样的,序列化协议属于哪一层呢?

  1. 应用层
  2. 传输层
  3. 网络层
  4. 网络接口层

TCP/IP 4层模型

如上图所示,OSI 七层协议模型中,表示层做的事情主要就是对应用层的用户数据进行处理转换为二进制流。反过来的话,就是将二进制流量转换成应用层的用户数据。这不就对应的是序列化和反序列化么?

因为,OSI 七层协议模型中的应用层、表示层和会话层对应的都是 TCP/IP 四层模型中的应用层,所以序列化协议属于 TCP/IP 协议应用层的一部分。

常见序列化协议对比

JDK 自带的序列化方式一般不会用 ,因为序列化效率低并且部分版本有安全漏洞。比较常用的序列化协议有 hessian、kyro、protostuff。

下面提到的都是基于二进制的序列化协议,像 JSON 和 XML 这种属于文本类序列化方式。虽然 JSON 和 XML 可读性比较好,但是性能较差,一般不会选择。

JDK 自带的序列化方式

JDK 自带的序列化,只需实现 java.io.Serializable接口即可。

@AllArgsConstructor
@NoArgsConstructor
@Getter
@Builder
@ToString
public class RpcRequest implements Serializable {private static final long serialVersionUID = 1905122041950251207L;private String requestId;private String interfaceName;private String methodName;private Object[] parameters;private Class<?>[] paramTypes;private RpcMessageTypeEnum rpcMessageTypeEnum;
}

序列化号 serialVersionUID 属于版本控制的作用。序列化的时候 serialVersionUID 也会被写入二级制序列,当反序列化时会检查 serialVersionUID 是否和当前类的 serialVersionUID 一致。如果 serialVersionUID 不一致则会抛出 InvalidClassException 异常。强烈推荐每个序列化类都手动指定其 serialVersionUID,如果不手动指定,那么编译器会动态生成默认的序列化号

我们很少或者说几乎不会直接使用这个序列化方式,主要原因有两个:

  1. 不支持跨语言调用 : 如果调用的是其他语言开发的服务的时候就不支持了。
  2. 性能差 :相比于其他序列化框架性能更低,主要原因是序列化之后的字节数组体积较大,导致传输成本加大。

Kryo

Kryo 是一个高性能的序列化/反序列化工具,由于其变长存储特性并使用了字节码生成机制,拥有较高的运行速度和较小的字节码体积。

另外,Kryo 已经是一种非常成熟的序列化实现了,已经在 Twitter、Groupon、Yahoo 以及多个著名开源项目(如 Hive、Storm)中广泛的使用。

guide-rpc-framework[1] 就是使用的 kyro 进行序列化,序列化和反序列化相关的代码如下:

/*** Kryo serialization class, Kryo serialization efficiency is very high, but only compatible with Java language** @author shuang.kou* @createTime 2020年05月13日 19:29:00*/
@Slf4j
public class KryoSerializer implements Serializer {/*** Because Kryo is not thread safe. So, use ThreadLocal to store Kryo objects*/private final ThreadLocal<Kryo> kryoThreadLocal = ThreadLocal.withInitial(() -> {Kryo kryo = new Kryo();kryo.register(RpcResponse.class);kryo.register(RpcRequest.class);return kryo;});@Overridepublic byte[] serialize(Object obj) {try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();Output output = new Output(byteArrayOutputStream)) {Kryo kryo = kryoThreadLocal.get();// Object->byte:将对象序列化为byte数组kryo.writeObject(output, obj);kryoThreadLocal.remove();return output.toBytes();} catch (Exception e) {throw new SerializeException("Serialization failed");}}@Overridepublic <T> T deserialize(byte[] bytes, Class<T> clazz) {try (ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);Input input = new Input(byteArrayInputStream)) {Kryo kryo = kryoThreadLocal.get();// byte->Object:从byte数组中反序列化出对对象Object o = kryo.readObject(input, clazz);kryoThreadLocal.remove();return clazz.cast(o);} catch (Exception e) {throw new SerializeException("Deserialization failed");}}}

Github 地址:https://github.com/EsotericSoftware/kryo[2] 。

Protobuf

Protobuf 出自于 Google,性能还比较优秀,也支持多种语言,同时还是跨平台的。就是在使用中过于繁琐,因为你需要自己定义 IDL 文件和生成对应的序列化代码。这样虽然不然灵活,但是,另一方面导致 protobuf 没有序列化漏洞的风险。

Protobuf 包含序列化格式的定义、各种语言的库以及一个 IDL 编译器。正常情况下你需要定义 proto 文件,然后使用 IDL 编译器编译成你需要的语言

一个简单的 proto 文件如下:

// protobuf的版本
syntax = "proto3";
// SearchRequest会被编译成不同的编程语言的相应对象,比如Java中的class、Go中的struct
message Person {//string类型字段string name = 1;// int 类型字段int32 age = 2;
}

Github 地址:https://github.com/protocolbuffers/protobuf[3]

ProtoStuff

由于 Protobuf 的易用性,它的哥哥 Protostuff 诞生了。

protostuff 基于 Google protobuf,但是提供了更多的功能和更简易的用法。虽然更加易用,但是不代表 ProtoStuff 性能更差。

Github 地址:https://github.com/protostuff/protostuff[4]

hession

hessian 是一个轻量级的,自定义描述的二进制 RPC 协议。hessian 是一个比较老的序列化实现了,并且同样也是跨语言的。

dubbo RPC 默认启用的序列化方式是 hession2 ,但是,Dubbo 对 hessian2 进行了修改,不过大体结构还是差不多。

总结

Kryo 是专门针对 Java 语言序列化方式并且性能非常好,如果你的应用是专门针对 Java 语言的话可以考虑使用,并且 Dubbo 官网的一篇文章中提到说推荐使用 Kryo 作为生产环境的序列化方式。(文章地址:https://dubbo.apache.org/zh/docs/v2.7/user/references/protocol/rest/[5])

像 Protobuf、 ProtoStuff、hession 这类都是跨语言的序列化方式,如果有跨语言需求的话可以考虑使用。

除了我上面介绍到的序列化方式的话,还有像 Thrift,Avro 这些。

其他推荐阅读

  • 美团技术团队-序列化和反序列化:https://tech.meituan.com/2015/02/26/serialization-vs-deserialization.html[6]
  • 在 Dubbo 中使用高效的 Java 序列化(Kryo 和 FST):https://dubbo.apache.org/zh-cn/docs/user/serialization.html[7]

参考资料

[1]

guide-rpc-framework: https://github.com/Snailclimb/guide-rpc-framework

[2]

https://github.com/EsotericSoftware/kryo: https://github.com/EsotericSoftware/kryo

[3]

https://github.com/protocolbuffers/protobuf: https://github.com/protocolbuffers/protobuf

[4]

https://github.com/protostuff/protostuff: https://github.com/protostuff/protostuff

[5]

https://dubbo.apache.org/zh/docs/v2.7/user/references/protocol/rest/:https://dubbo.apache.org/zh/docs/v2.7/user/references/protocol/rest/

[6]

https://tech.meituan.com/2015/02/26/serialization-vs-deserialization.html: https://tech.meituan.com/2015/02/26/serialization-vs-deserialization.html

[7]

https://dubbo.apache.org/zh-cn/docs/user/serialization.html: https://dubbo.apache.org/zh-cn/docs/user/serialization.html

·········· END ············

招银网络二面:什么是序列化?常见的序列化协议有哪些?相关推荐

  1. 招银网络科技杭州 java_招银网络科技_杭州Java后端_视频一、二面,HR面

    2020-7-28HR面 在别人面过HR面之后的一周,收到了HR面的通知.大概是7.24收到的吧. 自我介绍 为什么不读博士? 为什么投招银?了解招银网络科技吗? 平时的作息? 他们是995,问能否接 ...

  2. 招银网络科技java春招二面_招银网络科技 2019春招笔试题复盘

    因本人刚开始写博客,学识经验有限,如有不正之处望读者指正,不胜感激:也望借此平台留下学习笔记以温故而知新.这篇博客是复盘回忆招银网络科技2019春招的笔试试题类型,相关岗位:算法工程师. 简要介绍:时 ...

  3. 招银网络---C++

    基本情况信息 1.自我介绍 2.项目介绍 3.为什么要做测试,不去做开发 4.测试需要哪些技能 需要一定的代码能力.了解计算机网络TCP/IP协议.熟悉数据库.软件测试的基础理论.协调沟通能力 5.找 ...

  4. 杭州c语言开发招聘,杭州招银网络科技

    为了帮助职业圈网友能够及时了解杭州招银网络科技的面试流程以及面试过程所涉及的面试问题,职业圈小编把刚获得的杭州招银网络科技面试经验马上编辑好,快速提供给大家,以便能够尽快帮助到有需要的人.这次面试总共 ...

  5. 一个妹子的招银网络科技Java后台开发面经

    基本情况 妹子985非科班硕士,秋招Java后台开发,先后投递了招银网络科技,招行***中心,招行总行的岗位和招行杭州分行. 招行有很多机构,这些机构之间可同时投递多个,面试可并行进行,也可以同时拿多 ...

  6. 生化环材非科班,自学算法,秋招拿腾讯美团网易华为招银网络意向书

    目录 个人简介 why 转行? why 算法? 学习之路漫漫 what is 算法? 疫情 实习 秋招 一点建议 写在最后 个人简介 本人本硕top10 985,生化环材非科班,在课题组内没有任何与代 ...

  7. 2021届招银网络科技提前批笔试

    2021届招银网络科技提前批笔试 写在前面: 第一次参加笔试,结果不重要,就当作是积累经验啦~ 有一些坑记录下来,后面的人看到也可以注意一下: 1.每部分题目是不能往回翻页的,就是说你不能想着做完了后 ...

  8. 招银网络笔试java_2020招银网络科技校园招聘常见问题

    关于简历投递方面问题 Q:我可以申请几个校招职位? A:本次校园招聘您最多只能申请1个职位,因此建议明确自己希望应聘的岗位. Q:简历提交之后,我还能进行修改? A:简历状态为"简历评估&q ...

  9. 招银网络2018笔试分享

    招银网络笔试时间两个半小时,两个小时的技能笔试和半个小时的性格测试.这里主要和大家分享一下技能笔试的内容. Part1. 30道单选 这三道单选涉及到Java,C++,多线程,算法,数据结构,CPU, ...

最新文章

  1. python3字典详解_python3中字典详解
  2. 2019年首趟春运年货集装箱班列抵达北京
  3. mysql5.5更改端口后初始化_centos7 修改mysql5.7默认端口后启动异常
  4. BZOJ 4551树题解
  5. IMP-00017: 由于 ORACLE 错误 6550解决办法
  6. Linux 命令(48)—— stat 命令
  7. 第十七周项目2-引用作形参
  8. Chrome 新功能:因更新或崩溃而重启后,PWA应用将自动恢复运行!
  9. cdn 内容分发 资源放在更接近用户的网络边缘
  10. python实现找到给定列表中满足给定和的所有子列表,元素可重复使用
  11. creo5.0安装教程(图文详解)
  12. 爬取中国地震网地震数据
  13. Icode编程>>>Python编程>>>1级训练场>>>基础训练【1】
  14. js 浏览器永久保存数据:localStorage
  15. sqlconnection mysql_深入sql数据连接时的一些问题分析
  16. 机器学习训练素材_广告素材在编码训练营中导航的5条提示
  17. Zend Studio 10.6.0正式版注册破解
  18. 阿里云轻量云服务器部署java项目
  19. java实现导出内容不固定的word文档
  20. 友价源码怎么样主动提交链接给百度?

热门文章

  1. android蓝牙编程资料搜集
  2. Swagger-springFox3.0使用教程
  3. WCF 跨域问题解决方案
  4. win7下JDK环境变量设置方法
  5. 弘辽科技:提升销量能增加店铺权重吗?如何做好?
  6. Android View体系(2)
  7. 戴德金--连续性和无理数--我自己做的中文翻译第3页
  8. 反爬虫策略调研与分析
  9. 人工智能深度学习火起来的原因
  10. (我决定发N个在线播放的电影出来,当然是免费以稳定,速度又快的)□ 影片名:《野兽刑警》(24794)