grpc案例

177 阅读2分钟

安装

go get -u google.golang.org/grpc
go get -u github.com/golang/protobuf/protoc-gen-go

工具了解

protobuf

protobuf是goole的一种数据交换的格式,类似json、xml。

protoc

protoc是protobuf文件的编译器,可以借助这个工具把proto文件转译成各种编码对应的源码,包含数据类型定义、调用接口。

通过命令 protoc --version来检查是否安装成功

protoc-gen-go

protoc-gen-go是protobuf编译插件系列中的go版本,相比还有生成其他语言的插件。

案例

项目目录

image.png

第一步:编写proto文件

syntax = "proto3";
package proto;

service SearchService{
  rpc Search(SearchRequest)returns(SearchResponse){}
}

message SearchRequest{
  string request = 1;
}
message SearchResponse{
  string response = 1;
}

第二步:生成.pb.go文件

根据以下命令生成pb.go文件,路径根据自己的proto位置进行修改。

 protoc --go_out=plugins=grpc:. ./proto/*.proto

image.png

  • plugins=plugin1+plugin2:指定要加载的子插件列表 我们定义的 proto 文件是涉及了 RPC 服务的,而默认是不会生成 RPC 代码的,因此需要给出 plugins 参数传递给 protoc-gen-go,告诉它,请支持 RPC(这里指定了 gRPC)
  • --go_out=.:设置 Go 代码输出的目录

该指令会加载 protoc-gen-go 插件达到生成 Go 代码的目的,生成的文件以 .pb.go 为文件后缀

  • : (冒号) 冒号充当分隔符的作用,后跟所需要的参数集。如果这处不涉及 RPC,命令可简化为:
protoc --go_out=. ./hello/*.proto

这种命令与上边的命令生成的.pb.go文件是有区别的。

.pb.go文件内容 image.png

  • 字段名称从小写下划线转换为大写驼峰模式(字段导出)
  • 生成一组 Getters 方法,能便于处理一些空指针取值的情况
  • ProtoMessage 方法实现 proto.Message 的接口
  • 生成 Rest 方法,便于将 Protobuf 结构体恢复为零值
  • Repeated 转换为切片

第三步:编写server文件

package main

import (
	"context"
	"google.golang.org/grpc"
	"log"
	"net"
	pb "wsn-grpc/proto"
)

type SearchService struct {
}

func (s *SearchService) Search(ctx context.Context, r *pb.SearchRequest) (*pb.SearchResponse, error) {
	return &pb.SearchResponse{Response: r.GetRequest() + "server"}, nil
}

func main() {
	port := ":9091"
	server := grpc.NewServer()
	pb.RegisterSearchServiceServer(server, &SearchService{})
	lis, err := net.Listen("tcp", port)
	if err != nil {
		log.Fatal("net.listen err:%v", err)
	}
	server.Serve(lis)
}
  • 创建 gRPC Server 对象,你可以理解为它是 Server 端的抽象对象
  • 将 SearchService(其包含需要被调用的服务端接口)注册到 gRPC Server 的内部注册中心。这样可以在接受到请求时,通过内部的服务发现,发现该服务端接口并转接进行逻辑处理
  • 创建 Listen,监听 TCP 端口
  • gRPC Server 开始 lis.Accept,直到 Stop 或 GracefulStop

第四步:编写client文件

package main

import (
	"context"
	"google.golang.org/grpc"
	"log"
	pb "wsn-grpc/proto"
)

func main() {
	port := ":9091"
	conn, err := grpc.Dial("localhost"+port, grpc.WithInsecure())
	if err != nil {
		log.Fatalf("grpc.Dial err:%v", err)
	}
	defer conn.Close()
	client := pb.NewSearchServiceClient(conn)
	resp, err := client.Search(context.Background(), &pb.SearchRequest{
		Request: "test grpc",
	})
	if err != nil {
		log.Fatalf("client search err:%v", err)
	}
	log.Printf("resp: %s", resp.GetResponse())

}

  • 创建与给定目标(服务端)的连接交互
  • 创建 SearchService 的客户端对象
  • 发送 RPC 请求,等待同步响应,得到回调后返回响应结果
  • 输出响应结果