Featured image of post 练习 gRPC,Protobuf

练习 gRPC,Protobuf

高效率的序列化方案

鉴于最近接触到很多使用了 grpc 的服务,如果还不了解的话,就根本没办法继续学习下去了,所以(又)花了小半天时间再次熟悉了一下。

protobuffer 安装

安装 proto-compiler

推荐使用 chocolatey,可以一键安装 choco install protoc

安装 ptotoc-gen-xx

可以从官方 github 的 release 下载, 如 v3.17.3,然后将 protobuf-3.17.3/src/google 文件夹下的内容保存到 C:ProgramData/chocolatey/lib/protoc/tools/include/google 中即可。

项目结构

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
.
├── go.mod
├── go.sum
├── mail
│   ├── client_test.go
│   ├── makefile
│   └── server.go
└── proto
    └── mail
        ├── mail.pb.go
        ├── mail.proto
        └── mail_grpc.pb.go

mail.proto

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
syntax = "proto3"; // 指定protobuf版本

package mall; // 指定默认包名

// 指定生成go文件的包名
option go_package = "github.com/azusachino/grpc_demo/proto";

service MailService {
    rpc SendMail(MailRequest) returns (MailResponse) {
    }
}

// 请求消息
message MailRequest {
    string mail = 1;
    string text = 2;
}
// 响应消息
message MailResponse {
    bool ok = 1;
}

makefile

  • mail.pb.go: 主要包括 message 的相关定义
  • mail_grpc.pb.go: 主要包括 service 的相关定义

通过指定相对路径,使用 make build 命令即可生成这两个文件。

1
2
3
4
# parse proto files
build:
    protoc --proto_path=../proto --go_out=../proto --go_opt=paths=source_relative \
 --go-grpc_out=../proto --go-grpc_opt=paths=source_relative ../proto/mail/mail.proto

server.go

 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
35
36
37
38
39
package main

import (
    "context"
    "fmt"
    pb "github.com/azusachino/grpc_demo/proto/mail"
    "google.golang.org/grpc"
    "google.golang.org/grpc/reflection"
    "net"
)

type service struct {
    // fallback solution, service must implement
    pb.UnimplementedMailServiceServer
}

func (s *service) SendMail(ctx context.Context, req *pb.MailRequest) (res *pb.MailResponse, err error) {
    fmt.Printf("mail: %s, msg detail: %s\n", req.Mail, req.Text)
    return &pb.MailResponse{
        Ok: true,
    }, nil
}

func main() {
    // listen tcp 8972
    lis, err := net.Listen("tcp", ":8972")
    if err != nil {
        fmt.Printf("failed to listen: %v", err)
        return
    }
    // grpc server
    s := grpc.NewServer()
    pb.RegisterMailServiceServer(s, &service{})
    reflection.Register(s)

    if err := s.Serve(lis); err != nil {
        fmt.Println(err)
    }
}

client_test.go

 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
package main

import (
    "context"
    pb "github.com/azusachino/grpc_demo/proto/mail"
    "google.golang.org/grpc"
    "log"
    "testing"
    "time"
)

func TestService_SendMail(t *testing.T) {

    ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
    defer cancel()
    // dial grpc server
    conn, err := grpc.DialContext(ctx, "127.0.0.1:8972", grpc.WithInsecure(),
        grpc.WithBlock())
    if err != nil {
        log.Fatalf("failed to dial: %v", err)
    }

    c := pb.NewMailServiceClient(conn)

    res, err := c.SendMail(context.TODO(), &pb.MailRequest{
        Mail: "[email protected]",
        Text: "Hello",
    })
    log.Println(res)
}

暂时性总结

这是个十分简单的 demo,后续学习一下和 etcd 之间的交互。

参考链接

The older I get, the more I realize that most of life is a matter of what we pay attention to, of what we attend to [with focus].
Built with Hugo
Theme Stack designed by Jimmy