红魔咖啡馆

头发越掉越多,头发越掉越少

0%

【gRPC】Gateway

作用

gRPC-gateway是protoc编译器的一个插件,需要提供传统HTTP/JSON API来满足向后兼容或不支持gRPC的客户端时,gRPC-gateway 可以通过protobuf文件自动生成符合REFTful API的反向代理服务器

安装

1
2
3
4
5
6
7
8
9
# 安装grpc-gateway插件
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

# 添加依赖
go get github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway

用法

  • buf mod init:生成buf.yaml文件
  • buf lint:检测protobuf格式

生成gRPC服务

写好protobuf文件后,创建一个buf.gen.yaml文件,按如下模板:

1
2
3
4
5
6
7
8
9
10
version: v2
plugins:
  - local: protoc-gen-go
    out: gen/go
    opt:
      - paths=source_relative
  - local: protoc-gen-go-grpc
    out: gen/go
    opt:
      - paths=source_relative

其中out是生成文件的地址,按需修改

执行buf generate就可以生成文件了

生成反向代理

buf.gen.yaml模板如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
version: v2
plugins:
  - local: protoc-gen-go
    out: gen/go
    opt:
      - paths=source_relative
  - local: protoc-gen-go-grpc
    out: gen/go
    opt:
      - paths=source_relative
  - local: protoc-gen-grpc-gateway
    out: gen/go
    opt:
      - paths=source_relative
      - generate_unbound_methods=true

若需要修改URL,则需要引入google.api.http,protobuf文件添加import "google/api/annotations.proto"

定义service如下:

1
2
3
4
5
6
7
8
service YourService {
 rpc Echo(StringMessage) returns (StringMessage) {
   option (google.api.http) = {
     post: "/v1/example/echo"
     body: "*"
   };
 }
}

buf.yaml文件下也需要加入对应的依赖:

1
2
3
4
version: v2
name: buf.build/yourorg/myprotos
deps:
  - buf.build/googleapis/googleapis

添加依赖后运行buf dep update

编写entrypoint

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
package main

import (
  "context"
  "flag"
  "net/http"

  "github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
  "google.golang.org/grpc"
  "google.golang.org/grpc/credentials/insecure"
  "google.golang.org/grpc/grpclog"

  gw "github.com/yourorg/yourrepo/proto/gen/go/your/service/v1/your_service"  // 你的网关代码包
)

var (
  grpcServerEndpoint = flag.String("grpc-server-endpoint",  "localhost:9090", "gRPC server endpoint")
)

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

  // 创建HTTP mux,用来注册路由
  mux := runtime.NewServeMux()
  // 设置连接gRPC的选项
  opts := []grpc.DialOption{grpc.WithTransportCredentials(insecure.NewCredentials())}
  // 注册所有需要转发的服务处理函数
  err := gw.RegisterYourServiceHandlerFromEndpoint(ctx, mux,  *grpcServerEndpoint, opts)
  if err != nil {
    return err
  }

  // 启动服务并监听代理
  return http.ListenAndServe(":8081", mux)
}

func main() {
  flag.Parse()

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