当前位置:网站首页>对象序列化
对象序列化
2022-06-27 11:56:00 【瑾琳】
什么是对象序列化?
序列化(Serialization)是将对象的状态信息转换为可以存储或传输的形式的过程.
这是百度百科的说明,也很浅显易懂,比如说,我有一个java对象,我想传输给远端的程序,如何传输尼?
java提供了序列化接口,只要实现了Serializable接口,就可将java对象序列化成字节,然后以流的形式传输,然后在远端再反序列化成对象,这就达到了传输消息的目的.
但是这种序列化存在一些缺陷,1不能跨语言,2,序列化体积大
所以为了支持跨语言,并提高序列效率,减少传输时的码流大小,好多公司或者大神开发了各种序列化库,hession,protostuff,kryo,jackson,xml等,比如json也算是一种序列化,方式,也是目前使用的最为广泛的一种,但是json严格来说并不是一种序列化,它只是一种通用的信息描述方式,一组json信息,可能对应不同的对象模式.比如你可以将一组json转换成java bean对象也可以转换成map,形式具有不确定性.所以一般的远程调用不会采用json来作为序列化实现.
| 序列类型 | 是否跨语言 | 优缺点 |
|---|---|---|
| hession | 支持 | 跨语言,序列化后体积小,速度较快 |
| protostuff | 支持 | 跨语言,序列化后体积小,速度快,但是需要Schema,可以动态生成 |
| jackson | 支持 | 跨语言,序列化后体积小,速度较快,且具有不确定性 |
| fastjson | 支持 | 跨语言支持较困难,序列化后体积小,速度较快,只支持java,c# |
| kryo | 支持 | 跨语言支持较困难,序列化后体积小,速度较快 |
| fst | 不支持 | 跨语言支持较困难,序列化后体积小,速度较快,兼容jdk |
|jdk|不支持|序列化后体积很大,速度快|
序列化可以做什么?
如第一节提的一样,对象序列化可以用来传输消息,并且以流的形式传输,提高传输效率,使用场景如远程服务调用rpc
各个序列化库比较
0.准备依赖
<!-- protostuff -->
<dependency>
<groupId>com.dyuproject.protostuff</groupId>
<artifactId>protostuff-core</artifactId>
<version>1.0.8</version>
</dependency>
<dependency>
<groupId>com.dyuproject.protostuff</groupId>
<artifactId>protostuff-runtime</artifactId>
<version>1.0.8</version>
</dependency>
<!-- objenesis(support protostuff,可以使用无参构造方法) -->
<dependency>
<groupId>org.objenesis</groupId>
<artifactId>objenesis</artifactId>
<version>2.1</version>
</dependency>
<!-- hessian -->
<dependency>
<groupId>com.caucho</groupId>
<artifactId>hessian</artifactId>
<version>4.0.38</version>
</dependency>
<!-- jackson -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.0</version>
</dependency>
<!-- fastjson-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.47</version>
</dependency>
<!-- kryo -->
<dependency>
<groupId>com.esotericsoftware</groupId>
<artifactId>kryo</artifactId>
<version>4.0.0</version>
</dependency>
<!-- fst -->
<dependency>
<groupId>de.ruedigermoeller</groupId>
<artifactId>fst</artifactId>
<version>2.57</version>
</dependency>1.编写序列化接口
public interface Serializer {
<T> byte[] serialize(T obj);
<T> Object deserialize(byte[] bytes, Class<T> clazz);
}2.实现接口
hession实现
public class HessianSerializer implements Serializer {
@Override
public <T> byte[] serialize(T obj){
ByteArrayOutputStream os = new ByteArrayOutputStream();
HessianOutput ho = new HessianOutput(os);
try {
ho.writeObject(obj);
} catch (IOException e) {
throw new IllegalStateException(e.getMessage(), e);
}
return os.toByteArray();
}
@Override
public <T> Object deserialize(byte[] bytes, Class<T> clazz) {
ByteArrayInputStream is = new ByteArrayInputStream(bytes);
HessianInput hi = new HessianInput(is);
try {
return hi.readObject();
} catch (IOException e) {
throw new IllegalStateException(e.getMessage(), e);
}
}
}jackson实现
public class JacksonSerializer implements Serializer {
private final static ObjectMapper objectMapper = new ObjectMapper();
@Override
public <T> byte[] serialize(T obj) {
try {
return objectMapper.writeValueAsBytes(obj);
} catch (JsonProcessingException e) {
throw new IllegalStateException(e.getMessage(), e);
}
}
@Override
public <T> Object deserialize(byte[] bytes, Class<T> clazz) {
try {
return objectMapper.readValue(bytes, clazz);
} catch (JsonParseException e) {
throw new IllegalStateException(e.getMessage(), e);
} catch (JsonMappingException e) {
throw new IllegalStateException(e.getMessage(), e);
} catch (IOException e) {
throw new IllegalStateException(e.getMessage(), e);
}
}
}fastjson实现
import com.alibaba.fastjson.JSON;
public class FastJsonSerializer implements Serializer {
@Override
public <T> byte[] serialize(T obj) {
try {
return JSON.toJSONBytes(obj);
} catch (Exception e) {
throw new IllegalStateException(e.getMessage(), e);
}
}
@Override
public <T> Object deserialize(byte[] bytes, Class<T> clazz) {
try {
return JSON.parseObject(bytes, clazz);
} catch (Exception e) {
throw new IllegalStateException(e.getMessage(), e);
}
}
}prostfuff实现
public class ProtostuffSerializer implements Serializer {
private static Objenesis objenesis = new ObjenesisStd(true);
private static Map<Class<?>, Schema<?>> cachedSchema = new ConcurrentHashMap<Class<?>, Schema<?>>();
private static <T> Schema<T> getSchema(Class<T> cls) {
@SuppressWarnings("unchecked")
Schema<T> schema = (Schema<T>) cachedSchema.get(cls);
if (schema == null) {
schema = RuntimeSchema.createFrom(cls);
if (schema != null) {
cachedSchema.put(cls, schema);
}
}
return schema;
}
@Override
public <T> byte[] serialize(T obj) {
@SuppressWarnings("unchecked")
Class<T> cls = (Class<T>) obj.getClass();
LinkedBuffer buffer = LinkedBuffer.allocate(LinkedBuffer.DEFAULT_BUFFER_SIZE);
try {
Schema<T> schema = getSchema(cls);
return ProtostuffIOUtil.toByteArray(obj, schema, buffer);
} catch (Exception e) {
throw new IllegalStateException(e.getMessage(), e);
} finally {
buffer.clear();
}
}
@Override
public <T> Object deserialize(byte[] bytes, Class<T> clazz) {
try {
T message = (T) objenesis.newInstance(clazz);
Schema<T> schema = getSchema(clazz);
ProtostuffIOUtil.mergeFrom(bytes, message, schema);
return message;
} catch (Exception e) {
throw new IllegalStateException(e.getMessage(), e);
}
}
}
kryo实现
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import com.esotericsoftware.kryo.Kryo;
import com.esotericsoftware.kryo.io.Input;
import com.esotericsoftware.kryo.io.Output;
import com.esotericsoftware.kryo.pool.KryoFactory;
import com.esotericsoftware.kryo.pool.KryoPool;
/**
* @author 都市桃源
*
*/
public class KryoSerializer implements Serializer {
/**
* kryo 不是线程安全的,所以使用池控制
*/
private static final KryoPool kryoPool = new KryoPool.Builder(
new KryoFactory() {
public Kryo create() {
Kryo kryo = new Kryo();
return kryo;
}
}).build();
@Override
public <T> byte[] serialize(T obj) throws Exception {
try (
Output output = new Output(new ByteArrayOutputStream())) {
Kryo kryo = kryoPool.borrow();
kryo.writeObject(output, obj);
kryoPool.release(kryo);
output.flush();
return ((ByteArrayOutputStream) output.getOutputStream()).toByteArray();
}
}
@Override
public <T> Object deserialize(byte[] bytes, Class<T> clazz)
throws Exception {
try (Input input = new Input(new ByteArrayInputStream(bytes))) {
Kryo kryo = kryoPool.borrow();
T res = kryo.readObject(input, clazz);
kryoPool.release(kryo);
return res;
}
}
}
jdk实现
public class JdkSerializer implements Serializer {
@Override
public <T> byte[] serialize(T obj) {
try {
ByteArrayOutputStream byteArr = new ByteArrayOutputStream();
ObjectOutputStream out=new ObjectOutputStream(byteArr);
out.writeObject(obj);
out.flush();
return byteArr.toByteArray();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
@Override
public <T> Object deserialize(byte[] bytes, Class<T> clazz) {
try {
ObjectInputStream input=new ObjectInputStream(new ByteArrayInputStream(bytes));
return input.readObject();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
fst实现
import org.nustaq.serialization.FSTConfiguration;
public class FstSerializer implements Serializer {
private static final FSTConfiguration configuration = FSTConfiguration
.createStructConfiguration();
@Override
public <T> byte[] serialize(T obj) {
return configuration.asByteArray(obj);
}
@Override
public <T> Object deserialize(byte[] bytes, Class<T> clazz) {
return configuration.asObject(bytes);
}
}3,准备序列对象
序列化对象需要实现Serializable,有的需要有的不需要,hession需要,而且还需要有默认的无参构造方法jackson需要
public class User implements Serializable{
private String name;
private String address;
private Integer age;
public User() {
super();
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public User(String name, String address, Integer age) {
super();
this.name = name;
this.address = address;
this.age = age;
}
}
4.序列化速度比较
public class SerTest {
public static void main(String[] args) {
int len=10;
test(new HessianSerializer(), "hession",len);
test(new JacksonSerializer(), "jackson",len);
test(new ProtostuffSerializer(), "protostu",len);
test(new JdkSerializer(),"jdk",len);
test(new KryoSerializer(),"kryo",len);
test(new FstSerializer(),"fst",len);
test(new FastJsonSerializer(),"fastjson",len);
}
public static void test(Serializer s,String tag,int len){
long cap=0;
long sumTime=0;
for(int i=0;i<len;i++){
User u=new User("taoyuan"+i, i+"addr", i);
long start=System.currentTimeMillis();
byte[] serialize = s.serialize(u);
cap+=serialize.length;
s.deserialize(serialize, User.class);
long cal= System.currentTimeMillis()-start;
sumTime+=cal;
}
System.out.println(tag+"-->["+len+"]对象序列总体积大小:"+cap);
System.out.println(tag+"->["+len+"]对象总消耗时间为:"+sumTime);
}
}
结果:
hession–>[100]对象序列总体积大小:7780
hession->[100]对象总消耗时间为:197
jackson–>[100]对象序列总体积大小:4770
jackson->[100]对象总消耗时间为:122
protostu–>[100]对象序列总体积大小:2080
protostu->[100]对象总消耗时间为:102
jdk–>[100]对象序列总体积大小:21380
jdk->[100]对象总消耗时间为:122
kryo–>[100]对象序列总体积大小:2016
kryo->[100]对象总消耗时间为:47
fst–>[100]对象序列总体积大小:4880
fst->[100]对象总消耗时间为:35
fastjson–>[100]对象序列总体积大小:4770
fastjson->[100]对象总消耗时间为:206
5结论
从以上结果来看,序列化综合性能比较好的是protostuff和kryo
jdk的序列化速度比较快,就是序列体积较大.
所以当我们的需要开发一套rpc服务时,可以采用kryo来序列化对象,提高传输效率
rpc服务简单实现原理简介
个人理解
要想实现一套rpc服务,首先我们得将我们得从本质理解rpc
rpc简单来说就是序列化+传输协议+调用实现+服务管理
序列化是基础也决定了rpc是否支持跨语言
传输协议可以选择tcp,http,udp等协议
调用实现即rpc服务的业务实现
服务管理即是在以上基础之上的优化管理层次,负载均衡,调用追踪等
一旦我们从本质上理解了rpc之后,写一套简单的rpc服务也是很简单的事情,具体业务再去分析优化,每一层隔离开,优化时,改动也不会太大,,有机会,我们写一篇,手把手教你实现rpc的博文
边栏推荐
- R language uses GLM function to build Poisson logarithm linear regression model, processes three-dimensional contingency table data to build saturation model, uses step function to realize stepwise re
- i.mx6ull(单片机) c语言环境搭建
- 怎么找相同台词的影视片段?这8个电影搜索神器,一句台词找到对应片段
- [tcapulusdb knowledge base] Introduction to tcapulusdb tcapsvrmgr tool (II)
- 2022ciscn central China Web
- 微服务拆分
- [high frequency interview questions] difficulty 1.5/5, LCS template questions
- Time management understood after being urged to work at home
- 消息队列的使用
- 如何修改 node_modules 裏的文件
猜你喜欢

数学知识——博弈论(巴什博奕、尼姆博奕、威佐夫博奕)思路及例题

How to adjust an integer that is entered in Excel but always displays decimals?

Drive to APasS!使用明道云管理F1赛事

Safe landing practice of software supply chain under salesforce containerized ISV scenario

动态规划【四】(计数类dp)例题:整数划分

MySQL高阶语句(一)

Usage of rxjs mergemap

Nvme2.0 protocol - new features

如何修改 node_modules 裏的文件

干货!零售业智能化管理会遇到哪些问题?看懂这篇文章就够了
随机推荐
Topic38——56. 合并区间
How histrix works
Interview shock 60: what will cause MySQL index invalidation?
Getting started with go web programming: validators
优博讯出席OpenHarmony技术日,全新打造下一代安全支付终端
[tcapulusdb knowledge base] Introduction to tcapulusdb tcapsvrmgr tool (II)
Drive to APasS! Use Mingdao cloud to manage F1 events
一个有趣的网络掩码的实验
Youboxun attended the openharmony technology day to create a new generation of secure payment terminals
TiDB 6.0:让 TSO 更高效丨TiDB Book Rush
聊聊 Go 语言与云原生技术
MySQL high level statements (I)
【面试高频题】难度 1.5/5,LCS 模板题
C/s architecture
Secyun won the "2022 AI analysis · it operation and maintenance vendor panorama report" as the representative vendor of intelligent operation and maintenance aiops Market
How to participate in openharmony code contribution
R language uses the poisgof function of epidisplay package to test the goodness of fit of Poisson regression and whether there is overdispersion
What is the TCP 3-time handshake process?
如何修改 node_modules 里的文件
Jwas: a Bayesian based GWAS and GS software developed by Julia