1、何为编解码
对于java来说就是序列化与反序列化机制,java序列化主要有两种用途,就是网络传输和对象持久化,所以Java提供了ObjectOutPutStream和ObjectInputStream。 既然Java已经提供了编解码机制,为何Netty还要提供另外的编解码框架呢?
2、Java序列化的缺点
(1)无法跨语言:Java序列化技术只是java语言内部的私有协议,其它语言并不支持。
(2)序列化之后码流太大:看个例子
//定义一个对象实现Serializable接口
public class JavaSerial implements Serializable {
private int id;
private String name;
//省略get/set方法
@Override
public String toString() {
return "JavaSerial{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
}
//测试代码
public class Test {
public static void main(String[] args) throws IOException, ClassNotFoundException {
//实例化对象
JavaSerial javaSerial = new JavaSerial();
javaSerial.setId(1);
javaSerial.setName("Tom");
//使用Java序列化机制
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(javaSerial);
oos.flush();
oos.close();
System.out.println("Java序列化之后对象大小:"+bos.toByteArray().length);
//使用ByteBuf存储数据
ByteBuf byteBuf = Unpooled.buffer(1024);
byte[] nameBytes = javaSerial.getName().getBytes();
byteBuf.writeInt(nameBytes.length);
byteBuf.writeBytes(nameBytes);
System.out.println("将对象写入ByteBuf后对象大小:"+byteBuf.readableBytes());
}
}
上述代码运行结果如下:可得知两种结果相差悬殊。
(3)序列化性能低
将上述测试代码进行更改,把两种序列化执行1000000次,看耗时
public static void main(String[] args) throws IOException, ClassNotFoundException {
JavaSerial javaSerial = new JavaSerial();
javaSerial.setId(1);
javaSerial.setName("Tom");
ByteArrayOutputStream bos = null;
ObjectOutputStream oos = null;
long startTime = System.currentTimeMillis();
for (int i = 0; i < 1000000; i++) {
bos = new ByteArrayOutputStream();
oos = new ObjectOutputStream(bos);
oos.writeObject(javaSerial);
oos.flush();
oos.close();
}
System.out.println("java将对象序列化1000000次耗时:"+(System.currentTimeMillis() - startTime) + "ms");
ByteBuf byteBuf = Unpooled.buffer(1024);
startTime = System.currentTimeMillis();
for (int i = 0; i < 1000000; i++) {
byte[] nameBytes = javaSerial.getName().getBytes();
byteBuf.writeInt(nameBytes.length);
byteBuf.writeBytes(nameBytes);
}
System.out.println("将对象写入ByteBuf1000000次耗时:"+(System.currentTimeMillis() - startTime) + "ms");
}
运行结果如下:可知,java序列化性能对比ByteBuf写入是多么的悬殊。
3、业界主流编解码框架
(1)Google的Protobuf
将数据结构以.proto文件进行描述,通过代码生成工具可以生成对应数据结构的POJO对象和Protobuf相关的方法和属性。
特点:结构化数据存储格式(XML,JSON等)
高效的编解码性能
无关语言、平台,扩展性好
官方支持java、c++、python
(2)Facebook的Thrift
在多种不同语言之间通信,Thrift可作为高性能的通信中间件使用,支持数据对象序列化以及多种类型的RPC服务。适用于静态的数据交换,当数据结构发生变化时,必须重新编辑IDL文件,重新生成代码和编译。适用于搭建大型数据交换及存储的通用工具,对于大型系统中的内部数据传输,相比于json和xml,在性能和传输大小上更具有优势。
thrift主要由5个部分组成
1、语言系统以及IDL编译器:负责由用户给定的IDL文件生成相应语言的接口代码;
2、TProtocol:RPC的协议层,可以选择多种不同的对象序列化方向,如json和Binary
3、TTransport:RPC的传输层,同样可以选择不同的传输层实现,如socket、NIO、MemoryBUffer等
4、TProcessor:作为协议层和用户提供的服务实现之间的纽带,负责调用服务实现的接口
5、TServer:聚合TProtocol、TTransport和TProcessor等对象
其编解码框架就是TProtocol
(3)MessagePack
一个高效的二进制序列化格式。它让你像JSON一样可以在各种语言之间交换数据。但是它比JSON更快、更小的整数会被编码成一个字节,短的字符串仅仅只需要比它的长度多一字节的大小。
特点:编解码高效,性能高
序列化之后的码流好
支持跨语言
上述就是编解码技术的介绍,之后会聊一下框架的使用