go语言搭建项目--grpc 以及grpc-getway使用

首先需要下载proto包:

go get -u github.com/golang/protobuf/proto

一、安装

go get -u github.com/grpc-ecosystem/grpc-gateway/protoc-gen-grpc-gateway
go get -u github.com/grpc-ecosystem/grpc-gateway/protoc-gen-swagger
go get -u github.com/golang/protobuf/protoc-gen-go

分别安装gateway、swagger、还有就是protoc中go语言的编译器。
二、编写.proto文件

syntax = "proto3"; // proto版本
package demo; // 指定包名,默认go中包名也是这个

option go_package = ".;demo"; // 指定go包名

// 定义Demo服务
service Demo {
     
  // 定义Confession方法
  rpc TestSay(SayRequest) returns (SayResponse) {
     }
}

// 请求
message SayRequest {
     
  string name = 1;
}

// 响应
message SayResponse {
     
  string result = 1;
}

这个是最简单的也就仅仅使用的grpc基本的功能,如果要用grpc gateway的话,在这个基础上面改一下

syntax = "proto3"; // proto版本
package demo; // 指定包名,默认go中包名也是这个
import "google/api/annotations.proto";
option go_package = ".;demo"; // 指定go包名

// 定义Demo服务
service Demo {
     
  // 定义Get方法
  //其实重点就是定义这个玩意,可以定义get,post,put,delete等method,主要是用于外部调用
  rpc GetTestSay (SayRequest) returns (SayResponse){
     
		option (google.api.http) ={
     
			get: "/v1/demo/{name}"
		};
	}
  //定义Post方法
  rpc PostTestSay (SayRequest) returns (SayResponse){
     
		option (google.api.http) ={
     
			post: "/v1/demo"
			body: "*"
		};
	}
}

// 请求
message SayRequest {
     
  string name = 1;
}

// 响应
message SayResponse {
     
  string result = 1;
}

三、生成.pb文件
首先生成demo.pb.go文件。

protoc --go_out=plugins=grpc:. demo.proto

然后给我报出来这么一个玩意

2020/12/21 16:18:53 WARNING: Deprecated use of 'go_package' option without a full import path in "google/protobuf/descriptor.proto", please specify:
        option go_package = "google/protobuf;types";
A future release of protoc-gen-go will require the import path be specified.
See https://developers.google.com/protocol-buffers/docs/reference/go-generated#package for more information.

大体的意思就是说之后要使用的时候需要指定路径,直接忽略,后续升级版本的时候再说。原谅我的不细致。。。
然后在你的demo.proto所在的目录下就会生成一个demo.pb.go文件。
之后咱们开始生成demo.pb.gw.go文件

protoc --grpc-gateway_out=logtostderr=true:. demo.proto

也是在demo.proto这个文件所在的目录下执行上面的这个命令行
然后在这个文件夹下面会有一个demo.pb.gw.go文件出现。
四、编写代码
上面已经把准备的工作做好了,那之后我们就开始写服务端和客户端的代码
服务端分为两个部分:
grpc服务端代码:

type server struct {
     }

func (s *server) GetTestSay(ctx context.Context,res *demo.SayRequest) (resp *demo.SayResponse,err error) {
     
	return &demo.SayResponse{
     Result: "hello " + res.Name}, nil
}

func (s *server) PostTestSay(ctx context.Context,res *demo.SayRequest) (*demo.SayResponse, error) {
     
	return &demo.SayResponse{
     Result: "hello " + res.Name}, nil
}

func main() {
     
	// 监听本地端口
	lis, err := net.Listen("tcp", "127.0.0.1:9100")
	if err != nil {
     
		fmt.Printf("监听端口失败: %s", err)
		return
	}
	// 创建gRPC服务器
	s := grpc.NewServer()
	// 注册服务
	demo.RegisterDemoServer(s, &server{
     })
	reflection.Register(s)
	err = s.Serve(lis)
	if err != nil {
     
		fmt.Printf("开启服务失败: %s", err)
		return
	}
}

http服务端代码:

func main() {
     
	//1.定义一个context
	ctx:=context.Background()
	ctx,cancel:=context.WithCancel(ctx)
	defer cancel()

	//grpc服务地址
	endpoint := "127.0.0.1:9100"
	mux := runtime.NewServeMux()
	opts := []grpc.DialOption{
     grpc.WithInsecure()}

	//Http转grpc
	err:= demo.RegisterDemoHandlerFromEndpoint(ctx,mux,endpoint,opts)
	if err != nil {
     
		grpclog.Fatalf("Register handler err:%vn", err)
	}
	grpclog.Println("HTTP Listen on 9000")
	http.ListenAndServe("127.0.0.1:9000", mux)
}

由上面代码可以看出来,其实http请求也是将http的方式转化为grpc的方式,只不过grpc已经为我们提供了更加方便的http的调用方式。

客户端代码:

func main(){
     
	// 连接服务器
	conn, err := grpc.Dial("127.0.0.1:9100", grpc.WithInsecure())
	if err != nil {
     
		fmt.Printf("连接服务端失败: %s", err)
		return
	}
	defer conn.Close()

	// 新建一个客户端
	c := demo.NewDemoClient(conn)

	// 调用服务端函数
	r, err := c.GetTestSay(context.Background(), &demo.SayRequest{
     Name: "Grpc"})
	if err != nil {
     
		fmt.Printf("调用服务端代码失败: %s", err)
		return
	}
	fmt.Printf("调用成功: %s", r.Result)
}

其实这个客户端直接走的是grpc,而http调用的方式就需要我们使用postman来调用了。http调用的监听端口为9000,host是:127.0.0.1,然后我们回到demo.proto这个文件,在最开始定义的时候我们在方法里面添加了不同请求方式对应的url,直接拼接就好了。
具体的调用url为:127.0.0.1:9000/v1/demo/{Http}
项目的代码结构为:

go语言搭建项目--grpc 以及grpc-getway使用_第1张图片
补充一点:
其实可以将http的方式和grpc的方式放在一起:

var(
	endpoint = "127.0.0.1:9000"
)
type server struct {
     }

func (s *server) GetTestSay(ctx context.Context,res *demo.SayRequest) (resp *demo.SayResponse,err error) {
     
	return &demo.SayResponse{
     Result: "hello " + res.Name}, nil
}

func (s *server) PostTestSay(ctx context.Context,res *demo.SayRequest) (*demo.SayResponse, error) {
     
	return &demo.SayResponse{
     Result: "hello " + res.Name}, nil
}

func run() error {
     
	ctx := context.Background()
	ctx, cancel := context.WithCancel(ctx)
	defer cancel()

	mux := runtime.NewServeMux()
	opts := []grpc.DialOption{
     grpc.WithInsecure()}
	err := demo.RegisterDemoHandlerFromEndpoint(ctx, mux, endpoint, opts)
	if err != nil {
     
		return err
	}

	return http.ListenAndServe("127.0.0.1:9100", mux)
}


func main() {
     
	lis, err := net.Listen("tcp", endpoint)
	if err != nil {
     
		log.Fatal("failed to listen: %v", err)
	}
	s := grpc.NewServer()
	demo.RegisterDemoServer(s, &server{
     })
	go s.Serve(lis)

	defer glog.Flush()

	if err := run(); err != nil {
     
		glog.Fatal(err)
	}

}

其中grpc的端口是9000,http端口为9100。这样无论是grpc还是http都会走这块的。
既然说到grpc了,那咱们在下一节就再说一下路由以及swagger

你可能感兴趣的:(go,go,grpc)