Go配置grpc
这是我参与【第五届青训营】伴学笔记创作活动的第13天
1.先配置环境变量:
- 在path下面添加protoc的bin目录
2.在Go下面输入对应的命令行
- 进行对应的配置
go get google.golang.org/grpc
go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest
- 实在不行可以先尝试输入以下命令行
git clone https://github.com/grpc/grpc-go.git $GOPATH/src/google.golang.org/grpc
git clone https://github.com/golang/net.git $GOPATH/src/golang.org/x/net
git clone https://github.com/golang/text.git $GOPATH/src/golang.org/x/text
3.运行对应的proto文件
- 先创建对应的.proto文件
- 然后写完对应的约束代码后,我们在控制台进行相关操作:
//使用的是proto3语法
syntax = "proto3";
//这部分的内容是关于生成后的go在哪个目录哪个包中,代表在当前目录生成,service代表生成的go文件的包名是service
option go_package = ".;service";
//然后我们需要定义一个服务,在这个服务中需要有一个方法,这个方法可以接受客户端的参数,再返回服务端的响应
//其实很容易可以看出,我们定义了一个service,称为SayHello,有个rpc的方法,名为SayHello
//这个方法会发送一个HelloRequest,然后再返回一个HelloResponse
service SayHello{
rpc SayHello(HelloRequest) returns (HelloResponse){}
}
//message关键字,其实你可以理解为Golang中的结构体
//注意变量后面的“赋值”,其实不是赋值,而是在定义这个变量在message中的位置
message HelloRequest{
string requestName = 1;
//int age =2;
//repeated string name = 3; //切片字段
}
message HelloResponse{
string responseMsg = 1;
}
- 先cd到对应的proto的文件夹下面
protoc --go_out=. hello.proto (hello.proto是对应的proto文件名)
protoc --go-grpc_out=. hello.proto
4.服务端代码的编写:
引入:
import pb "awesomeProject/gPRC_demo/hello_server/proto"
- 先引入我们创建的proto文件,然后创建一个对象,我们可以调用里面的函数
定义一个和我们导入的包里面同样的结构体:可以在生成的包中寻找对应的结构体
// hello server
type server struct {
pb.UnimplementedSayHelloServer
}
重写我们需要用到的函数
func (server) SayHello(ctx context.Context,req *pb.HelloRequest) (*pb.HelloResponse, error) {
return &pb.HelloResponse{ResponseMsg: "hello"+req.RequestName},nil
}
创建一个grpc server对象
//创建grpc服务
grpcServer := grpc.NewServer()
将server注册到grpc server的内部中心,这样可以在请求该接口的时候通过内部服务发现,发现该端口并进行逻辑处理
//在grpc服务端中去注册我们自己编写的服务
pb.RegisterSayHelloServer(grpcServer,&server{})
创建listen,监听tcp端口:
//开启端口
listen,_ := net.Listen("tcp",":9090")
gRPC server 开始lis.Accept直到stop
//启动服务
err := grpcServer.Serve(listen)
if err!=nil {
fmt.Printf("failed to serve: %v",err)
return
}
5.客户端代码编写:
连接到server端
//连接到server端,此次禁用安全传输,没有加密验证
conn,err := grpc.Dial("127.0.0.1:9090",grpc.WithTransportCredentials(insecure.NewCredentials()))
if err!=nil {
fmt.Printf("failed to connect: %v",err)
}
//连接用完后得关闭
defer conn.Close()
建立连接:
import pb "awesomeProject/gPRC_demo/hello_server/proto"
//建立连接
client :=pb.NewSayHelloClient(conn)
执行rpc调用
//执行rpc调用
resp,_ :=client.SayHello(context.Background(),&pb.HelloRequest{RequestName: "Graves"})
fmt.Println(resp.GetResponseMsg())
6.Token验证
client端
//创建对应的验证
func (c ClientTokenAuth) GetRequestMetadata(ctx context.Context, uri ...string) (map[string]string,error) {
return map[string]string{
"appId":"Graves",
"appKey":"123123",
},nil
}
//关闭安全验证
func (c ClientTokenAuth)RequireTransportSecurity() bool {
return false
}
在client的main函数下面写
//连接到server端,此处禁用安全传输,没有加密验证
var opts []grpc.DialOption
opts = append(opts,grpc.WithTransportCredentials(insecure.NewCredentials()))
opts = append(opts,grpc.WithPerRPCCredentials(new(ClientTokenAuth)))
conn,err := grpc.Dial("127.0.0.1:9090",opts...)
server端:
创建对应的验证函数
func (server) SayHello(ctx context.Context,req *pb.HelloRequest) (*pb.HelloResponse, error) {
//获取元数据的信息
md ,ok:= metadata.FromIncomingContext(ctx)
if !ok{
return nil,errors.New("未传输Token")
}
var appId string
var appkey string
if v,ok:= md["appid"];ok{
appId = v[0]
}
if v,ok:= md["appkey"];ok{
appId = v[0]
}
if appId !="Graves"|| appkey !="123123"{
return nil,errors.New("不正确")
}
fmt.Println("GOOD!")
return &pb.HelloResponse{ResponseMsg: "hello"+req.RequestName},nil
}