go gRPC 、gateway 简单使用

2,267 阅读2分钟

gRPC 简单使用

Server端代码 github.com/Charlotte32…

Client端代码 github.com/Charlotte32…

1. 安装 protobuf

brew install protobuf

2. 创建一个go 程序

go mod init moudleName

3. 安装grpc

go get -u google.golang.org/grpc

4. 安装 protobuf 插件(protoc-gen-go),用来生成 pb.go pb_grpc.go

go get -u google.golang.org/protobuf/cmd/protoc-gen-go
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest

安装后可以到 go env GOPATH里面的bin目录去查看 是否生成了protoc-gen-go

5. 编写.proto文件

语法文档: developers.google.com/protocol-bu…

touch Hello.proto
vi Hello.proto
syntax = "proto3"; //版本号
package services; // 生成的文件放到哪个包

option go_package = "nsqk.com/rpc";

message SayHelloRequest{
  string name = 1;
}

message HelloReplay{
  string message = 1;
}

6. 生成对应的pb.go 文件

cd ..
# 创建一个services 文件夹,因为proto文件中的package写的是services
mkdir services 
cd pb/
protoc --go_out=../services Hello.proto

7. 编写对应的rpc service

syntax = "proto3"; //版本号
package services; // 生成的文件放到哪个包

option go_package = "nsqk.com/rpc";

message SayHelloRequest{
  string name = 1;
}

message HelloReplay{
  string message = 1;
}

// 下面编写rpc 接口
service HelloWorld{
	rpc HelloRPC (SayHelloRequest) returns (HelloReplay) {}
}

8. 生成.pb_grpc 文件

cd pb

protoc --go_out=../services --go_opt=paths=source_relative \
    --go-grpc_out=../services --go-grpc_opt=paths=source_relative \
    Hello.proto

gRPC-getway 同时提供RESTful 和 grpc接口

证书相关的操作 juejin.cn/post/702550…

1. 安装

  1. 新建一个tool 文件夹,下面创建一个tool.go
  2. 引入需要的包
package tool
import (
	_ "github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway"
	_ "github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2"
	_ "google.golang.org/grpc/cmd/protoc-gen-go-grpc"
	_ "google.golang.org/protobuf/cmd/protoc-gen-go"
)
  1. go mod tidy

  2. 安装插件到go bin目录中‘

    go install \
        github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway \
        github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2 \
        google.golang.org/protobuf/cmd/protoc-gen-go \
        google.golang.org/grpc/cmd/protoc-gen-go-grpc
    
  3. google 这个文件夹拷贝到pb文件夹下方

    cp /Users/jr/go/pkg/mod/github.com/grpc-ecosystem/grpc-gateway@v1.16.0/third_party/googleapis/google ./pb/
    
googleapis

2. 新建一个Prod.proto

syntax = "proto3"; //版本号
package services; // 生成的文件的包名

option go_package = ".;services"; //用来覆盖上面的package名称 ;前面是路径

import "google/api/annotations.proto";

message ProdRequest{
  int32 prod_id = 1; // 商品id
}

message ProdResponse{
  int32 prod_stock = 1; // 库存
}

message QuerySize{
  int32 size = 1; //页尺寸
}

message ProdResponseList{ // 返回商品库存列表
  repeated ProdResponse prodres = 1;
}


service ProdService{
  rpc GetProdStock(QuerySize) returns (ProdResponseList){
    option (google.api.http) = {
      get: "/v1/prod/{size}"
    };
  }

}

3. 重新生成 pb.go _grpc.pb.go,和生成新的gateway需要的pb.gw.go

生成Prod.pb.goProd_grpc.pb.go

cd pb && protoc --go_out=../services --go_opt=paths=source_relative \
    --go-grpc_out=../services --go-grpc_opt=paths=source_relative \
    Hello.proto

生成 Prod.pb.gw.go

protoc -I . \
       --grpc-gateway_out ../services \
       --grpc-gateway_opt logtostderr=true \
       --grpc-gateway_opt paths=source_relative \
           Prod.proto

4. 编写ProdService 文件

package services

import (
	"context"
	"log"
)

type ProdService struct {

}

func (p *ProdService)GetProdStock(ctx context.Context, req *QuerySize) (*ProdResponseList, error){
	log.Println(req.Size)
	return &ProdResponseList{Prodres: []*ProdResponse{&ProdResponse{ProdStock: 2333}}},nil
}
func (p *ProdService)mustEmbedUnimplementedProdServiceServer(){
	log.Fatalln("含有未实现的service")
}

5. 编写http 服务文件

package main

import (
	"context"
	"github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
	"google.golang.org/grpc"
	"log"
	"net/http"
	"nsqk.com/rpc/helper"
	"nsqk.com/rpc/services"
)

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

	// 创建一个gateway mux
	gwmux := runtime.NewServeMux()
	// 创建grpc client dial 配置项
	// 这里把RESTful api 转成 gRPC client 去请求,所以传入客户端的证书
	opt := []grpc.DialOption{grpc.WithTransportCredentials(helper.GetClientCreds())}
	// 注册并且设置http的handler,这里传入的endpoint 是gRPC server的地址
	err := services.RegisterHelloWorldHandlerFromEndpoint(ctx,gwmux,"localhost:2333",opt)
	if err != nil{
		log.Fatalln("注册hello grpc转发失败:",err)
	}
	err = services.RegisterProdServiceHandlerFromEndpoint(ctx,gwmux,"localhost:2333",opt)
	if err != nil{
		log.Fatalln("注册prod grpc转发失败:",err)
	}
	httpServer := &http.Server{
		Addr: ":23333",
		Handler: gwmux,
	}
	err = httpServer.ListenAndServe()
	if err != nil{
		log.Fatalln("http 启动失败:",err)
	}


}

6. 启动

  1. 先启动grpcServer
  2. 再启动httpServer

这里grpc 端口是2333 http端口是23333

结尾

到此,http 和 grpc 都可以进行访问了

image.png

demo代码地址 :

​ client :github.com/Charlotte32…

​ server: github.com/Charlotte32…