我正在学习酷酷的 Golang,可点此查看帖子Golang学习笔记汇总。
gRPC 是一个高性能、开源、通用的 RPC 框架。
A high performance, open-source universal RPC framework.
gRPC is a modern open source high performance RPC framework that can run in any environment. It can efficiently connect services in and across data centers with pluggable support for load balancing, tracing, health checking and authentication. It is also applicable in last mile of distributed computing to connect devices, mobile applications and browsers to backend services.
先了解几个基本概念,https://grpc.io/docs/guides/concepts/
gRPC 默认使用 protocol buffers 作为接口描述语言,用它来描述服务端接口及消息格式。
service HelloService {
rpc SayHello (HelloRequest) returns (HelloResponse);
}
message HelloRequest {
string greeting = 1;
}
message HelloResponse {
string reply = 1;
}
gRPC 允许你定义四类服务方法:
gRPC提供了 protocol buffer 编译器插件,可生成客户端和服务器端代码。 gRPC用户通常在客户端(stub)调用这些API,并在服务器端实现相应的API。
阻塞的同步RPC调用直到服务器收到响应为止是最接近RPC所追求的过程调用抽象的近似方法。 另一方面,网络本质上是异步的,并且在许多情况下能够启动RPC而不阻塞当前线程很有用。
gRPC编程都有同步和异步两种形式。
参考 https://grpc.io/docs/quickstart/go/
安装 gRPC
$ go get -u google.golang.org/grpc
安装 PROTOC 编译器
3.7.1 版本安装示例:
$ PROTOC_ZIP=protoc-3.7.1-linux-x86_64.zip
$ curl -OL https://github.com/google/protobuf/releases/download/v3.7.1/$PROTOC_ZIP
$ sudo unzip -o $PROTOC_ZIP -d /usr/local bin/protoc
$ rm -f $PROTOC_ZIP
3.10.1 版本安装示例:
PROTOC_ZIP=protoc-3.10.1-linux-x86_64.zip
curl -OL https://github.com/protocolbuffers/protobuf/releases/download/v3.10.1/$PROTOC_ZIP
sudo unzip -o $PROTOC_ZIP -d /usr/local bin/protoc
rm -f $PROTOC_ZIP
安装 protoc 的 go 插件
$ go get -u github.com/golang/protobuf/protoc-gen-go
protoc-gen-go 将会安装在 GOBIN, 默认是 GOPATH/bin. 需要在
$ export PATH=$PATH:$GOPATH/bin
$ cd $GOPATH/src/google.golang.org/grpc/examples/helloworld
开两个终端,分别执行 server 和 client:
$ go run greeter_server/main.go
$ go run greeter_client/main.go
这样执行之后,终端上就有日志打印出来了:
# go run greeter_client/main.go
2019/11/04 12:21:47 Greeting: Hello world
# go run greeter_server/main.go
2019/11/04 12:21:47 Received: world
// 1 定义服务
service Greeter {
// 2 定义服务中的方法
rpc SayHello (HelloRequest) returns (HelloReply) {}
}
// 3 定义方法中的请求消息格式
message HelloRequest {
string name = 1;
}
// 4 定义方法中的回复消息格式
message HelloReply {
string message = 1;
}
// Step1. grpc 连接
conn, err := grpc.Dial(address, grpc.WithInsecure())
if err != nil {
log.Fatalf("did not connect: %v", err)
}
defer conn.Close()
// Step2. 新建客户端 c := pb.New(ServiceName)Client(conn)
c := pb.NewGreeterClient(conn)
// Step3. 准备 context 用于 grpc 请求
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
defer cancel()
// Step4. 客户端调用预先定义的方法,并传入方法对应的请求 c.(MethodName)(ctx, &pb.(RequestMessageName))
r, err := c.SayHello(ctx, &pb.HelloRequest{Name: name})
// Step1. 配置监听的协议和端口
lis, err := net.Listen("tcp", port)
if err != nil {
log.Fatalf("failed to listen: %v", err)
}
// Step2. 新建 grpc 服务端
s := grpc.NewServer()
// Step3. 将 pb消息处理 的实例进行注册
pb.RegisterGreeterServer(s, &server{})
// Step4. 启动监听服务
if err := s.Serve(lis); err != nil {
log.Fatalf("failed to serve: %v", err)
}
除了这4步常规操作之外,更重要的是定义 pb消息处理 的实例:
// server is used to implement helloworld.GreeterServer.
type server struct{}
// SayHello implements helloworld.GreeterServer
func (s *server) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) {
log.Printf("Received: %v", in.Name)
return &pb.HelloReply{Message: "Hello " + in.Name}, nil
}
在 pb 中增加新的方法
service Greeter {
// Sends a greeting
rpc SayHello (HelloRequest) returns (HelloReply) {}
// Sends another greeting
rpc SayHelloAgain (HelloRequest) returns (HelloReply) {}
}
使用 protoc 自动更新代码
protoc -I helloworld/ helloworld/helloworld.proto --go_out=plugins=grpc:helloworld
在 greeter_server/main.go 中更新 server 代码
func (s *server) SayHelloAgain(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) {
return &pb.HelloReply{Message: "Hello again " + in.GetName()}, nil
}
在 greeter_client/main.go 中更新 client 代码
r, err = c.SayHelloAgain(ctx, &pb.HelloRequest{Name: name})
if err != nil {
log.Fatalf("could not greet: %v", err)
}
log.Printf("Greeting: %s", r.GetMessage())
运行结果
$ go run greeter_client/main.go
Greeting: Hello world
Greeting: Hello again world
本篇笔记演示了如何使用 gRPC 框架,包括 proto 文件定义服务,使用 pb 编译器产生代码,最后使用 gRPC API 编写 client 和 server 代码。