网络通讯高效序列化类protobuf

2017/05/10 Java 共 3488 字,约 10 分钟

简介

在http网络通讯时,一般使用Json或高效序列化类的方式对数据进行传输,高效序列化类比较流行的是谷歌的protocol buffer与spark的kryo。下面介绍一下protocol buffer,当对数据的描述由使用JSON改为Protobuf,这样就可通过IDL实现强制约束,包括数据类型、字段命名等,相比json格式protocol字段格式相对固定。

优点

protobuf 不管是处理时间上,还是空间占用上都优于现有的其他序列化方式。内存暂用是java 序列化的1/9,时间也是差了一个数量级,一次操作在1us左右。

缺点

缺点:就是对象结构体有限制,只适合于内部系统使用。

Mac安装Protobuf编译Java

  1. 安装Homebrew(如果已有编译环境这步可忽略)

    Homebrew是一个类yum的软件包管理器,需要使用homebrew安装protobuf所需的编译器gcc等软件。

    Homebrew安装方法:https://jingyan.baidu.com/article/fec7a1e5ec30341190b4e7e5.html 安装Homebrew

    ruby -e "$(curl --insecure -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
    

    注意:安装HomeBrew时会报...could not lock config file .git/config: Permission denied ,所以先修改文件权限

    sudo chgrp -R admin /usr/local
    sudo chmod -R g+w /usr/local
       
    

    安装编译环境

    brew install gcc
    
  2. 在Mac上安装protobuf

    protobuf下载地址 https://github.com/google/protobuf/tags?after=v3.0.0-alpha-1

    解压压缩包

    tar zxvf protobuf-2.5.0.tar.gz
    

    cd到protobuf-2.5.0 目录

    cd protobuf-2.5.0
    

    指定安装目录(/Users/gongenbo/Tools/protobuf安装目录)

    ./configure --prefix=/Users/gongenbo/Tools/protobuf
       
    

    安装

    make
    make install
    

    设置环境变量

     sudo vi /etc/profile
    
     export PROTOBUF=/opt/tools/protobuf-2.5.0
     export PATH=$JAVA_HOME/bin:$PROTOBUF/bin:$PATH
    

    刷新环境变量

     source /etc/profile
    

    测试protobuf

     protoc --version
    
  3. 编写.proto文件,可以自己写,也可以复制example中的文件过来

    protobuf.proto

     option java_package = "com.example.demo";  
      
     option java_outer_classname = "PersonPb";  
    	  
     message Person {  
         required string name = 1;  
         required int32 id = 2;  
         optional string email = 3;  
    	  
         enum PhoneType {  
             MOBILE = 0;  
             HOME = 1;  
             WORKE = 2;  
         }  
    	  
         message PhoneNumber {  
             required string number = 1;  
             optional PhoneType type = 2 [default = HOME];  
         }  
    	  
         repeated PhoneNumber phone = 4;  
    	  
         message CountryInfo {  
             required string name = 1;  
             required string code = 2;  
             optional int32 number = 3;  
         }  
    	  
     }  
    	  
     message AddressBook {  
         repeated Person person = 1;  
     }  
    
  4. 编译生成Java

     protoc -I=src/main/resource/proto --java_out=src/main/java src/main/resource/proto/protobuf.proto
    

    PersonPb.java

     private PersonPb() {}  
       public static void registerAllExtensions(  
           com.google.protobuf.ExtensionRegistry registry) {  
       }  
       public interface PersonOrBuilder  
           extends com.google.protobuf.MessageOrBuilder {  
    	  
         // required string name = 1;  
         /** 
          * <code>required string name = 1;</code> 
          */  
         boolean hasName();  
         ...  
         ...内容很多,(稍后附件中有)  
         ...  
         com.google.protobuf.Descriptors.FileDescriptor  
           .internalBuildGeneratedFileFrom(descriptorData,  
             new com.google.protobuf.Descriptors.FileDescriptor[] {  
             }, assigner);  
       }  
    	  
       // @@protoc_insertion_point(outer_class_scope)  
     }  
    
  5. 使用:

     public class MainTest {  
         public static void main(String[] args) {  
             System.out.println("Test_Systemout");  
    	  
             PersonPb.AddressBook.Builder build = PersonPb.AddressBook.newBuilder();  
    	  
             PersonPb.Person person1 = PersonPb.Person.newBuilder().setId(1).setName("xxxxxxi").setEmail("123@qq.com").  
                     addPhone(PersonPb.Person.PhoneNumber.newBuilder().setNumber("15211112222").setType(PersonPb.Person.  
                             PhoneType.HOME).build()).build();  
    	  
             build.addPerson(person1);  
             PersonPb.Person person2 = PersonPb.Person.newBuilder().setId(2).setName("sasasasas").setEmail("qqqqq@qq.com").  
                     addPhone(PersonPb.Person.PhoneNumber.newBuilder().setNumber("15211112222").setType(PersonPb.Person.  
                             PhoneType.HOME).build()).build();  
    	  
             build.addPerson(person2);  
    	  
             for (int i = 0; i < build.getPersonList().size(); i++) {  
                 System.out.println("name=" + build.getPersonList().get(i).getName());  
             }  
         }  
     }  
    

核心概念

1,.proto文件5/10/2017 10:44:16 PM 相当于确定数据协议,数据结构中存在哪些数据,数据类型是怎么样

2,modifiers

  • 2.1. required 不可以增加或删除的字段,必须初始化
  • 2.2 optional 可选字段,可删除,可以不初始化
  • 2.3 repeated 可重复字段, 对应到java文件里,生成的是List

3,Message 在proto文件里,数据的协议时以Message的形式表现的。

4, Build 生成具体的java类时,例如Person.java,同时会存在build方法。文档的意思是对于转化后的数据,具有唯一性,build提供了便利的方法来初始化这些数据。

参考

win7如何安装maven、安装protoc: http://www.aboutyun.com/thread-8212-1-1.html

Mac安装Protobuf编译Java: http://blog.csdn.net/u013045971/article/details/50592998

支付宝打赏 微信打赏

您的打赏是对我最大的鼓励!

Search

    Post Directory