gRPC 开发环境

安装gRPC

1
go install google.golang.org/grpc@latest

Protocol Buffers v3

https://github.com/protocolbuffers/protobuf/releases

下载合适的版本,并将 bin 添加到环境变量中

1
2
3
#protoc
export PROTOC_DIR=/Users/rex/Documents/server/protoc-22.2-osx-x86_64
export PATH=$PATH:$PROTOC_DIR/bin
1
2
source ~/.bash_profile
protoc --version

安装插件

安装 protoc-gen-go

1
go install google.golang.org/protobuf/cmd/protoc-gen-go@latest

安装 protoc-gen-go-grpc

1
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest

验证

1
2
protoc-gen-go --version
protoc-gen-go-grpc --version

如果不存在,则查看是否在 gopath 下有可执行程序,然后将 gopath 加入环境变量即可。

Goland 安装 Protoc 插件

服务端代码

定义 pb

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
syntax = "proto3";

option go_package="hello_server/pb"; // 项目中 import 导入生成代码的路径。这里的 hello_server 为 go mod 的名称。

package pd; // protoc 文件模块

service Greeter {
rpc SayHello(HelloRequest) returns (HelloResponse){}
}

message HelloRequest{
string name=1;
}

message HelloResponse{
string reply =1;
}

生成服务端代码

生成 go 语言代码,和 grpc 所需的代码

1
protoc --go_out=. --go_opt=paths=source_relative --go-grpc_out=. --go-grpc_opt=paths=source_relative pb/hello.proto

实现逻辑并启动服务

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

import (
"context"
"google.golang.org/grpc"
"hello_server/pb" // 这个路径就是 proto 文件中的 go_package 字段的值
"net"
)

type server struct {
// 继承 UnimplementedGreeterServer,确保 server 实现了里面所有的方法
pb.UnimplementedGreeterServer
}

// SayHello 实现 SayHello 方法,如果记不清具体方法的实现,可以进入到 UnimplementedGreeterServer 中复制出来
func (s *server) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloResponse, error) {
reply := "hello" + in.GetName()
return &pb.HelloResponse{Reply: reply}, nil
}

func main() {
// 创建 tcp
listen, err := net.Listen("tcp", ":8888")
if err != nil {
return
}
// 创建 grpc 服务
s := grpc.NewServer()
// 注册服务
pb.RegisterGreeterServer(s, &server{})
// 启动服务
err = s.Serve(listen)
if err != nil {
return
}
}

客户端代码

定义 pb

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
syntax = "proto3";

option go_package="hello_client/pb"; // 项目中 import 导入生成代码的路径。这里的 hello_client 为 go mod 的名称

package pd; // protoc 文件模块

service Greeter {
rpc SayHello(HelloRequest) returns (HelloResponse){}
}

message HelloRequest{
string name=1;
}

message HelloResponse{
string reply =1;
}

生成客户端代码

1
2
3
protoc --go_out=. --go_opt=paths=source_relative \
--go-grpc_out=. --go-grpc_opt=paths=source_relative \
pb/hello.proto

连接 server 端, 并调用 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"
"flag"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
"hello_client/pb"
"log"
"time"
)

var name = flag.String("name", "rex", "please input your name")

func main() {
flag.Parse()

// 连接 server 端
conn, err := grpc.Dial("127.0.0.1:8888", grpc.WithTransportCredentials(insecure.NewCredentials()))
if err != nil {
return
}
defer conn.Close()
// 创建客户端
c := pb.NewGreeterClient(conn)
// 调用 RPC 方法
ctx, cancel := context.WithTimeout(context.Background(), time.Second*1)
defer cancel()
response, err := c.SayHello(ctx, &pb.HelloRequest{Name: *name})
if err != nil {
return
}
log.Printf("Greeting: %s", response.GetReply())
}

本文代码:https://github.com/rexyan/Go-Microservice/tree/main/hello_client,https://github.com/rexyan/Go-Microservice/tree/main/hello_server