09 | 网络通信优化之序列化:避免使用Java序列化
刘超

你好,我是刘超。
当前大部分后端服务都是基于微服务架构实现的。服务按照业务划分被拆分,实现了服务的解耦,但同时也带来了新的问题,不同业务之间通信需要通过接口实现调用。两个服务之间要共享一个数据对象,就需要从对象转换成二进制流,通过网络传输,传送到对方服务,再转换回对象,供服务方法调用。这个编码和解码过程我们称之为序列化与反序列化。
在大量并发请求的情况下,如果序列化的速度慢,会导致请求响应时间增加;而序列化后的传输数据体积大,会导致网络吞吐量下降。所以一个优秀的序列化框架可以提高系统的整体性能。
我们知道,Java 提供了 RMI 框架可以实现服务与服务之间的接口暴露和调用,RMI 中对数据对象的序列化采用的是 Java 序列化。而目前主流的微服务框架却几乎没有用到 Java 序列化,SpringCloud 用的是 Json 序列化,Dubbo 虽然兼容了 Java 序列化,但默认使用的是 Hessian 序列化。这是为什么呢?
今天我们就来深入了解下 Java 序列化,再对比近两年比较火的 Protobuf 序列化,看看 Protobuf 是如何实现最优序列化的。
Java 序列化
在说缺陷之前,你先得知道什么是 Java 序列化以及它的实现原理。
公开
同步至部落
取消
完成
0/2000
笔记
复制
AI
- 深入了解
- 翻译
- 解释
- 总结
仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《Java 性能调优实战》,新⼈⾸单¥59
《Java 性能调优实战》,新⼈⾸单¥59
立即购买
© 版权归极客邦科技所有,未经许可不得传播售卖。 页面已增加防盗追踪,如有侵权极客邦将依法追究其法律责任。
登录 后留言
全部留言(36)
- 最新
- 精选
- 陆离序列化会通过反射调用无参构造器返回一个新对象,破坏单例模式。 解决方法是添加readResolve()方法,自定义返回对象策略。
作者回复: 回答正确
7102 - 密码123456看到提问,才发现这竟然不是单例。回想内容是因为。可以把类路径上几乎所有实现了 Serializable 接口的对象都实例化。还真不知道怎么写?内部私有类实现,这种可以吗?
作者回复: 线上代码发生错位了,已修正。 导致这个问题的原因是序列化中的readObject会通过反射,调用没有参数的构造方法创建一个新的对象。 所以我们可以在被序列化类中重写readResolve方法。 private Object readResolve(){ return singleInstance; }
724 - 尔冬橙它会在反序列化过程中来验证序列化对象是否加载了反序列化的类,如果是具有相同类名的不同版本号的类,在反序列化中是无法获取对象的。老师,这句话能举个例子么,没太明白
作者回复: 在Class类文件中默认会有一个serialNo作为序列化对象的版本号,无论在序列化方还是在反序列化方的class类文件中都存在一个默认序列号,在序列化时,会将该版本号加载进去,在反序列化时,会校验该版本号。
9 - kevin老师请教下,为什么spring cloud不使用protobuf, thrift等性能更高、支持跨平台的序列化工具,而且使用json?
作者回复: springcloud是spring生态中的一部分,就目前spring生态很少引入非生态框架。但是我们可以自己实现springcloud兼容protobuf序列化。
7 - -W.LI-文中说Java序列化,不会序列化静态变量,这个单例的静态变量会被怎么处理啊?
作者回复: 是的,Java序列化会调用构造函数,构造出一个新对象
27 - waniz老师您好,Java序列化将数据转化为二进制字节流,json序列化将数据转化为json字符串。但是在物理层数据都是以电信号或模拟信号传输。那么从应用层到物理层数据的编码状态究竟是怎么变化的?出发点不同,最后都是二进制传输…忘解惑
作者回复: Java序列化是将Java对象转化为二进制流,而Json序列化是将Json字符串转为二进制的过程,只是包装的数据格式不一样。
26 - 天天向上想知道为什么用非Java的序列化方式的也需要实现Serializable接口?
作者回复: 这是Java说明需要序列化的一种标识
4 - 钱课后思考及问题 1:老师能深入细致的讲讲JAVA怎么实现序列化的嘛?比如:一个对象怎么一步步神奇的变成一个字节数组的?对象中的属性、属性值、方法、以及此对象的信息怎么变成一个字节数组的? 2:我们知道对象是通过在 ObjectInputStream 上调用 readObject() 方法进行反序列化的,这个方法其实是一个神奇的构造器,它可以将类路径上几乎所有实现了 Serializable 接口的对象都实例化。 这个神奇的构造器的实现原理是啥?一个字节数组他怎么将其转换为一个对象的?很好奇,他知道字节数组多少位表示啥意思?然后一段一段的取,一段的翻译嘛?老师给讲讲呗? 老师深入讲一下原理实现细节,API式的讲解不过瘾,和老师要深入理解的风格也不符呀😄
作者回复: 序列化是将一个对象通过某种数据结构包装好对象中的具体属性和值,转换为二进制进行网络传输的一个过程。例如一个int类型的属性,数组是1000,转换为二进制则是4个字节的byte数组了。 后面我会使用一个具体的例子来优化讲解这一讲。
3 - 晓杰不是单例,因为在反序列化的时候,会调用ObjectInputStream的readObject方法,该方法可以对实现序列化接口的类进行实例化,所以会破坏单例模式。 可以通过重写readResolve,返回单例对象的方式来避免这个问题
作者回复: 正确
21 - 尔冬橙序列化对象中加载反序列化的类怎么理解?
作者回复: 我也没有看懂这句话,请问在哪里看到的?
收起评论