Google Protobuf知识解析

首先先弄清楚几个概念:

  • RPC

应用步骤:

  1. 定义一个接口说明文件(IDL),去描述对象(结构体)、对象成员、接口方法等一系列信息。
  2. 通过RPC框架所提供的编译器,将接口说明文件编译成具体语言文件。
  3. 在客户端与服务器端分别引入RPC编译器所生成的文件,即可以像调用本地方法一样调用远程方法。

效率:

RPC的效率主要在于编解码的快慢。

  • Protobuf

可以说是一种通过RPC(Remote Procedure call)协议去进行数据传输的通信协议,这种协议以更小的体积对数据进行编码和解码,也就是序列化和反序列化,并且实现跨语言,和只限于Java语言的RMI协议的端到端就不同了。

  • RMI

说到这种远程通信协议,就有必要说一下RMI了,RMI全称Remote method invocation,意思也就是远程方法调用,令不同电脑之间的方法可以互相调用,其原理也是编解码,client端的方法有一个封装好的stub,server端有一个封装好了skeleton,然后这两个封装好的工具进行socket通信,实现方法编解码与通信。

  • 序列化和反序列化

分别对应着编码和解码,也就是将对象转换为对应的字节码,然后返回去,也就是序列化和反序列化的意思

实现序列化和反序列化

首先我们先看看官网对于序列化和反序列化给出的提示吧:

在这里插入图片描述

  1. 使用Java序列化,这是一种最原生的方法,因为语言中已经设计好了,但是问题就是,如果你的产品是用c++或者python开发的,数据无法共享。
  2. 你也可以给数据进行编码,这是一种简单且灵活的方法,尽管在编码和解码的时候会浪费系统资源,所以你可以用在简单的数据上。
  3. 将数据转换成为xml,因为xml可读性强,并且很多语言都有识别xml的库,所以你想分享语言的产品是用不同语言开发的,也不会有问题的,但是问题就是xml的标签很占用内存,并且解码也很占用时间内存。

在这里插入图片描述
总结:protobuf很灵活,高效,有影响力,可以自动化精确的解决问题。你可以用.proto描述你所希望存储的数据结构,然后protubuf就能创建一个类,自动实现编码和解析,并且创建的类拥有get set方法,并且可以横向扩展,令程序读取老数据格式。

然后我们就来看看具体的实现细节:

  1. 创建一个.proto文件,将要序列化的message填进去,标记出每一个字段的名字和种类。
  • require:被标记的字段一定要提供值,否则报错。
  • optional:如果标记的字段不提供值,就会自动给一个默认值,同时默认值,default=xxx,也是可以自己设定默认值的。同样,访问这个值,你不给他初值,也是return一个默认值。
  • repeated:可以重复去声明,每次声明的信息,存储在protobuf里面。

注意:require标记的字段如果突然在半途想换成optional去修饰,是不可以的,会报错,因为这属于语法就错了。所以google的工程师建议字段直接标记为optional或者repeated。

  1. 编写构建器/信息
    在这里插入图片描述

也就是Builders/messages,这两个是有一定区别的,由protocol buffer定义的消息都是不可变长的,一旦消息对象定义就无法修改了,要想定义一个消息,就要先造出构建消息的构造器,将要设置的任何字段设置为可选值,然后调用构建器的build方法就行了。

并且你会注意到每次你修改message就会返回另一个构建的形体,其实返回的事实上是相同的方法,目的是你能多塞几个setter进去到一行代码里。
在这里插入图片描述

接下来演示一下:

先创建出来.proto文件
在这里插入图片描述

然后按照官网的格式去编写(项目使用的protobuf为3.9.1)

syntax = "proto3";

package com.protocol;

option optimize_for = SPEED;
option java_package = "com.protocol";
option java_outer_classname = "DataInfo";

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


然后是protoc编译生成代码
protoc --java_out=src/main/java src/probuf/Student.proto

这时就会生成一个文件,但是这个文件是不能修改的,一旦修改,就会覆盖原有的序列化反序列化的方法。
在这里插入图片描述

之前也说了protobuf本来就是专门来序列化反序列化字段最后去做数据存储的一种高性能工具。

于是我们来写一个测试demo

package com.protocol;

import com.google.protobuf.InvalidProtocolBufferException;

public class ProtoBufTest {
    public static void main(String[] args) throws InvalidProtocolBufferException {

        //先序列化
        DataInfo.Student build = DataInfo.Student.newBuilder()
                .setName("zhangsan")
                .setAddress("Beijing")
                .setAge(18)
                .build();
        //序列化之后存储字节数组
        byte[] student2ByteArray = build.toByteArray();

        //反序列化回来
        DataInfo.Student student = DataInfo.Student.parseFrom(student2ByteArray);

        System.out.println(student);

    }
}

//output:
//name: "zhangsan"
//age: 18
//address: "Beijing"
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值