zoukankan      html  css  js  c++  java
  • protobuf和protostuff的区别

    在我们的开发过程中,序列化是经常需要处理的问题,比如在做分布式访问数据时,或者是在做redis缓存存储数据时,如果我们涉及的知识面不够广的话,可能会简单的使用JDK的序列化,也即在需要序列化的类上implements Serializable接口去实现序列化,我想说的是这种方式在小系统中尚且可以用一用,如果是并发很大的系统会受到严重影响,这是由于JDK自带的序列化效率很低,不论是时间上还是空间上。我们经常使用的序列化方式还有XML和Json,说实在的我更多的是使用Json,我觉得它很方便很友好,但这些都不够好,我今天要将的是google开发的开源的序列化方案protocol buffer(简称protobuf),它的好处很多,独立于语言,独立于平台,最最重要的是它的效率相当高,用protobuf序列化后的大小是json的10分之一,xml格式的20分之一,是二进制序列化的10分之一,是不是很心动。其实我也刚接触这个好东西,写下此篇博客就当一个学习笔记吧。

    protobuf使用起来非常简单,它的主要流程是:我们需要自己写一个.proto文件用来描述序列化的格式,然后用protobuf提供的protoc工具将.proto文件编译成一个Java文件(protobuf官方支持很多语言:Java、C++、C#、Go、Python ,protobuf是一个开源项目,因此有很多大牛也实现了其他语言,但它们的可靠性还有待验证),最后将该Java文件引入到我们的项目中就可以使用了,当然还得引入protobuf的依赖包。

     

    1、我们需要到官网下载protobuf的相应版本,我这里下载的是windows下的3.1.0版protoc-3.1.0-win32.zip

    2、将下载好的zip解压,能看到bin目录下有一个protoc.exe的文件,等下需要用它来编译文件,我们直接在bin目录下      创建一个简单的person.proto的描述文件,内容如下:

     

    1. syntax = "proto3";  
    2.   
    3. option java_package = "gudao.red.protobuf";  
    4. option java_outer_classname = "PersonFactory";  
    5.   
    6. message Person{  
    7.   
    8.      int32 id = 1;  
    9.      string name = 2;  
    10.      int32 age = 3;  
    11.      Addr addr = 4;  
    12.      
    13. }  
    14.   
    15. message Addr{  
    16.        
    17.      string contry = 1;  
    18.      string city = 2;  
    19.   
    20. }  

    内容非常简单,大概介绍一下:

    syntax = "proto3";   我们使用proto3版协议

    option java_package = "gudao.red.protobuf"; 编译之后生成的Java文件的包名

    option java_outer_classname = "PersonFactory"; 编译之后生成的Java类的类名

    message 相当于Java中的class

    详细的介绍,还请自行去官网查看

     

    3、使用protoc编译上述.proto文件,生成Java类,使用如下命令完成该操作

    1. protoc --java_out=./src ./person.proto  

     --java_out:生成的Java文件输出的位置,其他语言有相应的选项

    这样就会在src目录下生成一个 名为PersonFactory的Java文件

     

    4、将PersonFactory.java文件引入到我们的项目中,并引入对应版本的protobuf的依赖包

     

    5、写测试代码

    1. package gudao.red.protobuf_test;  
    2.   
    3. import java.net.Socket;  
    4.   
    5. import gudao.red.protobuf.PersonFactory.Addr;  
    6. import gudao.red.protobuf.PersonFactory.Person;  
    7.   
    8. public class Client {  
    9.       
    10.     public static void main(String[] args) throws Exception {  
    11.         Socket socket = new Socket("127.0.0.1",3030);  
    12.           
    13.         Person.Builder person = Person.newBuilder();  
    14.           
    15.         Addr.Builder addr = Addr.newBuilder();  
    16.         addr.setContry("china").setCity("shenzhen");  
    17.           
    18.         person.setId(1).setAge(12).setName("ccf");  
    19.         person.setAddr(addr);  
    20.           
    21.         byte[] messageBody = person.build().toByteArray();  
    22.       
    23.         int headerLen = 1;  
    24.         byte[] message = new byte[headerLen+messageBody.length];  
    25.         message[0] = (byte)messageBody.length;  
    26.         System.arraycopy(messageBody, 0,  message, 1, messageBody.length);  
    27.         System.out.println("msg len:"+message.length);  
    28.         socket.getOutputStream().write(message);  
    29.     }  
    30.   
    31. }  

     

    1. package gudao.red.protobuf_test;  
    2.   
    3. import java.net.ServerSocket;  
    4. import java.net.Socket;  
    5.   
    6. import gudao.red.protobuf.PersonFactory.Person;  
    7.   
    8. public class Server {  
    9.       
    10.     /** 
    11.      * @param args 
    12.      */  
    13.     public static void main(String[] args) throws Exception {  
    14.         // TODO Auto-generated method stub  
    15.         ServerSocket serverSock = new ServerSocket(3030);  
    16.         while(true){  
    17.             Socket sock = serverSock.accept();  
    18.             byte[] msg = new byte[256];  
    19.             sock.getInputStream().read(msg);  
    20.             int msgBodyLen = msg[0];  
    21.             System.out.println("msg body len:"+msgBodyLen);  
    22.             byte[] msgbody = new byte[msgBodyLen];  
    23.             System.arraycopy(msg, 1, msgbody, 0, msgBodyLen);  
    24.               
    25.             Person person = Person.parseFrom(msgbody);  
    26.               
    27.             System.out.println("Receive:");  
    28.             System.out.println(person);  
    29.         }  
    30.   
    31.     }  
    32.   
    33. }  

    先后启动Server和Client,就可以看到控制台的输出如下:

    至此,我们的简单使用过程就完成了,是不是很简单。是,这个例子看上去是挺简单的,但如果我们需要序列化的类非常多,那么我们是不是得写非常多的.proto文件,并且还需要更新它们,这个代价可以想象一下也是非常大的。那么,接下来我们就来讲一讲protostuff,看这名字是不是跟protobuf很像,嗯,它们是有关系,前者就是基于后者实现的。

     

    6、protostuff是一个基于protobuf实现的序列化方法,它较于protobuf最明显的好处是,在几乎不损耗性能的情况下做到了不用我们写.proto文件来实现序列化。使用它也非常简单,所以直接上代码。

    1. package gudao.red.protostuff;  
    2.   
    3. import java.util.Arrays;  
    4. import java.util.List;  
    5.   
    6. public class Po {  
    7.       
    8.     private Integer id;  
    9.     private String name;  
    10.     private String remark;  
    11.     private Integer age;  
    12.     private int[] array;  
    13.     private InnerPo innerPo;  
    14.     private List<String> more;  
    15.       
    16.     public Po(){}  
    17.       
    18.     public Po(Integer id,String name,String remark,Integer age,  
    19.             int[] array,InnerPo innerPo,List<String> more){  
    20.         this.id = id;  
    21.         this.name = name;  
    22.         this.remark = remark;  
    23.         this.age = age;  
    24.         this.array = array;  
    25.         this.innerPo = innerPo;  
    26.         this.more = more;  
    27.     }  
    28.       
    29.     public Integer getId() {  
    30.         return id;  
    31.     }  
    32.     public void setId(Integer id) {  
    33.         this.id = id;  
    34.     }  
    35.     public String getName() {  
    36.         return name;  
    37.     }  
    38.     public void setName(String name) {  
    39.         this.name = name;  
    40.     }  
    41.     public String getRemark() {  
    42.         return remark;  
    43.     }  
    44.     public void setRemark(String remark) {  
    45.         this.remark = remark;  
    46.     }  
    47.     public Integer getAge() {  
    48.         return age;  
    49.     }  
    50.     public void setAge(Integer age) {  
    51.         this.age = age;  
    52.     }  
    53.     public int[] getArray() {  
    54.         return array;  
    55.     }  
    56.     public void setArray(int[] array) {  
    57.         this.array = array;  
    58.     }  
    59.     public InnerPo getInnerPo() {  
    60.         return innerPo;  
    61.     }  
    62.     public void setInnerPo(InnerPo innerPo) {  
    63.         this.innerPo = innerPo;  
    64.     }  
    65.   
    66.     public List<String> getMore() {  
    67.         return more;  
    68.     }  
    69.   
    70.     public void setMore(List<String> more) {  
    71.         this.more = more;  
    72.     }  
    73.       
    74.   
    75.     
    76.     @Override  
    77.     public String toString() {  
    78.           
    79.         StringBuffer sb = new StringBuffer();  
    80.         sb.append("id:"+id+" ");  
    81.         sb.append("name:"+name+" ");  
    82.         sb.append("remark:"+remark+" ");  
    83.         sb.append("age:"+age+" ");  
    84.         sb.append("array:"+Arrays.toString(array)+" ");  
    85.         sb.append("innerPo:"+innerPo.toString()+" ");  
    86.         sb.append("more:"+more);  
    87.         return  sb.toString();  
    88.     }  
    89.       
    90.       
    91. }  
    92.   
    93.   
    94. class InnerPo{  
    95.     private Integer id;  
    96.     private String name;  
    97.       
    98.     public InnerPo(){}  
    99.       
    100.     public InnerPo(Integer id,String name){  
    101.         this.id = id;  
    102.         this.name = name;  
    103.     }  
    104.       
    105.     public Integer getId() {  
    106.         return id;  
    107.     }  
    108.     public void setId(Integer id) {  
    109.         this.id = id;  
    110.     }  
    111.     public String getName() {  
    112.         return name;  
    113.     }  
    114.     public void setName(String name) {  
    115.         this.name = name;  
    116.     }  
    117.       
    118.       
    119.     @Override  
    120.     public String toString() {  
    121.         return id+"-"+name;  
    122.     }  
    123.       
    124. }  


    1. package gudao.red.protostuff;  
    2.   
    3. import java.util.ArrayList;  
    4. import java.util.List;  
    5.   
    6. import com.dyuproject.protostuff.LinkedBuffer;  
    7. import com.dyuproject.protostuff.ProtostuffIOUtil;  
    8. import com.dyuproject.protostuff.runtime.RuntimeSchema;  
    9.   
    10. public class ProtostuffTest {  
    11.       
    12.     static RuntimeSchema<Po> poSchema = RuntimeSchema.createFrom(Po.class);  
    13.       
    14.     private static byte[] decode(Po po){  
    15.         return ProtostuffIOUtil.toByteArray(po, poSchema, LinkedBuffer.allocate(LinkedBuffer.DEFAULT_BUFFER_SIZE));  
    16.     }  
    17.       
    18.     private static Po ecode(byte[] bytes){  
    19.         Po po = poSchema.newMessage();  
    20.         ProtostuffIOUtil.mergeFrom(bytes, po, poSchema);  
    21.         return po;  
    22.     }  
    23.       
    24.     public static void main(String[] args) {  
    25.         InnerPo innerPo = new InnerPo(1, "InnerPo1");  
    26.         List<String> list = new ArrayList<String>();  
    27.         list.add("a");  
    28.         list.add("b");  
    29.         Po po = new Po(1, "Fong", "备注", 24, new int[]{1,2,3,4},innerPo,list);  
    30.         byte[] bytes = decode(po);  
    31.         System.out.println(bytes.length);  
    32.         Po newPo = ecode(bytes);  
    33.         System.out.println(newPo);  
    34.     }  
    35.   
    36. }  

  • 相关阅读:
    hdu 4009 Transfer water(最小型树图)
    如何使用java调用DLL运行C++(初篇)
    腾讯笔试题(2015)
    md5算法原理一窥(其一)
    hdu 3038 How Many Answers Are Wrong ( 带 权 并 查 集 )
    Java 基础知识点(必知必会其二)
    Java 基础知识点(必知必会其一)
    web基础之hibernate(一篇)
    web基础之Structs(一篇)
    mysql知识初篇(一)
  • 原文地址:https://www.cnblogs.com/zhaoxinshanwei/p/8482358.html
Copyright © 2011-2022 走看看