目录
1、开发环境准备
要使用grpc,首先需要安装Protocol Buffers 工具,不同的平台对应不同的包,我们都可以从这里下载到:
https://github.com/protocolbuffers/protobuf/releases/tag/v29.3
如果你是linux环境,可以下载:protoc-29.3-linux-x86_64.zip。
如果是mac环境,现在苹果基本都是自研的cpu,下载:protoc-29.3-osx-aarch_64.zip.
win环境下载:protoc-29.3-win64.zip。
这个工具可以将proto文件转换为对应语言的代码,是使用grpc必不可少的一环。
下载完成后,要将对应的可执行文件放到PATH目录下,比如我的protoc目录如下:
需要将对应的目录加到PATH目录:
export PATH=/Users/liupeng/Documents/binary/bin:$PATH
查看protoc版本:
安装golang插件:
# 用于将 *.proto 文件生成一个后缀为 *.pb.go 的文件。生成文件中包含所有 .proto 文件中定义的类型及其序列化方法
go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
# 用于生成 gRPC 服务端需要实现的接口
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest
将GOPATH/bin目录添加到PATH中:
export PATH=/Users/liupeng/go/bin:$PATH
这一步很重要,否则无法编译proto生成golang代码。
2、编写proto,定义调用函数
grpc函数支持4种模式,分别为普通模式、客户端流式、服务端流式、双端流式,四种模式的定义分别如下介绍。
1、普通模式
客户端发送请求到服务端,服务端实时响应,返回数据给客户端,如普通的函数调用一般。
rpc SayHello (HelloRequest) returns (HelloReply) {}
2、客户端流式
客户端向服务端发送流式请求,可以多次写入数据,服务端循环获取客户端数据,直到客户端关闭该流。服务端接收完所有数据并处理后,向客户端返回一个普通响应。
rpc ClientStreamingSayHello(stream HelloRequest) returns (HelloReply) {}
3、服务端流式
客户端向服务端发送请求,服务端发送流到客户端,客户端从流中读取数据,直到服务端关闭该流。
rpc ServerStreamingSayHello(HelloRequest) returns (stream HelloReply) {}
4、双端流式
这就比较容易理解了,上报、下发数据都以流式方式进行。
rpc BidirectionalStreamingSayHello(stream HelloRequest) returns (stream HelloReply) {}
完整的proto代码放到文章最后,需要的同学可以自取。
3、编译proto,生成golang源码
server端,编译proto,生成golang源码:
protoc --go_out=. --go-grpc_out=. hello.proto
client端一样的道理,编译hello.proto:
4、grpc 服务端代码实现
我们一共注册了四个函数,在服务端需要分别实现其业务逻辑,我们只实现将收到的信息返回回去,simple rpc函数实现如下:
func (s *Server) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) {
fmt.Println("Received:", in.GetName())
return &pb.HelloReply{Message: "Hello " + in.GetName()}, nil
}
双端流式实现如下:
func (s *Server) BidirectionalStreamingSayHello(stream pb.Greeter_BidirectionalStreamingSayHelloServer) error {
for {
in, err := stream.Recv()
if err == io.EOF {
return nil
}
if err != nil {
return err
}
fmt.Println("bidirectional request received:", in)
if err := stream.Send(&pb.HelloReply{Message: "bidirectional done"}); err != nil {
return err
}
}
}
5、grpc 客户端代码实现
客户端代码实现,simple rpc与双端流失放到了一起:
func main() {
flag.Parse()
conn, err := grpc.NewClient(*addr, grpc.WithTransportCredentials(insecure.NewCredentials()))
if err != nil {
fmt.Println("did not connect: ", err)
}
defer conn.Close()
c := pb.NewGreeterClient(conn)
// Contact the server and print out its response.
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
defer cancel()
// --------普通请求方式------- //
r, err := c.SayHello(ctx, &pb.HelloRequest{Name: *name})
if err != nil {
fmt.Println("could not greet: ", err)
}
fmt.Println("Greeting: ", r.GetMessage())
// --------双向流式请求方式------- //
bstream, err := c.BidirectionalStreamingSayHello(ctx)
if err != nil {
fmt.Println("could not open stream: ", err)
return
}
go func() {
// 异步发送信息
for i := 0; i < 10; i++ {
bstream.Send(&pb.HelloRequest{Name: "bidirection stream client"})
}
bstream.CloseSend()
}()
fmt.Printf("response:\n")
for {
r, err := bstream.Recv()
if err != nil {
break
}
fmt.Printf(" - %s\n", r.Message)
}
}
6、运行代码,查看运行结果
可以看到普通模式,以及双端流式都正常运行了。
grpc还有异步使用模式,nvidia的triton server就是使用的异步模式,后面再单独介绍。
所有代码都已经上传到github了,需要的同学可自由获取:
https://github.com/liupengh3c/career/tree/main/grpc
都到这里了,小伙伴们点个关注呗~~~~~~~~~。