1. grpc原理
1.1 通信方式
gRPC 允许你定义四类服务方法:
简单RPC(Simple RPC)
即客户端发送一个请求给服务端,从服务端获取一个应答,就像一次普通的函数调用。
1
2rpc SayHello(HelloRequest) returns (HelloResponse){
}服务端流式RPC(Server-side streaming RPC):
一个请求对象,服务端可以传回多个结果对象。即客户端发送一个请求给服务端,可获取一个数据流用来读取一系列消息。客户端从返回的数据流里一直读取直到没有更多消息为止。
1
2rpc LotsOfReplies(HelloRequest) returns (stream HelloResponse){
}客户端流式RPC(Client-side streaming RPC)
客户端传入多个请求对象,服务端返回一个响应结果。即客户端用提供的一个数据流写入并发送一系列消息给服务端。一旦客户端完成消息写入,就等待服务端读取这些消息并返回应答。
1
2rpc LotsOfGreetings(stream HelloRequest) returns (HelloResponse) {
}双向流式RPC(Bidirectional streaming RPC)
结合客户端流式rpc和服务端流式rpc,可以传入多个对象,返回多个响应对象。即两边都可以分别通过一个读写数据流来发送一系列消息。这两个数据流操作是相互独立的,所以客户端和服务端能按其希望的任意顺序读写。
1
2rpc BidiHello(stream HelloRequest) returns (stream HelloResponse){
}
1.2 超时
go里面一般会使用Context进行超时控制以及参数传递, 其中超时控制可以使用context.WithDeadline()或者context.WithTimeout()实现, 二者实现效果是一致的。
gRPC基本上所有的对外函数都是带context参数的, 所以说它默认就集成了context的功能, 我们只需要在调用方法的时候传入 ctx 参数便可。
WithTimeout 只能设置在某一段时间后超时,比如3秒后超时。
WithDeadline() 则可以设置到具体某个时间点, 比如在临晨0点10分20秒的时候返回。
1.3 重试
gRPC 中已经内置了 retry 功能,客户端需要通过grpc.WithDefaultServiceConfig()
配置 retry 功能, 并且设置环境变量export GRPC_GO_RETRY=on
- client.go
1 | func main() { |
1.4 拦截器
拦截器(interceptor)是grpc提供给开发者便于在每个RPC请求前中后进行如认证、鉴权、统计等功能的机制,熟悉Gin框架的同学的可以把拦截器理解为gin.HandlerFunc中间件,只不过grpc由于是双向通信,所以客户端和服务端都可以使用interceptor。
拦截器主要划分为两种,一元拦截器(unary interceptor)和流拦截器(stream interceptor),区别就是在于有没有rpc使用stream。
2. 安装使用
2.1 下载protoc 生成器
通过proto文件,生成相关代码。下载地址:https://github.com/protocolbuffers/protobuf/releases
例如我下载的是 protoc-3.9.0-osx-x86_64.zip
1 | cd protoc-3.9.0-osx-x86_64 |
2.2 proto文件
helloworld.proto 文件如下
1 | syntax = "proto3"; |
2.3 golang使用
1 | go get -u google.golang.org/grpc |
我们去 $GOPATH/src/google.golang.org/grpc/examples
看helloworld例子
1 | cd $GOPATH/src/google.golang.org/grpc/examples/helloworld |
我们通过.proto文件生成golang文件, 生成后的文件不要编辑。
1 | protoc -I helloworld/ helloworld/helloworld.proto --go_out=plugins=grpc:helloworld |
运行后生成了 helloworld.pb.go
client 和 server 调用
我们看下greeter_server
的代码并且启动: go run greeter_server/main.go
1 | package main |
我们看下greeter_client
的代码并且启动:go run greeter_client/main.go
1 | package main |
If things go smoothly, you will see the Greeting: Hello world
in the client side output.
Congratulations! You’ve just run a client-server application with gRPC.
增加新的方法实现
在proto文件里增加
rpc SayHelloAgain (HelloRequest) returns (HelloReply) {}
的定义通过protoc重新生成golang文件, 生成的文件里增加了SayHelloAgain相关方法。
修改server文件增加方法来实现接口
1 | func (s *server) SayHelloAgain(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) { |
- 修改client方法增加调用
1 | r, err = c.SayHelloAgain(ctx, &pb.HelloRequest{Name: name}) |
2.4 cpp 版本
参考: https://github.com/grpc/grpc/blob/master/BUILDING.md
1 | # 安装xcode command line tools |
我们先进入hellworld例子
1 | cd examples/cpp/hellworld/ |
还可以这样生成:
1 | protoc --cpp_out=. helloworld.proto |
2.5 python版本
1 | sudo python3 -m pip install grpcio |