序列化之protobuf与avro对比(Java)

 

  最近在做socket通信中用到了关于序列化工具选型的问题,在调研过程中开始趋向于用protobuf,可以省去了编解码的过程。能够实现快速开发,且只需要维护一份协议文件即可。

  但是调研过程中发现了protobuf的一些弊端,比如需要生成相应的文件类,和业务绑定太紧密,所以在看了AVRO之后发现它完美解决了这个问题。

  下面记录下对这两种序列化工具的入门与测评。

一、protobuf基本操作

protobuf简介:

Protocol Buffers (a.k.a., protobuf) are Google's language-neutral, platform-neutral, extensible mechanism for serializing structured data. 

protobuf是google提供的一种跨语言、跨平台、可扩展的序列化工具。

1.1定义协议文件(部分字段)(TCPLog.proto):

复制代码

syntax = "proto2";
message TCPLog{
         optional int32   total_byteps = 1;
         optional int64 flow_start_time =2;
         optional int64 date =3;
}

复制代码

1.2生成对应的Java类:

生成过程可以使用ecplise 的插件 或者 直接在控制台中使用命令生成。

命令行中生成规则如下:

1

protoc.exe -I=proto的输入目录 --java_out=java类输出目录 proto的输入目录包括包括proto文件

  生成java类如下:

View Code

之后便可以使用该类进行序列化和反序列化。

具体示例代码如下》:

复制代码

import java.io.File;
import java.io.FileOutputStream;


public class ProtoTest3 {
 /**
 * @param args
 * @throws Exception
 * @author qiang(upupgo)
 */
public static void main(String[] args) throws Exception {
        //模拟将对象转成byte[],方便传输
     TCPLogOuterClass.TCPLog.Builder builder = TCPLogOuterClass.TCPLog.newBuilder();
    builder.setTotalByteps(1024);
    builder.setFlowStartTime(1502415717l);
    builder.setDate(1502415717l);
   //序列化到文件
     TCPLogOuterClass.TCPLog tcpLog= builder.build();
     FileOutputStream out = new FileOutputStream(new File("D:/pb"));
     out.write(tcpLog.toByteArray());
     out.close();
     //反序列化
    TCPLogOuterClass.TCPLog tcp = TCPLogOuterClass.TCPLog.parseFrom(tcpLog.toByteArray());
    System.out.println(tcp);
}
}

复制代码

二、AVRO序列化基本操作:

AVRO简介:

复制代码

Apache Avro™ is a data serialization system.
Avro provides:
Rich data structures.
A compact, fast, binary data format.
A container file, to store persistent data.
Remote procedure call (RPC).
Simple integration with dynamic languages. Code generation is not required to read or write data files nor to use or implement RPC protocols. Code generation as an optional optimization, only worth implementing for statically typed languages.

复制代码

  Avro是一个序列化系统。丰富的数据结构、快速压缩的二进制数据格式、数据持久化存储、RPC及动态语言集成。

2.1定义协议文件(TCPLog.avro)

复制代码

{"namespace": "example.avro",
 "type": "record",
 "name": "TCPLog",
 "fields": [
     {"name": "total_byteps", "type": "int"},
     {"name": "flow_start_time",  "type": "long"},
     {"name": "date", "type": "long"}
     
 ]
}
              

复制代码

avro和protobuf一样可以生成相应语言的类文件,或直接支持动态扩张。下面以Java语言不生成类说明:

具体序列化与反序列化操作代码如下:、

复制代码

package avro;

import java.io.File;

import org.apache.avro.Schema;
import org.apache.avro.file.DataFileReader;
import org.apache.avro.file.DataFileWriter;
import org.apache.avro.generic.GenericData;
import org.apache.avro.generic.GenericDatumReader;
import org.apache.avro.generic.GenericDatumWriter;
import org.apache.avro.generic.GenericRecord;
import org.apache.avro.io.DatumReader;
import org.apache.avro.io.DatumWriter;
/**
 * @date 2017年8月13日22:15:32
 * @author qiang(upupgo)
 *
 */
public class AvroTest2 {
public static void main(String[] args) throws Exception {
    String filePath = "D:/TCPLog.avsc";
    Schema schema = new Schema.Parser().parse(new File(filePath));
    
    GenericRecord tcpLog = new GenericData.Record(schema);
    tcpLog.put("total_byteps", 1024);
    tcpLog.put("flow_start_time", 1502415717L);
    tcpLog.put("date", 1502415717L);
   
    System.out.println(tcpLog);
    
    
    // Serialize user1 and tcpLog to disk
    File file = new File("D:/avro");
    DatumWriter<GenericRecord> datumWriter = new GenericDatumWriter<GenericRecord>(schema);
    DataFileWriter<GenericRecord> dataFileWriter = new DataFileWriter<GenericRecord>(datumWriter);
    dataFileWriter.create(schema, file);
    long timestart = System.currentTimeMillis();
    dataFileWriter.append(tcpLog);
    dataFileWriter.close();
    long timeend = System.currentTimeMillis();
    System.out.println(timeend-timestart);
    
    // Deserialize users from disk
    DatumReader<GenericRecord> datumReader = new GenericDatumReader<GenericRecord>(schema);
    DataFileReader<GenericRecord> dataFileReader = new DataFileReader<>(new File("d:/avro"), datumReader);
    GenericRecord tcpLogs = null;
    long timestart1 = System.currentTimeMillis();
    while (dataFileReader.hasNext()) {
    // Reuse user object by passing it to next(). This saves us from
    // allocating and garbage collecting many objects for files with
    // many items.
        tcpLogs = dataFileReader.next();
//    System.out.println("xx"+tcpLogs);
  }
    long timeend1 = System.currentTimeMillis();
    System.out.println("Deserialize"+(timeend1-timestart1));
 }
}

复制代码

以下是通过对100W tcpLog序列化操作对比结论:

通过对比测试发现 avro的性能要不pb稍微好一些,且支持动态性。故技术选型上可以优先考虑。

以上是通过测试对比了pb与avro的一些性能差异,但是具体测试和机器和样本都有关系,可以参考。

以下是对比protobuf、avro、thrift的一些优缺点:

参考:https://www.douban.com/note/523340109/

复制代码

Google protobuf:
优点

    二进制消息,性能好/效率高(空间和时间效率都很不错)
    proto文件生成目标代码,简单易用
    序列化反序列化直接对应程序中的数据类,不需要解析后在进行映射(XML,JSON都是这种方式)
    支持向前兼容(新加字段采用默认值)和向后兼容(忽略新加字段),简化升级
    支持多种语言(可以把proto文件看做IDL文件)
    Netty等一些框架集成

缺点

    官方只支持C++,JAVA和Python语言绑定
    二进制可读性差(貌似提供了Text_Fromat功能)
    二进制不具有自描述特性
    默认不具备动态特性(可以通过动态定义生成消息类型或者动态编译支持)
    只涉及序列化和反序列化技术,不涉及RPC功能(类似XML或者JSON的解析器)

Apache Thrift:
应用

    Facebook的开源的日志收集系统(scribe: https://github.com/facebook/scribe)
    淘宝的实时数据传输平台(TimeTunnel http://code.taobao.org/p/TimeTunnel/wiki/index)
    Evernote开放接口(https://github.com/evernote/evernote-thrift)
    Quora(http://www.quora.com/Apache-Thrift)
    HBase( http://abloz.com/hbase/book.html#thrift )
    …

优点

    支持非常多的语言绑定
    thrift文件生成目标代码,简单易用
    消息定义文件支持注释
    数据结构与传输表现的分离,支持多种消息格式
    包含完整的客户端/服务端堆栈,可快速实现RPC
    支持同步和异步通信

缺点

    和protobuf一样不支持动态特性

Apache Avro:
应用

    Hadoop RPC (http://hadoop.apache.org/#What+Is+Apache+Hadoop%3F)

优点

    二进制消息,性能好/效率高
    使用JSON描述模式
    模式和数据统一存储,消息自描述,不需要生成stub代码(支持生成IDL)
    RPC调用在握手阶段交换模式定义
    包含完整的客户端/服务端堆栈,可快速实现RPC
    支持同步和异步通信
    支持动态消息
    模式定义允许定义数据的排序(序列化时会遵循这个顺序)
    提供了基于Jetty内核的服务基于Netty的服务

缺点

    只支持Avro自己的序列化格式
    语言绑定不如Thrift丰富
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值