gRPC的简单使用

突然想学习使用一下gRPC,下文会简单的构建一个RPC服务,使用go作为服务端和客户端。

定义服务

gRPC使用Protobuf作为序列化工具,所以首先需要安装Protobuf,编译之后会生成protoc可执行程序。以Echo服务为例子,首先在proto文件中定义服务和协议。如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
syntax = "proto3";
package echo;
message EchoRequest{
string message = 1;
}
message EchoResponse{
string message = 1;
}
service EchoService{
rpc Echo(EchoRequest) returns (EchoResponse);
}

代码生成

定义好协议之后,就可以使用protoc生成对应编程语言的代码了。protoc使用的格式如下:

1
protoc -I $SRC_DIR --go_out=$DST_DIR $SRC_DIR/echo.proto

我们为了使用gRpc构建RPC服务,还需要生成通信代码,只需要加上插件参数即可:

1
protoc -I $SRC_DIR --go_out=plugins=grpc:$DST_DIR $SRC_DIR/echo.proto

服务端实现

服务端需要实现以下三个功能:
1.定义一个server结构,实现echo.pb.go定义的Echo接口
2.把server注册到gRPC Server
3.启动gRPC的监听服务
实现代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
package main
import (
"context"
"google.golang.org/grpc"
"google.golang.org/grpc/reflection"
pb "grpc_demo"
"log"
"net"
)
const port = ":7777"
type EchoServer struct{}
func (s *EchoServer) Echo(ctx context.Context, in *pb.EchoRequest) (*pb.EchoResponse, error) {
return &pb.EchoResponse{in.Message}, nil
}
func main() {
lis, err := net.Listen("tcp", port)
if err != nil {
log.Fatalf("failed to listen %v\n", err)
}
s := grpc.NewServer()
pb.RegisterEchoServiceServer(s, &EchoServer{})
reflection.Register(s)
if err := s.Serve(lis); err != nil {
log.Fatalf("failed to server %v\n", err)
}
}

客户端实现

客户端需要实现以下功能:
1.创建一个gRPC连接conn
2.使用conn创建一个echo.pb.go定义的客户端
3.使用客户端调用RPC服务

实现代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
package main
import (
"context"
"fmt"
"google.golang.org/grpc"
pb "grpc_demo"
"log"
"time"
)
const address = "localhost:7777"
func main() {
conn, err := grpc.Dial(address, grpc.WithInsecure())
if err != nil {
log.Fatalf("failed to connect %v \n", err)
}
defer conn.Close()
for {
c := pb.NewEchoServiceClient(conn)
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
go func(ctx context.Context) {
r, err := c.Echo(ctx, &pb.EchoRequest{"hello world"})
if err == nil {
fmt.Println(r.GetMessage())
}
}(ctx)
select {
case <-ctx.Done():
cancel()
}
}
}
文章目录
  1. 1. 定义服务
  2. 2. 代码生成
  3. 3. 服务端实现
  4. 4. 客户端实现
|