gRPC

476 阅读4分钟

前置知识点

简介

  • gRPC是由Google公司开源的高性能RPC框架
  • gRPC支持多语言
  • gRPC原生使用C Java Go进行了三种实现,而C语言实现的版本进行封装后又支持C++ C# Node ObjC Python Ruby PHP等开发语言
  • gRPC支持多平台:Linux Android iOS MacOS Windows
  • gRPC的消息协议使用Google自家开源的Protocol Buffers协议 (proto3)
  • gRPC的传输使用HTTP/2标准,支持双向流和连接多路复用

截屏2022-12-23 16.52.03.png

架构

截屏2022-12-23 16.57.07.png

gRPC借口类型

gRPC有4种类型:

  • Unary RPC(一元RPC)
  • Server Straming RPC (服务器流式RPC)
  • Clinet Sreaming RPC (客户端流式RPC)
  • Bidirectional Streaming RPC (双向流式RPC) 对于底层的HTTP/2而言,这些都是数据流Steam,我们所说的接口类型是指进行一次gRPC调用的数据通讯流程(可以称为数据流(Stream)的生命周期)

Unary RPC

最简单的RPC类型,客户端发送单个请求并且返回单个响应

截屏2022-12-24 13.38.06.png

Server Straming RPC

服务器流式RPC中服务器可以返回多个响应信息 截屏2022-12-24 13.52.18.png

Client Steaming RPC

客户端流式RPC中客户端发送多个请求,服务端返回单个响应 截屏2022-12-24 13.56.45.png

Bidirectional Streaming RPC

在双向流式RPC中,客户端和服务器可以按任何顺序独立的读写数据流,服务器可以在收到所有的请求信息后再响应信息,或者收到一个请求信息返回一个响应信息,或者收到一些请求信息再返回一些请求信息,等等,都是可以的 截屏2022-12-24 14.00.54.png

Protocol Buffers

Protocol Buffers 是一种与语言无关,平台无关的可扩展机制,用于序列化结构化数据,使用Protocol Buffers可以一次定义结构化的数据,然后使用特殊生成的源代码轻松地在各种数据流中使用各种语言编写和读取结构化数据
现在有许多框架在使用Protocol Buffers,gRPC也是基于Protocol Buffers,Protocol Buffers的版本有2和3,在gRPC中推荐Proto3

文档结构

Protocol Buffers版本

Protocol Buffers文档的第一行并非注释,为版本声明,不写默认为2

syntax="proto3"
or
syntax="proto2"

Package包

Protocol Buffers可以声明package,来防止重命名冲突,Packages是可选的

// 声明
package foo.bar
message Open { ... }

使用的时候也要加上命名空间

message Foo {
    ...
    foo.bar.Open open = 1;
    ...

}

注意:对于Python而言,package会被忽略,因为Python中的包是以文件目录来定义的

导入

Protocol Buffers中可以导入其它文件消息等,与Python的import类似

import "myproject/...."

定义各种消息和服务

消息message是用来定义数据的,服务service是用来提供gRpce方法的

数据类型

基本数据类型

截屏2022-12-24 15.04.07.png

枚举

enum Corpus {
    WEB = 0;
    LOCAL = 1;
    ...
}
Corpus corpus = 4;

枚举定义在一个消息内部或者外部都是可以的,如果枚举定义在message内部,而其它message又要使用,可以通过MessageType.EnumType的方式引用
定义枚举的时候,我们要保证第一个枚举值必须是0,枚举值不能重复,除非使用option allow_alias=true选项来开启别名

enum EnumAllowingAlias {
    option allow_alias = true;
    UNKOWN = 0;
    STARTED = 1;
}

枚举值的范围是32-bit integer,但因为枚举值使用变长编码,所以不推荐使用负数作为枚举值,因为这会带来效率问题

消息类型

Protocol Buffers使用message定义消息数据,在Protocol Buffers中使用的数据都是通过message消息数据封装基本类型数据或者其他数据,对应Python中的类

message SearchRequest {
// 类型名 | 字段名 | 字段编号
    string query = 1;
    int32 page_number;
    int32 result_per_page = 3;
}

字段编号说明: 截屏2022-12-24 15.26.14.png

指定字段规则

截屏2022-12-24 15.32.24.png

message Result {
    string url = 1;
    string title = 2;
    repeated string snippets = 3;
}

定义多个消息类型

截屏2022-12-24 15.37.01.png

保留字段

截屏2022-12-24 15.37.54.png

嵌套类型

截屏2022-12-24 15.44.43.png

map映射

map<key_type, value_type> map_field = N

截屏2022-12-24 15.49.45.png

oneof

截屏2022-12-25 13.40.57.png

定义服务

Protocol Buffers使用service定义RPC服务

message HelloRequest {
    string greeting = 1;
}

message HelloResponse {
    string reply = 1;
}

service HelloService {
    rpc SayHello (HelloRequest) returns (HelloResponse) {}
}
// 一个service中可以定义多个方法
// Unary RPC
rpc SayHello (HelloRequest) returns (HelloResponse) {}
// Server Streaming RPC
rpc LotsOfReplies (HelloRequest) returns (stream HelloResponse) {}
// Client Streaming RPC
rpc LotsOfGreetings(stream HelloRequest) returns (HelloResponse) {}
// BidiRectional Streaming RPC
rpc BidiHello(stream HelloRequest) returns (stream HelloResponse) {}

gRPC-demo
参考视频