Protobuf

原理

protobuf 采用二进制文件传输数据,使用双方统一约定的规则传递数据进行序列化和反序列化(数据存根Stub),数据在传递过程中没有像json需要指定key,使用T - L - V 存储数据序列,数据也会因为类型采用不同的编码格式,以最小的数据流传递数据。

  • String 采用 UTF-8编码

此文章对ProtoBuf有深入的讲解:Protobuf序列化原理

proto文件

proto是一种通讯协议,.proto为文件格式,具有语言无关性。文件后缀以.proto命名。
Proto使用手册

message

syntax="proto3"; //默认为proto2,此放在第一行,不能有注释放在第一行。
// 注释采用双斜杠

import "Family.proto"; //引入外部对象
import public "Family.proto";  //可透传引入,即如果family中有import,此处也可使用

// message修饰符表示此为传递的数据对象
message UserInfo{
   required int32 id=1;
   optional string name=2 [default="张三"];
   map<int32, string> dataMap = 3; //map类型
   repeated string addressList = 4 [packed=true]; //packed=true可实现T-L-V-V-V存储,节省空间 List类型
   repeated WorkHis workhisList = 5;  //可嵌套其它message
   Family family = 6; //通过import导入外部message对象
   int32 oldName = 7 [deprecated=true]; //deprecated已不推荐使用
}

// 被上面使用的message
message WorkHis{
	string company=1;
	int32 duration=2;

}

※注意:字段一旦确定就不能发生变更,可以删除字段,但是新字段不能再占用原有字段的序号位置,新字段只能放到最后递增。不可随意调整顺序位置。

字段序号:

字段序号用于说明字段的位置,一般建议连续排列。且从1-15为宜,用16进制1个字节就可存储,16-2047 用2个字节存储。

修饰符参见下表:

修饰符 含义 说明
required 必填 pro3 已废弃
optional 可选
repeated 可重复,用于多值的List类型
singular 可选,和optional意义一样,3版本出来
reserved 废弃指定的字段,使用方式:reserved 1, 4, 8 to 11;reserved "foo", "bar";

数据类型对应Java类型参见下表:
image

service(服务)

syntax="proto3";


// 用于服务端定义接收体和返回体
service rpcUser{
  rpc searchUser(UserInfo) returns (UserInfo) {} //userInfo为指定的message
  rpc upload(stream UserInfo) returns (UserInfo) {} //流式数据上传
  rpc download(string) returns(stream UserInfo){} //流式数据下载
}

option(选项) 针对Java

package com.test.proto; //proto文件的package,用于区分多个proto的message引用重复问题,一旦确定则不能再修改,类查找将添加此package否则会找不到对应类

option java_multiple_files = true;  //多文件分离
option java_package="com.test.proto"; // java的package名称
option java_outer_classname="UserInfo"; // java的对象名称
option optimize_for=SPEED;//可选值[SPEED|CODE_SIZE|LITE_RUNTIME],lite需要引入额外包定义



转换器

protobuf执行转换器下载地址github
选择 protoc-21.7-win64.zip 或者 protoc-21.7-linux-x86_64.zip
如果版本过高可选择低版本安装。
转换器支持 JAVA,RUBY, Python, PHP ,C++;
转换器是将proto文件对象,转换成常用语言开发的对象。

./bin/protoc --proto_path=/opt/protoc/protoFile --java_out=protoFile User.proto

grpc转换器

grpc转换器下载地址:MVN-protoc-gen-grpc-java
下载下来后执行命令

D:\software\protoc-21.7-win64\bin\protoc.exe --plugin=protoc-gen-grpc-java=D:\software\protoc-21.7-win\protoc-gen-grpc-java.exe --grpc-java_out=D:\logs ./AuthInfo.proto

※在windows环境下会由于C:\Users\在展示上是叫用户为中文名,和内部用户也有的有中文名,且无法修改名称,导致出现:protoc-gen-grpc-java: The system cannot find the path specified.

Linux下使用:

./bin/protoc --plugin=protoc-gen-grpc-java=/opt/protoc/protoc-gen-grpc-java-1.50.0-linux-x86_64.exe --grpc-java_out=./protoFile ./protoFile/AuthInfo.proto

※注意:linux下下载的也是exe文件,但是exe文件在linux下是默认不可执行文件,因此要调整 chmod 777 protoc-gen-grpc-java-1.50.0-linux-x86_64.exe 使其变为可执行文件即可。

idea protobuf插件使用

选择插件 protobuf Generator and protobuf Support 安装。
Tools -》 Configure Gen Protobuf Plugin
示例
在resources 创建文件夹protobuf ,创建.proto文件.
MAVEN的Pom.xml文件

        <dependency>
            <groupId>com.google.protobuf</groupId>
            <artifactId>protobuf-java-util</artifactId>
            <version>${protobuf.version}</version>
        </dependency>

文件上右键选择quick gen protobuf here or rules都可以。

※:注意生成的文件有时idea加载不及时,需要刷新idea reload disk,重新reload project生效。

maven plugin proto-buf使用

            <plugin>
                <groupId>kr.motd.maven</groupId>
                <artifactId>os-maven-plugin</artifactId>
                <version>1.5.0.Final</version>
            </plugin>

            <plugin>
                <groupId>org.xolstice.maven.plugins</groupId>
                <artifactId>protobuf-maven-plugin</artifactId>
                <version>0.6.1</version>
                <extensions>true</extensions>
                <configuration>
                    <!--默认值-->
                    <temporaryProtoFileDirectory>${project.build.directory}/generated-sources/protobuf/java</temporaryProtoFileDirectory>
                    <!--更多配置信息可以查看https://www.xolstice.org/protobuf-maven-plugin/compile-mojo.html-->
                    <!--suppress UnresolvedMavenProperty -->
                    <protocExecutable>D:\software\protoc-21.7-win64\bin\protoc.exe</protocExecutable>
                    <protocArtifact>
                        com.google.protobuf:protoc:${protobuf.version}:exe:${os.detected.classifier}
                    </protocArtifact>
                </configuration>
                <executions>
                    <execution>
                        <phase>compile</phase>
                        <goals>
                            <goal>compile</goal>
                        </goals>
                        <!--也可以设置成局部变量,执行compile或test-compile时才执行-->
                        <configuration>
                            <protoSourceRoot>${project.basedir}/src/main/resources/protobuf</protoSourceRoot>
                            <outputDirectory>${project.basedir}/src/main/java</outputDirectory>
                            <!--设置是否在生成java文件之前清空outputDirectory的文件,默认值为true,设置为false时也会覆盖同名文件-->
                            <clearOutputDirectory>false</clearOutputDirectory>
                        </configuration>
                    </execution>
                </executions>
            </plugin>

带 grpc mvn插件方式

mvn插件方式就可以不用下载protoc.exe,grpc-gen-protoc-java直接通过plugin操作即可。最好在properties中s手动添加 os.detected.classifier,不然会提示下载不到proto内容。
完整的mvn插件:

   
<properties>
    <os.detected.classifier>windows-x86_64</os.detected.classifier>
</properties>

   <build>
        <plugins>
            <plugin>
                <groupId>kr.motd.maven</groupId>
                <artifactId>os-maven-plugin</artifactId>
                <version>1.5.0.Final</version>
            </plugin>

            <plugin>
                <groupId>org.xolstice.maven.plugins</groupId>
                <artifactId>protobuf-maven-plugin</artifactId>
                <version>0.6.1</version>
                <extensions>true</extensions>
                <configuration>
                    <protocArtifact>
                        com.google.protobuf:protoc:3.12.0:exe:${os.detected.classifier}</protocArtifact>
                    <pluginId>grpc-java</pluginId>
                    <pluginArtifact>io.grpc:protoc-gen-grpc-java:1.30.2:exe:${os.detected.classifier}</pluginArtifact>
                </configuration>
            </plugin>
        </plugins>
    </build>

将文件*.protoe文件放入到/src/main/proto 和 /src/test/proto 下。
mvn reload Project,选择Plugin:
image
执行完毕,会在/target/protoc-plugins 下下载到exe执行文件。同时将proto文件编译后的java类存放在 /target/generated-sources/protobuf 下,将此代码复制到java项目中即可。

※注意: 如果出现grpc产生的文件报错,找不到某些类,可能是plugin使用的工具grpc版本,和mvn实际要用的grpc-stub等版本不一致,需要调整版本。

posted on 2022-10-13 00:06  zhaoqiang1980  阅读(244)  评论(0编辑  收藏  举报