gRPC
最初是 google 开发的高性能,且功能强大的开源 RPC 框架,后来被纳入云原生基金会的托管项目中,由于背靠 google 老大哥,不论是技术储备还是生态建设都十分的成熟和完善。是一个应用非常广泛的 RPC
框架。
由RPC 详解我们知道,RPC 框架中有两个核心组件,客户端存根(client-stub)和服务端存根(server-stub)。业务代码通过调用存根提供的接口,使得远程调用看起来像本地接口调用一样。要创建这两个存根,我们需要明确客户端存根和和服务端存根传递消息的格式,传递消息使用的协议,以及类似参数传递等问题(这些在RPC 详解中已经介绍,这里不再赘述)。而定义这些服务使用的语言我们称作(IDL),服务定义语言(interface definition language)。
gRPC
使用 proto buffers
作为服务定义语言,编写 proto 文件,即可完成服务的定义。
syntax = "proto3";
message {
name_of_field_1 = tag_1;
name_of_field_2 = tag_2;
...
name_of_field_n = tag_n;
}
消息类型采用驼峰格式
消息域采用小写字母蛇形格式
基本数据类型有:
string, bool, bytes,
float, double
int32, int64, uint32, uint4, sint32, sint64, etc.
数据类型也可以是自定义的消息类型和枚举类型
tag_n :字段编号,用于二进制消息中识别各个字段,该编号在每个消息中唯一,且不可修改。注意在将message编码成二进制消息体时字段编号1-15将会占用1个字节,16-2047将占用两个字节。所以在一些频繁使用用的message中,你应该总是先使用前面1-15字段编号。
注意在将message编码成二进制消息体时字段编号1-15将会占用1个字节,16-2047将占用两个字节。所以在一些频繁使用用的message中,你应该总是先使用前面1-15字段编号。
mysql.proto 定义了一个 SelectRecord
gRPC 接口
syntax = "proto3"; // 1
package sample; // 2
option go_package = "./;pb"; // 3
import "google/api/annotations.proto"; // 4
message CreateMysqlRequest { // 5
string sql = 1; // 6
}
message CreateMysqlResponse { // 7
string body = 1; // 8
}
service MysqlService { // 9
rpc SelectRecord(CreateMysqlRequest) returns (CreateMysqlResponse) { // 10
option (google.api.http) = { // 11
post : "/v1/mysql/select"
body : "*"
};
};
}
syntax = "proto3";
,文件开头指定版本号;
package sample;
,定义本服务的包名,避免不同服务相同消息类型产生冲突;
option go_package = "./;pb";
,生成 go 代码对应的路径和目录;
import "google/api/annotations.proto";
,需要引用外部 proto 文件时使用;
CreateMysqlRequest
,请求消息类型定义;
sql
,定义消息中域的名称和类型,支持的类型可参考下面的链接,后面的数字同一个类型下面必须唯一;
CreateMysqlResponse
,响应消息类型;
body
,定义消息中域的名称和类型,支持的类型可参考下面的链接,后面的数字同一个类型下面必须唯一;
MysqlService
,定义服务的接口名称;
SelectRecord
,远程调用方法名;
option (google.api.http)
,gRPC
网关,用于支持 http 协议。
关于 proto buffers
详细内容可以参考谷歌的教程:https://developers.google.com/protocol-buffers/docs/gotutorial
使用编译器 protoc
,可以将 proto 文件编译生成客户端和服务端存根代码,要让这些代码能能够正常工作,我们还需要做以下事情。
在服务端代码中添加业务逻辑代码;
type MysqlServer struct{}
// NewMysqlServer returns a new MysqlServer
func NewMysqlServer() *MysqlServer {
return &MysqlServer{}
}
// SelectRecord selects record with the specific table
func (server *MysqlServer) SelectRecord(
ctx context.Context, req *pb.CreateMysqlRequest,
) (*pb.CreateMysqlResponse, error) {
sql := req.GetSql()
// business logic
// ...
}
创建并启动 gRPC
监听端口,并返回响应客户端请求。
func main() {
// step 1: news a server message struct
mySqlServer := service.NewMysqlServer()
// step 2: difines a listen address
listener, _ := net.Listen("tcp", address)
// setp 3: news a grpc server
grpcServer := grpc.NewServer()
// setp 4: regists grpc server
pb.RegisterMysqlServiceServer(grpcServer, mysqlServer)
reflection.Register(grpcServer)
// step 5: starts grpc server
return grpcServer.Serve(listener)
}
设置连接地址和端口号,调用 gRPC
接口(客户端和服务端可能使用不同的开发语言,需要使用 protoc
编译生成对应的开发语言代码)
func main() {
serverAddress := flag.String("address", "", "the server address")
flag.Parse()
cc1, err := grpc.Dial(*serverAddress)
mysqlClient := client.NewMysqlClient(cc1)
// business logic
log.Printf(mysqlClient.SelectRecord("SELECT * FROM users WHERE id=1;"))
}
到这里一个完整的 gRPC
服务就完成了,那么 gRPC
有哪些优势呢?
高效的进程间通信
不同于文本传输的 JSON
和 XML
,gRPC
使用基于二进制 proto buffers
协议进行客户端和服务端之间的通信,它是基于 HTTP2 协议标准实现的,不同进程间通信更加的快捷。
支持一些常用特性功能
如权限校验,加密通信,服务超时服务截止时间,元数据交换,压缩,负载均衡以及服务发现等等。
集成到了云原生生态中
gRPC
作为云原生基金会的一个托管项目,大多数现代框架和技术都提供了对 gRPC
的支持。
对于外部服务可能不是适用
有可能对方(本公司)系统不支持 gRPC
服务,也有可能不能向对方(非本公司)暴露gRPC
服务。早期 gRPC
不支持 HTTP 请求,不过现在这个问题已经解决了,可以通过 gRPC
网关将 http
请求转为 gRPC
请求。这样服务可以支持 gRPC
和 HTTP
两种请求。
对于频繁更迭的服务接口,不是很适用
每次修改服务接口,我们通常需要重新生成客户端和服务端代码,需要将这些代码并入现存的持续集成服务中,这可能使得整体开发周期变得复杂。但是,gRPC
对于不破坏服务约定的修改具有很好的兼容性,允许客户端和服务端使用不同版本的 proto
文件,因此代码重新生成也不是什么问题。
生态相对较小
和传统的 REST/HTTP 协议相比,gRPC
在浏览器和移动端应用的支持还处于很初级的阶段。
type | request | response | scenario |
---|---|---|---|
unary | unary | unary | normal |
client streaming | streaming | unary | continuous request |
server streaming | unary | streaming | continuous response |
bidirectional streaming | streaming | streaming | continuous request and response |
体验一把:http://www.http2demo.io
gRPC Up and Running
https://blog.csdn.net/weixin_39678525/article/details/110570486
https://developers.google.com/protocol-buffers/docs/gotutorial
https://www.bilibili.com/video/BV1Xv411t7h5?spm_id_from=333.999.0.0