目前本喵最看好的rpc框架是 grpc,同時借助 grpc-gateway 和 net.Pipe 可以幾乎無副作用的將 grpc unary 接口開放爲 http1.1 兼容接口。並且你不需要額外的編碼工作,你只需要寫好 grpc 代碼即可。並且 grpc-gateway 提供了工具,連 http 接口文檔都自動由 proto 檔案幫你生成,編寫服務器程式一下子變得異常簡單。
雖然如此但每次創建新項目時依然要寫一堆類似的初始化代碼,爲此本喵的解決方案是創建一個項目模板,由工具依據此模板爲新項目創建這些類似的初始化代碼。
github.com/powerpuffpenguin/jsgenerate_grpc-gateway 便是本喵實現的項目模板,本文主要在於介紹 jsgenerate_grpc-gateway 的特性和使用方式
特性
jsgenerate_grpc-gateway 創建了項目初始化代碼,這些預創建的代碼爲項目提供了一些有趣的特性
- 項目融合了 grpc grpc-gateway gin,你可以只寫 grpc 代碼,grpc-gateway 會自動爲 unary 接口提供一個http1.1 的兼容接口無需額外編碼,同時 grpc 和 gin 可以協同工作你還可以使用 gin 爲 http 定義額外的接口。
- 因爲 grpc grpc-gateway gin 其實都是 http 協議,故這三者共用同一個端口,無論是 grpc 還是 grpc-gateway 以及 gin 提供的服務,外部都只需要訪問服務提供的唯一一個對外開放的接口即可,這簡化的服務配置以及多客戶端的配置。
- 借助 golang 良好的接口特性和 net.Pipe,grpc-gateway 在轉發 grpc 服務時可以直接在內存 通信,不需要使用 socket 經過網卡轉發,這無疑增加了轉發效率。
- 創建了一些項目常用模塊
- db -> 數據庫層
- logger -> 分塊日誌
- sessions -> 用戶 session
- signal -> 模塊協作的插槽信號
- script -> 項目編譯等自動化腳本
環境配置
- 安裝好 nodejs 和 npm
- 安裝 jsgenerate,本喵使用 nodejs 實現的一個代碼生成工具
- npm install -g @king011/jsgenerate
- 安裝 jsgenerate_grpc-gateway 模板
- git clone https://github.com/powerpuffpenguin/jsgenerate_grpc-gateway.git ~/.jsgenerate/init/jsgenerate_grpc-gateway
創建項目
配置好環境後就可以使用 jsgenerate 指令新建項目,比如我們要在srv檔案夾下創建一個包名爲 powerpuffpenguin/example 的項目 可以輸入如下指令
mkdir srv && cd srv && \
jsgenerate init jsgenerate_grpc-gateway -t init-supplement -p powerpuffpenguin/example
-p 參數指定包名,-t 參數爲模板提供創建意見,支持多種選項比如 -t view 會創建一個默認的前端代碼到 view 檔案夾下
mkdir srv && cd srv && \
jsgenerate init jsgenerate_grpc-gateway -t init-supplement -t view -p powerpuffpenguin/example
輸入 -h 指令可以查看詳細使用說明
$ jsgenerate init jsgenerate_grpc-gateway -h
Usage: jsgenerate init jsgenerate_grpc-gateway [options]
google grpc frame template
Options:
-n, --name [] project name
-p, --package [] package name
-t, --tag [tags...] code generate tag
--list-tag list supported tag
-h, --help display help for command
項目結構清單
創建好的項目通常包含如下內容
- bin -> 編譯輸出的可執行檔案,日誌,配置檔案
- cmd -> 命令行解析,程式入口
- main.go -> 調用 cmd.Execute() 執行命令行解析
- configure -> 可執行檔案的配置定義
- db -> 數據庫層
- docker -> 通常可在此定義項目的docker鏡像
- logger -> 日誌實現
- m -> 模塊註冊與實現,通常你只需要修改這裏的go代碼實現自己的模塊功能
- pb -> grpc 的 定義檔案 (*.proto)
- protocol -> grpc 工具生成的 grpc 代碼
- script -> 一些爲項目提供幫助的自動化 bash 腳本
- build.sh -> 打包了 script 提供的功能到此腳本方便執行
- sessions -> 用戶 session
- signal -> 功能模塊應該完全隔離互不知道彼此,在此處使用插槽信號方式讓模塊通信
- static -> 一些嵌入的靜態檔案
- assets -> 靜態檔案生成的嵌入代碼
- third_party -> googleapis 的 *.proto
- utils -> 項目工具函數
- version -> 項目版本定義
- view -> 使用 -t view 會創建的一個 angular 實現的默認前端
編譯項目
爲了編譯項目你可能需要自行配置好以下環境,請參考各自官網的說明
- protocol buffer -> 生成 grpc 代碼
- golang grpc 插件 -> 生成 grpc 代碼
- grpc-gateway -> 生成 gateway 代碼 和 http api 接口文檔
- github.com/rakyll/statik -> 用於將靜態資源嵌入項目(api 接口文檔 前端view)
- angular -> 如果要嵌入默認前端實現(默認前端使用 angular)
配置好上述環境後就可以使用項目生成的 build.sh 來編譯項目
# 1. 生成 grpc 代碼
./build.sh grpc
# 2. 爲 api 文檔生成嵌入代碼
./build.sh document
# 3. 如果使用的默認前端,編譯前端並生成嵌入代碼
./build.sh view # 編譯前端
./build.sh view -s # -s 參數生成嵌入代碼
# 4. 編譯 go 代碼
./build.sh go
使用 -h 參數可以查看 build.sh 使用說明
$ ./build.sh -h
build script
Usage:
./build.sh [flags]
./build.sh [command]
Available Commands:
help help for ./build.sh
clear clear output
document static build document
go go build helper
view view build helper
grpc grpc protoc helper
pack pack release
run run project
docker docker build helper
Flags:
-h, --help help for ./build.sh
$ ./build.sh go -h
go build helper
Usage:
./build.sh go [flags]
Flags:
-c, --clear clear output
-d, --debug build debug mode
-l, --list list all supported platforms
-p, --pack pack to compressed package [7z gz bz2 xz zip]
-P, --platform build platform (default "linux/amd64")
-u, --upx use upx to compress executable programs
-h, --help help for ./build.sh go
script/conf.sh
script/conf.sh 用於爲自動腳本提供指導定義
Target="example"
Docker="powerpuffpenguin/example"
Dir=$(cd "$(dirname $BASH_SOURCE)/.." && pwd)
Version="v0.0.1"
View=1
Platforms=(
darwin/amd64
windows/amd64
linux/arm
linux/amd64
)
UUID="b1300070-c028-11eb-b0aa-27a5fad41b4d"
Protos=(
system/system.proto
session/session.proto
user/user.proto
logger/logger.proto
)
- Target -> 編譯輸出的可執行檔案名稱
- Docker -> docker 鏡像名稱
- Dir -> 項目根目錄,請不要修改
- Version -> 定義項目版本,build.sh go 時會自動修改源碼中的版本定義
- Platforms -> build.sh pack 時要編譯打包的平臺
- UUID -> proto uuid,請勿修改,用於解決 https://github.com/golang/protobuf/issues/1122 討論的問題
- Protos -> 參與生成的 grpc 定義,在添加了自定義 grpc 定義時將新的 *.proto 檔案添加到此列表中
添加 grpc 模塊
有了上述基礎後,剩下的創建新 grpc 模塊就很簡單了,模板已經提供了默認的幾個模塊你可以參考,應該按照下述步驟實現模塊
- 在 pb 檔案夾下 創建 *.proto 定義 grpc 和 gateway 提供的接口細節
- 在 script/conf.sh 檔案中 將創建的 *.proto 添加到 Protos 列表中
- 在 m/server 創建以包 實現 grpc 定義 和 提供一個 實現了 m.register.Module 接口的類型
- 在 m/register/grpc.go 中將實現的 m.register.Module 註冊到項目中
編譯項目後便可在使用 grpc 或 http 訪問模塊
document
嵌入的 http api 文檔,註冊的url 爲 /document/ ,你可以訪問此路徑查看,並在此訪問 http 接口以便測試