protoc 插件 - protoc-gen-grpc-gateway-gosdk

基本介紹

protoc-gen-grpc-gateway-gosdk 是一個 protoc 插件, 能根據 proto 文件一鍵生成 go http sdk 客戶端代碼,通過藉助 grpc-gateway 插件將 grpc 接口轉化爲 http 的方式, 進而可以通過本插件生成 http sdk 代碼。

特性

  1. 一鍵自動生成 go 客戶端代碼, 無需人工維護

  2. 通過設置統一網關, 支持將多個微服務的客戶端整合

  3. 根據 service 或者根據路由進行資源分類, 直觀調用

  4. 能對資源接口進行擴展, 如支持 websocket 接口以及支持擴展 http 原生框架的接口

  5. 自帶 http rest frame 封裝, 並支持 Direct 方式調用接口

  6. 能自動生成接口 fake 調用, 讓單元測試更加簡單

安裝

go install github.com/golang/protobuf/protoc-gen-go@v1.3.2
go install github.com/jaronnie/protoc-gen-grpc-gateway-gosdk@v1.8.0

快速使用

編寫 proto

syntax = "proto3";
option go_package = "./userpb";
package user;

import "google/api/annotations.proto";

message AddUserReq {
      string name = 1;
      int32 age = 2;
}

message AddUserResp {
      int32 id = 1;
}

service user {
      rpc Add(AddUserReq) returns (AddUserResp) {
            option (google.api.http) = {
                  post: "/api/v1.0/user/add"
                  body: "*"
            };
      };
}

目錄結構如下:

$ tree proto              
proto
├── google
│   └── api
│       ├── annotations.proto
│       └── http.proto
└── user.proto

2 directories, 3 files

生成 httpsdk

生成的 sdk 代碼在服務端:

mkdir -p pkgsdk/pb
protoc -I./proto --go_out=./pkgsdk/pb --grpc-gateway-gosdk_out=logtostderr=true,v=1,scopeVersion=userv1,sdkDir=pkgsdk:pkgsdk proto/user.proto

生成的 httpsdk 目錄結構如下:

$ tree pkgsdk 
pkgsdk
├── clientset.go
├── fake
│   └── fake_clientset.go
├── pb
│   └── userpb
│       └── user.pb.go
├── rest
│   ├── client.go
│   ├── option.go
│   └── request.go
└── typed
    ├── direct_client.go
    ├── fake
    │   └── fake_direct_client.go
    └── userv1
        ├── fake
        │   ├── fake_user.go
        │   ├── fake_user_expansion.go
        │   └── fake_userv1_client.go
        ├── user.go
        ├── user_expansion.go
        └── userv1_client.go

8 directories, 14 files

生成的 httpsdk 獨立 module:

mkdir -p modsdk/pb
protoc -I./proto --go_out=./modsdk/pb --grpc-gateway-gosdk_out=logtostderr=true,v=1,scopeVersion=userv1,goModule=github.com/jaronnie/autosdk,goVersion=1.18:modsdk proto/user.proto
cd modsdk
go mod tidy

生成的 httpsdk 目錄結構如下:

$ tree modsdk
modsdk
├── clientset.go
├── fake
│   └── fake_clientset.go
├── go.mod
├── go.sum
├── pb
│   └── userpb
│       └── user.pb.go
├── rest
│   ├── client.go
│   ├── option.go
│   └── request.go
└── typed
    ├── direct_client.go
    ├── fake
    │   └── fake_direct_client.go
    └── userv1
        ├── fake
        │   ├── fake_user.go
        │   ├── fake_user_expansion.go
        │   └── fake_userv1_client.go
        ├── user.go
        ├── user_expansion.go
        └── userv1_client.go

8 directories, 16 files

http sdk 結構剖析

高級使用 (微服務版)

一般而言, 都是多服務形式的, 如 A 服務, B 服務。前端通過統一的網關打入到 A, B 服務當中。通過該插件可生成 A, B 服務的統一 httpsdk。

編寫 A 服務 proto

syntax = "proto3";
option go_package = "./apb";
package a;

import "google/api/annotations.proto";

message AddUserReq {
      string name = 1;
      int32 age = 2;
}

message AddUserResp {
      int32 id = 1;
}

service a {
      rpc Add(AddUserReq) returns (AddUserResp) {
            option (google.api.http) = {
                  post: "/api/v1.0/user/add"
                  body: "*"
            };
      };
}

編寫 B 服務 proto

syntax = "proto3";
option go_package = "./bpb";
package b;

import "google/api/annotations.proto";

message AddUserReq {
      string name = 1;
      int32 age = 2;
}

message AddUserResp {
      int32 id = 1;
}

service b {
      rpc Add(AddUserReq) returns (AddUserResp) {
            option (google.api.http) = {
                  post: "/api/v1.0/user/add"
                  body: "*"
            };
      };
}

編寫 env_file.yaml

scopeVersions: [av1, bv1]
goModule: github.com/jaronnie/autosdk
goVersion: 1.18

生成 httpsdk

通過設置 gatewayPrefix 變量統一網關

mkdir -p mutilmodsdk/pb
protoc -I./proto --go_out=./mutilmodsdk/pb --grpc-gateway-gosdk_out=logtostderr=true,v=1,scopeVersion=av1,gatewayPrefix=/gateway/a,env_file=./etc/modmutilsdk.yaml:mutilmodsdk proto/a.proto
protoc -I./proto --go_out=./mutilmodsdk/pb --grpc-gateway-gosdk_out=logtostderr=true,v=1,scopeVersion=bv1,gatewayPrefix=/gateway/b,env_file=./etc/modmutilsdk.yaml:mutilmodsdk proto/b.proto
cd mutilmodsdk
go mod tidy

生成的目錄結構如下:

$ tree mutilmodsdk 
mutilmodsdk
├── clientset.go
├── fake
│   └── fake_clientset.go
├── go.mod
├── go.sum
├── pb
│   ├── apb
│   │   └── a.pb.go
│   └── bpb
│       └── b.pb.go
├── rest
│   ├── client.go
│   ├── option.go
│   └── request.go
└── typed
    ├── av1
    │   ├── av1_client.go
    │   ├── fake
    │   │   ├── fake_av1_client.go
    │   │   ├── fake_user.go
    │   │   └── fake_user_expansion.go
    │   ├── user.go
    │   └── user_expansion.go
    ├── bv1
    │   ├── bv1_client.go
    │   ├── fake
    │   │   ├── fake_bv1_client.go
    │   │   ├── fake_user.go
    │   │   └── fake_user_expansion.go
    │   ├── user.go
    │   └── user_expansion.go
    ├── direct_client.go
    └── fake
        └── fake_direct_client.go

11 directories, 23 files

實戰篇

採用 go-zero 微服務框架, 編寫 user 服務, 並加上 http 接口。

完整代碼示例: https://github.com/jaronnie/protoc-gen-grpc-gateway-gosdk/tree/main/examples/grpc-restful

git clone github.com/jaronnie/protoc-gen-grpc-gateway-gosdk
cd protoc-gen-grpc-gateway-gosdk/examples/grpc-restful
go run user.go

# 使用插件生成 pkgsdk
mkdir -p pkgsdk/pb
protoc -I./proto --go_out=./pkgsdk/pb --grpc-gateway-gosdk_out=logtostderr=true,v=1,scopeVersion=userv1,sdkDir=pkgsdk:pkgsdk proto/user.proto

使用示例

package main

import (
 "context"
 "fmt"
 "github.com/jaronnie/protoc-gen-grpc-gateway-gosdk/grpc-restful/pkgsdk"
 "github.com/jaronnie/protoc-gen-grpc-gateway-gosdk/grpc-restful/pkgsdk/pb/userpb"
 "github.com/jaronnie/protoc-gen-grpc-gateway-gosdk/grpc-restful/pkgsdk/rest"
 "net/http"
)

func main() {
 cs, err := pkgsdk.NewClientWithOptions(
  rest.WithProtocol("http"),
  rest.WithAddr("127.0.0.1"),
  rest.WithPort("8081"),
  rest.WithHeaders(http.Header{"Content-Type"[]string{"application/json"}}),
 )

 if err != nil {
  panic(err)
 }

 data, err := cs.Userv1().User().Add(context.Background()&userpb.AddUserReq{
  Name: "jaronnie",
  Age:  22,
 })
 if err != nil {
  panic(err)
 }
 fmt.Println(data)
}

參考鏈接

https://github.com/kevwan/grpc-restful

https://github.com/jaronnie/protoc-gen-grpc-gateway-gosdk/tree/main/examples/grpc-restful

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/OzRF_l_LNJmJ95dLl3oiCw