【微服务】序列化协议 In Action

孤街浪徒 提交于 2020-03-25 11:42:02

3 月,跳不动了?>>>

本文就常见的几种序列化协议介绍下简单的实践

ProtoBuf

ProtoBuf 是有谷歌开源,可以跨语言,可编译成各种语言。可称之为一个IDL, Interface description language.

  1. 下载编译器,protoc protoc-3.11.4-osx-x86_64.zip;可下载不同操作系统的版本, https://github.com/google/protobuf/releases
  2. 设置环境变量
 vi ~/.bash_profile
 export PATH=$PATH:/path/to/protoc-3.4.0/bin
  1. 在maven项目中引入相关依赖
<!-- https://mvnrepository.com/artifact/com.google.protobuf/protobuf-java -->
    <dependency>
      <groupId>com.google.protobuf</groupId>
      <artifactId>protobuf-java</artifactId>
      <version>3.11.4</version>
    </dependency>

    <!-- https://mvnrepository.com/artifact/com.googlecode.protobuf-java-format/protobuf-java-format -->
    <dependency>
      <groupId>com.googlecode.protobuf-java-format</groupId>
      <artifactId>protobuf-java-format</artifactId>
      <version>1.4</version>
    </dependency>
  1. 编写协议文件,扩展名为proto
syntax = "proto2";

package com.seandde.test;

option optimize_for = SPEED;
option java_package = "com.seandde.test.protobuf";
option java_outer_classname = "DataInfo";


message Student {
    required string name =1;
    required int32 age = 2;
    optional string address = 3;

}
  1. 使用protoc生成对应的java类
protoc --java_out=src/main/java src/protobuf/Student.proto
  1. 简单测试下
public class ProtoBufTest {
    public static void main(String ...arg) throws Exception {

        DataInfo.Student student = DataInfo.Student.newBuilder().setName("张三").setAge(28).setAddress("北京").build();

        System.out.println(student);

        //转换成字节可以在网络上传输
        byte[] stdent2ByteArray = student.toByteArray();

        //转换成java对象
        DataInfo.Student student2 = DataInfo.Student.parseFrom(stdent2ByteArray);

        System.out.println(student2);

    }

}

相关链接: https://developers.google.com/protocol-buffers/docs/overview https://developers.google.com/protocol-buffers/docs/javatutorial

JSON , 此处使用alibaba的fastJson

  1. 引入相关依赖
<!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
    <dependency>
      <groupId>com.alibaba</groupId>
      <artifactId>fastjson</artifactId>
      <version>1.2.62</version>
    </dependency>
  1. 编写测试类
public class Student {

    private String name;

    private int age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
public class FastJsonTest {
    public static void main(String[] args) {
        Student student = new Student();
        student.setAge(11);
        student.setName("张数");

        String result = JSON.toJSONString(student);

        System.out.println(result);

        Student student1 = JSON.parseObject(result, Student.class);

        System.out.println(student1);
    }
}

相关链接: https://github.com/alibaba/fastjson

MsgPack

注意: msgpack序列化时未记录字段名称,而是使用的数组,按字段顺序记录,因此,在bean中增加字段时需要加载bean的最后面. 使用时,可提前编译好各种msgpack模板,提升序列化、反序列化性能

  1. 引入相关依赖
 <!-- https://mvnrepository.com/artifact/org.msgpack/msgpack -->
    <dependency>
      <groupId>org.msgpack</groupId>
      <artifactId>msgpack</artifactId>
      <version>0.6.12</version>
    </dependency>
  1. 编写相关测试
public class MsgPackTest {

    public static void main(String[] args) throws IOException {
        MessagePack messagePack = new MessagePack();
        Student student = new Student();
        student.setName("zhangsan");
        student.setAge(11);
        
        byte[] result = messagePack.write(student);

        System.out.println(result);
        
        Student student1 = messagePack.read(result, Student.class);

        System.out.println(student1);
		
		// Create serialize objects.
List<String> src = new ArrayList<String>();
src.add("msgpack");
src.add("kumofs");
src.add("viver");
		
		
		// Serialize
byte[] raw = msgpack.write(src);

// Deserialize directly using a template
List<String> dst1 = msgpack.read(raw, Templates.tList(Templates.TString));
System.out.println(dst1.get(0));
System.out.println(dst1.get(1));
System.out.println(dst1.get(2));

// Or, Deserialze to Value then convert type.
Value dynamic = msgpack.read(raw);
List<String> dst2 = new Converter(dynamic)
    .read(Templates.tList(Templates.TString));
System.out.println(dst2.get(0));
System.out.println(dst2.get(1));
System.out.println(dst2.get(2));
    }
}

相关链接: https://msgpack.org/

hessian

hessian不同于msgpack,其记录了字段名称,因此性能可能会稍微差一些

  1. 引入相关依赖
  <!-- https://mvnrepository.com/artifact/com.caucho/hessian -->
    <dependency>
      <groupId>com.caucho</groupId>
      <artifactId>hessian</artifactId>
      <version>4.0.63</version>
    </dependency>
  1. 编写测试类
public class HessianTest {

    public static void main(String[] args) throws IOException {

        ByteArrayOutputStream os = new ByteArrayOutputStream();
        Hessian2Output output = new Hessian2Output(os);
        output.writeObject("23456789");
        output.close();

        ByteArrayInputStream in = new ByteArrayInputStream(os.toByteArray());
        Hessian2Input input = new Hessian2Input(in);
        System.out.println(input.readObject());
    }
}

相关链接: http://hessian.caucho.com/doc/hessian-serialization.html

总结

在选择序列化框架时,需考虑性能、支持的范围(如泛华、父子类)、集合类型是否会丢失等等。

欢迎关注我的公众号: 张恒强的学习笔记

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!