protoc 插件 - protoc-gen-grpc-gateway-gosdk
基本介紹
protoc-gen-grpc-gateway-gosdk 是一個 protoc 插件, 能根據 proto 文件一鍵生成 go http sdk 客戶端代碼,通過藉助 grpc-gateway 插件將 grpc 接口轉化爲 http 的方式, 進而可以通過本插件生成 http sdk 代碼。
特性
-
一鍵自動生成 go 客戶端代碼, 無需人工維護
-
通過設置統一網關, 支持將多個微服務的客戶端整合
-
根據 service 或者根據路由進行資源分類, 直觀調用
-
能對資源接口進行擴展, 如支持 websocket 接口以及支持擴展 http 原生框架的接口
-
自帶 http rest frame 封裝, 並支持 Direct 方式調用接口
-
能自動生成接口 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 結構剖析
-
clientset.go: 客戶端集合
-
fake/fake_clientset.go: fake 客戶端集合
-
pb: 使用 protoc-gen-go 插件生成的 pb 文件
-
rest: rest frame 封裝
-
typed: 所有接口封裝
-
typed/userv/fake: 即 user 服務 v1 接口 fake 實現
-
typed/userv1/user.go: userv1 服務 user 資源的實現
-
typed/userv1/user_expansion.go: userv1 服務 user 資源的接口擴展定義
-
typed/userv1/userv1_client.go: userv1 服務 user client 定義
-
typed/userv1/fake/fake_user.go: userv1 服務 user 資源的 fake 實現
-
typed/userv1/fake_user_expansion.go: userv1 服務 user 資源的 fake 接口擴展定義
-
typed/userv1/fake_userv1_client.go: userv1 服務 fake user client 定義
-
typed/direct_client.go: direct 方式調用的 client
-
typed/fake/fake_direct_client.go: direct 方式調用的 fake client
-
typed/userv1: 即 user 服務 v1 接口實現
高級使用 (微服務版)
一般而言, 都是多服務形式的, 如 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)
}
參考鏈接
-
五分鐘給你的 gRPC 服務加上 HTTP 接口:https://mp.weixin.qq.com/s/0v0zM9FkYSVw1iyRiQRNYw
-
protoc-gen-grpc-gateway-gosdk:
https://protoc-gen-grpc-gateway-gosdk.jaronnie.com/
-
grpc-restful:
https://github.com/kevwan/grpc-restful
- jaronnie/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