GRPC入门和基础知识
GRPC是google开源的一个高性能、跨语言的RPC框架,基于HTTP2协议,基于protobuf 3.x,基于Netty 4.x +。
GRPC使用protobuf序列化协议,基于protobuf来声明数据模型和RPC接口服务。
RPC流程图
1、服务调用方(Client)将远程方法的信息(如类名、方法方法名、方法传入的参数)封装为统一的请求体;
2、序列化请求对象,转化为二进制串,方便传输;
3、通过 Client Stub 发送消息到指定的服务提供方;
4、Server Stub 接收来自 Client 的消息;
5、反序列化二进制串,转化为对象,方便使用;
6、根据请求体,执行本地方法;
7、封装方法执行结果为统一的响应体;
8、序列化响应体对象,转化为二进制串;
9、通过 Server Stub 将消息发送给对应的 Client;
10、Client Stub 接受消息;
11、反序列化二进制串,转化为对象;
12、得到方法执行的结果。
基本数据类型
proto Type | Java Type | Default Value |
---|---|---|
double | double | 0 |
float | float | 0 |
int32 | int | 0 |
uint32 | int | 0 |
uint64 | long | 0 |
sint32 | int | 0 |
sint64 | long | 0 |
fixed32 | int | 0 |
fixed64 | long | 0 |
sfixed32 | int | 0 |
sfixed64 | long | 0 |
bool | boolean | false |
string | String | 空string |
bytes | ByteString | 空的bytes |
枚举
枚举类型必须将其第一个类型映射为0且零值必须为第一个元素。
枚举常量必须在32位整型值的范围内,因为enum值是使用可变编码方式的,对负数不够高效,因此不推荐在enum中使用负数。
时间戳
import public "google/protobuf/timestamp.proto";
google.protobuf.Timestamp regists_time = 1;//注册时间
日期
com.google.type.Date opening_date=1;
Protobuf文件
指定正在使用的语法
指定正在使用proto3语法,如果你没有指定这个,编译器会使用proto2。这个指定语法行必须是文件的非空非注释的第一个行。
syntax = "proto3";
选项
Java_package
表明生成java类所在的包,如果在.proto文件中没有明确的声明java_package,就采用默认的包名。当然了,默认方式产生的 java包名并不是最好的方式,按照应用名称倒序方式进行排序的。如果不需要产生java代码,则该选项将不起任何作用。
option java_package = "com.example.foo";
java_outer_classname
表明想要生成Java类的名称。如果在.proto文件中没有明确的java_outer_classname定义,生成的class名称将会根据.proto文件的名称采用驼峰式的命名方式进行生成。如(foo_bar.proto生成的java类名为FooBar.java),如果不生成java代码,则该选项不起任何作用。
option java_outer_classname = "Yuanda"
objc_class_prefix
设置Objective-C类的前缀,添加到所有Objective-C从此.proto文件产生的类和枚举类型。没有默认值,所使用的前缀应该是苹果推荐的3-5个大写字符,注意2个字节的前缀是苹果所保留的。
option objc_class_prefix = "Grpc";
deprecated
如果设置为true则表示该字段已经被废弃,并且不应该在新的代码中使用。
int32 old_field = 6 [deprecated=true];
定义包名
包名应以公司名称开头,以及主要版本。
package com.yuanda.paas.v1.course;
导入定义
如果想要使用的已经在其他.proto文件中已经定义过的消息类型通过import方式进行导入。
import "myproject/other.proto";
默认情况下只能使用直接导入的.proto文件中的定义。 然而, import public 依赖性会通过任意导入包含import public声明的proto文件传递。
import public "google/protobuf/timestamp.proto";
定义消息类型
指定字段类型
所有字段都是必须制定数据类型,可以是基本数据类型也可以是其他的合成类型,如枚举或其他消息类型。
分配标识符
在消息定义中,每个字段都有唯一的一个数字标识符。这些标识符是用来在消息的二进制格式中识别各个字段的,一旦开始使用就不能够再改变。[1,15]之内的标识号在编码的时候会占用一个字节,[16,2047]之内的标识号则占用2个字节,所以应该为那些频繁出现的消息元素保留 [1,15]之内的标识号。切记:要为将来有可能添加的、频繁出现的标识号预留一些标识号。
最小的标识号可以从1开始,最大到2^29 - 1, or 536,870,911。不可以使用其中的[19000-19999], Protobuf协议实现中对这些进行了预留。
指定字段规则
repeated
在一个格式良好的消息中,这种字段可以重复任意多次(包括0次)。重复的值的顺序会被保留。
在proto3中,repeated的标量域默认情况虾使用packed。
注释
在.proto文件中使用//添加注释。
定义服务
// 定义通用的 Grpc 服务
service CommonService {
// 处理请求
rpc handle (EmployeeRequest) returns (EmployeeResponse) {
}
}
完整示例
//指定proto3格式
syntax = "proto3";
//一些生成代码的设置
option java_package = "cn.com.yd.commons.grpc";
option java_outer_classname = "GrpcService";
option java_multiple_files = true;
//定义服务
service CommonService {
// 处理请求
rpc handle (EmployeeRequest) returns (EmployeeResponse) {
}
}
//定义一个请求
message EmployeeRequest {
string _id = 1; //主键
string name = 2; //姓名
sint32 tall = 3; //身高,单位cm,大于0
sint32 age = 4; //年龄,大于0
double weight = 5; //体重,单位kg,大于0
Gender gender = 6; //性别
//google.type.Date birthDate = 7;//出生日期
google.protobuf.Timestamp regist_time = 10; //注册日期
}
//定义一个响应
message EmployeeResponse {
string msg = 1; //响应消息
bool state = 2; //响应状态true|false
}