一、安装 Protocol Buffers
1、打开下载地址:https://github.com/protocolbuffers/protobuf/releases
找到对应的版本和对应的安装程序
2、下载完成解压 放到电脑磁盘,然后添加环境变量
检查配置是否成功:win+R cmd 回车输入:protoc
二、安装grpc核心库
1、下载地址:go get google.golang.org/grpc
2、安装go代码生成器:
go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest
三、proto文件编写
// 指定 proto 的版本信息
syntax = "proto3";
// 指定生成的 go 文件存放位置及其包名
option go_package = ".;service";
// 定义枚举消息体
message HelloRequest{
string requestName = 1;
}
message HelloResponse{
string responseMsg = 1;
}
service SayHello{
rpc SayHello(HelloRequest) returns (HelloResponse){}
}
1、切换到proto文件位置,打开编辑器终端输入命令:
protoc --go_out=. .\hello.proto
protoc --go-grpc_out=. .\hello.proto
生成文件:
四、proto文件详解
Sacred
Sacred
关注
1,message介绍
message:protobuf中定义一个消息类型是通过关键字message字段指定的。消息就算需要传输的数据格式的定义。message关键字类似于C++中的class,Java中的Class,go中的struct
例如:
在消息中承载的数据分别对应于每一个字段。
其中每个字段都有一个名字和一种类型。
2,字段规则
required:消息体中必填字段,不设置会导致编解码异常。一般不填就认为是必填字段了。
optional:消息体中可选字段。生成的是对应的指针。
repeated:消息体中可重复字段,重复的值的顺序会被保留,在go中重复的会被定义为切片。
这里我们来定义一下
然后我们生成一下
看下文件
这里就变成了一个切片
3,字段映射
4,默认值
protobuf3删除了protobuf2中用来设置默认值的default关键字,取而代之的是protobuf3为各类型定义的默认值,也就是约定的默认值,如下表:
5,标识号
标识号:在消息体的定义中,每个字段都必须要有一个唯一的标识号,标识号是[0.2^29-1]范围内的一个整数。
以Person为例,name=1,id=2,email=3,phones=4中的1-4就是标识号
6,定义多个消息类型
一个proto文件中可以定义多个消息类型
7,嵌套消息
可以在其他消息类型中定义,使用消息类型,在下面的例子中,Person消息就定义在PersonInfo消息内
如果你想在它的父消息类型的外部重用这个消息类型,你需要以PersonInfo.Person的形式来使用它,如:
当然,你也可以将消息嵌套任意多层,如:
8,定义服务
如果想要将消息类型用在RPC系统中,可以在.PROTO文件中定义一个RPC服务接口,protocolbuffer编译器会根据所选择的不同语言生成服务接口代码及存根。
上述代表表示,定义了一个RPC服务,该方法接收SearchRequest返回SearchResponse
五、服务端编写
创建grpc Server 对象,你可以理解为Server端的抽象对象
将server(其包含需要被调用的服务端接口)注册到grpc Server的内部注册中心
创建监听Listen,监听tcp端口
package main
import (
"context"
"fmt"
"google.golang.org/grpc"
pb "grpc_study/hello-server/proto"
"net"
)
type server struct {
pb.UnimplementedSayHelloServer
}
func (s *server) SayHello(ctx context.Context, req *pb.HelloRequest) (*pb.HelloResponse, error) {
return &pb.HelloResponse{ResponseMsg: "hello" + req.RequestName}, nil
}
func main() {
//开启端口
listen, _ := net.Listen("tcp", ":9090")
//创建grpc服务
grpcServer := grpc.NewServer()
//在grpc服务端中去注册我们自己编写的服务
pb.RegisterSayHelloServer(grpcServer, &server{})
//启动服务
err := grpcServer.Serve(listen)
if err != nil {
fmt.Println("failed to server %v", err)
return
}
}
六、编写客户端
创建与服务端的链接交互
创建server的客户端对象
发生rpc请求,等待同步响应。得到调用后返回结果
输出响应结果
package main
import (
"context"
"fmt"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
pb "grpc_study/hello-server/proto"
"log"
)
func main() {
//链接server端,此处禁用安全传输,没有加密和验证
conn, err := grpc.Dial("127.0.0.1:9090", grpc.WithTransportCredentials(insecure.NewCredentials()))
if err != nil {
log.Fatalf("did not connect %v", err)
}
defer conn.Close()
//建立连接
client := pb.NewSayHelloClient(conn)
//执行grpc调用
resp, _ := client.SayHello(context.Background(), &pb.HelloRequest{RequestName: "xiaoming"})
fmt.Println(resp.GetResponseMsg())
}