Netty编解码框架

时间:2022-07-24
本文章向大家介绍Netty编解码框架,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

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更快、更小的整数会被编码成一个字节,短的字符串仅仅只需要比它的长度多一字节的大小。

特点:编解码高效,性能高

    序列化之后的码流好

      支持跨语言

上述就是编解码技术的介绍,之后会聊一下框架的使用