gRPC相关介绍
一、RPC
什么是RPC
RPC是指远程过程调用(Remote Procedure Call),它的调用包含了传输协议和编码(对象序列号)协议等等。允许运行于一台计算机的程序调用另一台计算机的子程序,而开发人员无需额外的为这个交互作用编程。
实际场景
有两台服务器,分别是A、B。在A上的应用C想要调用B服务器上的应用D,它们可以直接本地调用吗?
答案是不能的,但走RPC的话,十分方便。因此常有人称使用RPC,就跟本地调用一个函数一样简单
RPC框架
通常来说,一个完整的RPC框架,应包含负载均衡、服务注册和发现、服务治理等功能,并具有可拓展性便于流量监控系统等接入。那么它才算完整的。当然,有一些比较单一的RPC框架,通过组合多组件也能达到这个标准。
常见RPC框架
为什么要RPC
简单、通用、安全、效率
RPC可以基于HTTP吗
RPC是代指远程过程调用,是可以基于HTTP协议的。肯定会有人说效率优势,但那是基于HTTP/1.1来讲的,HTTP/2优化了许多问题(当然也存在新的问题)。
二、Protobuf
介绍
Protocol Buffers是一种与语言、平台无关,可扩展的序列化结构化数据的方法,常见于通信协议,数据存储等等。相较于JSON、XML,它更小、更快、更简单,因此也更受开发人员的青睐。
语法
syntax = 'proto3';
service SearchService {
rpc Search (SearchRequest) returns (SearchResponse);
}
message SearchRequest {
string query = 1;
int32 page_number = 2;
int32 result_per_page = 3;
}
message SearchResponse {
...
}
- 第一行(非空的非注释行)声明使用
proto3
语法。如果不声明,将默认使用proto2
语法。建议不管是使用v2还是v3都应当声明其使用的版本 - 定义
SearchService
RPC服务,其包含RPC方法Search
,入参为SearchRequest
消息,出参为SearchResponse
消息 - 定义
SearchRequest
、SearchResponse
消息,前者定义了三个字段,每一个字段包含了三个属性:类型、字段名称、字段编号 - Protobuf编译器会根据选择的语言不同,生成相应语言的Service Interface Code和Stubs
- 消息定义中的每个字段都有一个唯一的编号。这些字段号用于标识
消息二进制格式的
字段,一旦使用了消息类型,就不应该更改这些字段号。需要注意的是,范围1到15的字段号需要一个字节来编码,包括字段编号和字段的类型。16到2047之间的字段编号占用两个字节。不能使用保留的字段好(19000-19999)。你可以指定的最小为1,最大为2²⁹-1(536870911)
数据类型
.proto Type | Go Type |
---|---|
double | float64 |
float | float32 |
int32 | int32 |
int64 | int64 |
uint32 | uint32 |
uint64 | uint64 |
sint32 | int32 |
sint64 | int64 |
fixed32 | uint32 |
fixed64 | uint64 |
sfixed32 | int32 |
sfixed64 | int64 |
bool | bool |
string | string |
bytes | []byte |
v2和v3主要区别
- 删除原始值字段的字段存在逻辑
- 删除required字段
- 删除optional字段,默认就是
- 删除default字段
- 删除扩展特性,新增Any类型来替代它
- 删除unknown字段的支持
- 新增JSON Mapping
- 新增Map类型的支持
- 修复enum的unknown类型
- repeated默认使用packed编码
- 引入了新的语言实现(C#,JavaScript,Ruby,Objective-C)
相较Protobuf,为什么不使用XML?
- 更简单
- 数据描述文件只需要原来的1/10至1/3
- 解析速度是原来的20倍至100倍
- 减少了二义性
- 生成了更易使用的数据访问类
三、gRPC
介绍
gRPC是一个高性能、多语言、开源和通用的RPC框架,面向移动和HTTP/2设计
特点
- HTTP/2
- Protobuf
- 客户端、服务端基于同一份IDL
- 移动网络的良好支持
- 支持多语言
概念
讲解
- 客户端(gRPC Sub)调用A方法,发起RPC调用
- 对请求信息使用Protobuf进行对象序列化压缩(IDL)
- 服务端(gRPC Server)接收到请求后,解码请求体,进行业务逻辑处理并返回
- 对相应结果使用Protobuf进行对象序列化压缩(IDL)
- 客户端接收到服务端的响应,解码请求体。回调被调用的A方法,唤醒正在等待响应(阻塞)的客户端调用并返回响应结果
示例
在这一小节,将简单的给大家展示gRPC的客户端和服务端的示例代码。
构建和启动服务端
list, err := net.Listen("tcp",fmt.Sprintf(":%d",*port))
if err != nil {
log.Fatalf("failed to listen:%v",err)
}
grpcServer := grpc.NewServer()
...
pb.RegisterSearchServer(grpcServer,&SearchServer{})
grpcServer.Serve(list)
创建客户端
var opts []grpc.DialOption
...
conn,err := grpc.Dial(*serverAddr, opts...)
if err != nil {
log.Fatalf("fail to dial:%v",err)
}
defer conn.Close()
client := pb.NewSearchClient(conn)
- 创建gRPC Channel与gRPC Server进行通信(需要服务器地址和端口作为参数)
- 设置DialOptions凭证(例如,TLS,GCE凭据,JWT凭证)
- 创建Search Client Stub
- 调用对应的服务方法