序列化协议Protobuf

1.序列化和反序列化

    序列化: 将对象序列化为二进制数据(字节数组),一般也将序列化称为编码(Enccode),主要用于网络传输,数据持久化。

   反序列化:  将从网络上,磁盘等读取的字节数组还原成原始对象,一般也将反序列化称为解码(Decode),主要用于网络传输对象的解码,以便完成远程调用。

2.选择序列化协议时,需要考虑什么?

  • 序列化之后的码流大小(占用网络带宽)
  • 序列化和反序列化的性能(cpu资源占用)
  • 是否支持跨语言

3.测试Java自带的序列化类

   objectoutputstream /objectInputstream是Java自带的序列化类,测试它序列化的效率。

   Teacher类是待序列化的类,它的定义如下:

import java.io.Serializable;
public class Teacher implements Serializable{
    private static final long serialVersionnUID = 8619259453444471644L;
    private Long id;
    private int age;
    private String name;

    public Teacher(Long id,int age,String name ){
        this.id = id;
        this.age = age;
        this.name = name;
    }
}

    序列化和反序列化的定义如下:

import java.io.ByteArrayOutputStream;
import java.io.ByteArrayInputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.Arrays;
import java.io.Serializable;
public class TestJavaSerializer
{
    //序列化
    private static byte[] serialize(Teacher t) throws Exception{
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(out);
        oos.writeObject(t);
        byte[] array = out.toByteArray();
        return array;
    }
   //反序列化
    private static Teacher deserialize(byte[] byteArray) throws Exception{
        ByteArrayInputStream ins = new ByteArrayInputStream(byteArray);
        ObjectInputStream ois = new  ObjectInputStream(ins);
        Teacher t = (Teacher)ois.readObject();
        return t;
    }

    public static void main(String []args) throws Exception{  
        Teacher t = new Teacher(1L, 22, "April");
        byte[] byteArray = serialize(t);
        System.out.println(Arrays.toString(byteArray));  
        System.out.println("Length = " + byteArray.length); 
        Teacher t1 = deserialize(byteArray);
    }
}

 输出结果如下:

[-84, -19, 0, 5, 115, 114, 0, 7, 84, 101, 97, 99, 104, 101, 114, -19, 83, 98, -77, 62, -23, 40, 8, 2, 0, 3, 73, 0, 3, 97, 103, 101, 76, 0, 2, 105, 100, 116, 0, 16, 76, 106, 97, 118, 97, 47, 108, 97, 110, 103, 47, 76, 111, 110, 103, 59, 76, 0, 4, 110, 97, 109, 101, 116, 0, 18, 76, 106, 97, 118, 97, 47, 108, 97, 110, 103, 47, 83, 116, 114, 105, 110, 103, 59, 120, 112, 0, 0, 0, 22, 115, 114, 0, 14, 106, 97, 118, 97, 46, 108, 97, 110, 103, 46, 76, 111, 110, 103, 59, -117, -28, -112, -52, -113, 35, -33, 2, 0, 1, 74, 0, 5, 118, 97, 108, 117, 101, 120, 114, 0, 16, 106, 97, 118, 97, 46, 108, 97, 110, 103, 46, 78, 117, 109, 98, 101, 114, -122, -84, -107, 29, 11, -108, -32, -117, 2, 0, 0, 120, 112, 0, 0, 0, 0, 0, 0, 0, 1, 116, 0, 5, 65, 112, 114, 105, 108]
Length = 176

    使用Java自带的序列化类objectoutputstream /objectInputstream对Teacher对象序列化后的长度为176。

4.Protobuf序列化

    用proto文件定义Teacher类,文件名为Teacher.proto,使用命令生成TeacherSerializer.java文件。

syntax = "proto2";
option java_package = "com.netty.protobuf";
option java_outer_classname = "TeacherSerializer";


message Teacher{
    required int64 id = 1;
    required int32 age =2;
    required string name = 3;
}

      序列化和反序列化的定义如下:

package com.netty.protobuf;

import java.util.Arrays;
import com.netty.protobuf.TeacherSerializer.Teacher;
import com.netty.protobuf.TeacherSerializer.Teacher.Builder;

public class TestProtobuf {
	//序列化
	private static byte[] serialize()
	{
		Builder builder = TeacherSerializer.Teacher.newBuilder();
		builder.setId(1L).setAge(22).setName("April");
		Teacher t = builder.build();
		return t.toByteArray();
	}
	//反序列化
	private static Teacher deserialize(byte[] data) throws Exception
	{
		Teacher t = TeacherSerializer.Teacher.parseFrom(data);
		return t;
	}
	
	public static void main(String[] args) throws Exception {
		byte[] data = serialize();
		System.out.println(Arrays.toString(data));
		System.out.println("Length = " + data.length);
		Teacher t = deserialize(data);
	}
}

输出结果如下:

[8, 1, 16, 22, 26, 5, 65, 112, 114, 105, 108]
Length = 11

    使用Protobuf对Teacher对象序列化后的长度为11。序列化后的数据长度比java自带的序列化类短了很多。

5.结论

    使用Java自带的序列化类objectoutputstream /objectInputstream对Teacher对象序列化后的长度为176。而使用Protobuf序列化后的长度仅为11。占用带宽和消耗CPU都会比较小,所以使用Protobuf效率更高

猜你喜欢

转载自blog.csdn.net/liyazhen2011/article/details/86698822