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类型参见下表:
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:
执行完毕,会在/target/protoc-plugins 下下载到exe执行文件。同时将proto文件编译后的java类存放在 /target/generated-sources/protobuf 下,将此代码复制到java项目中即可。
※注意: 如果出现grpc产生的文件报错,找不到某些类,可能是plugin使用的工具grpc版本,和mvn实际要用的grpc-stub等版本不一致,需要调整版本。