青训营笔记

50 阅读3分钟

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文件

  1. 先创建对应的.proto文件
  2. 然后写完对应的约束代码后,我们在控制台进行相关操作:
//使用的是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;
}

  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
}