
簡介
go-zero是一個整合了各種工程實踐的 web 和 rpc 框架。透過彈性設計保障了大併發服務端的穩定性,經受了充分的實戰檢驗。
go-zero 包含極簡的 API 定義和生成工具 goctl,可以根據定義的 api 檔案一鍵生成 Go, iOS, Android, Kotlin, Dart, TypeScript, JavaScript 程式碼,並可直接執行。
go-zero框架能輕鬆獲得支撐千萬日活服務的穩定性,內建級聯超時控制、限流、自適應熔斷、自適應降載等微服務治理能力,無需配置和額外程式碼,微服務治理中介軟體可無縫整合到其它現有框架使用,極簡的 API 描述,一鍵生成各端程式碼,自動校驗客戶端請求引數合法性,大量微服務治理和併發工具包。
go-zero框架具有強大的工具支援,儘可能少的程式碼編寫,極簡的介面,完全相容 net/http,支援中介軟體,方便擴充套件,高效能,面向故障程式設計,彈性設計,內建服務發現、負載均衡,內建限流、熔斷、降載,且自動觸發,自動恢復,API 引數自動校驗,超時級聯控制,自動快取控制,鏈路跟蹤、統計報警等,高併發支撐,穩定保障了疫情期間每天的流量洪峰。
下面是官方給的架構圖

安裝和快速使用
安裝
這裡主要是go-zero、goctl和go-zero的安裝指令,可以參照官方的文件:快速開始
注意先安裝go,關於go的安裝和配置可以見部落格:g的安裝和使用
# go-zero安装
go get -u github.com/zeromicro/go-zero@latest
# goctl安装
go install github.com/zeromicro/go-zero/tools/goctl@latest
# protoc安装
goctl env check --install --verbose --force

快速使用
Api demo
在這裡我建立了一個資料夾GoZeroDemo存放go-zero微服務框架學習期間的相關程式碼,之後初始化專案,並使用gpctl自動生成簡單API相關檔案
# 创建并进入项目
mkdir GoZeroDemo && cd GoZeroDemo
# 初始化项目并命名
go mod init gozerodemo
# 使用goctl创建API服务
goctl api new greet
# 安装缺失的依赖
go mod tidy
下面是生成的程式碼框架,包括配置檔案、main檔案、配置定義檔案、網路路由相關檔案、請求邏輯檔案、業務邏輯相關檔案以及業務相關結構體檔案等等。

之後我們根據官方說明,在greetlogic.go中實現Greet,做簡單的 Say Hello,測試效果如下,一個簡單的單體服務就構建完成了。

透過簡單的使用go-zero我們可以發現,框架的作用就是幫你生成配套程式碼,你只需要完成相應的業務邏輯。
gRPC demo
繼續在GoZeroDemo目錄下建立gRPC服務aorange
# 使用goctl创建RPC服务
goctl rpc new aorange
# 安装缺失的依赖
go mod tidy

之後按照文件進行簡單修改測試:gRPC-demo

MySQL
建立sql檔案,之後透過goctl生成對應的golang檔案和操作方法,具體參考:mysql程式碼生成
goctl model mysql ddl --src user.sql --dir .

Mongo
mongo 不像 mysql 一樣有建表語句,索引等集中有規律的約束資訊,因此 mongo 程式碼的生成無需類似 sql 或者資料庫連結一樣的資訊。,具體參考:mongo程式碼生成
goctl model mongo --type user --dir .

format
還可以透過goctl進行格式化,具體見:api檔案格式化
goctl api format --dir demo.api
Goctl
下面是goctl相關的指令和說明,我們常用的就是api和rpc

Api

參考官方給的api示例,我們使用goctl透過api檔案建立服務
首先建立專案資料夾新增user.api
之後在終端輸入指令
goctl api go -api user.api -dir . -style goZero
syntax = "v1"
type (
// 定义登录接口的 json 请求体
LoginReq {
Username string `json:"username"`
Password string `json:"password"`
}
// 定义登录接口的 json 响应体
LoginResp {
Id int64 `json:"id"`
Name string `json:"name"`
Token string `json:"token"`
ExpireAt string `json:"expireAt"`
}
)
type (
// 定义获取用户信息的 json 请求体
GetUserInfoReq {
Id int64 `json:"id"`
}
// 定义获取用户信息的 json 响应体
GetUserInfoResp {
Id int64 `json:"id"`
Name string `json:"name"`
Desc string `json:"desc"`
}
// 定义更新用户信息的 json 请求体
UpdateUserInfoReq {
Id int64 `json:"id"`
Name string `json:"name"`
Desc string `json:"desc"`
}
)
// 定义 HTTP 服务
// @server 语法块主要用于控制对 HTTP 服务生成时 meta 信息,目前支持功能有:
// 1. 路由分组
// 2. 中间件声明
// 3. 路由前缀
// 4. 超时配置
// 5. jwt 鉴权开关
// 所有声明仅对当前 service 中的路由有效
@server (
// 代表当前 service 代码块下的路由生成代码时都会被放到 login 目录下
group: login
// 定义路由前缀为 "/v1"
prefix: /v1
)
// 微服务名称为 user,生成的代码目录和配置文件将和 user 值相关
service user {
// 定义 http.HandleFunc 转换的 go 文件名称及方法,每个接口都会跟一个 handler
@handler login
// 定义接口
// 请求方法为 post
// 路由为 /user/login
// 请求体为 LoginReq
// 响应体为 LoginResp,响应体必须有 returns 关键字修饰
post /user/login (LoginReq) returns (LoginResp)
}
// @server 语法块主要用于控制对 HTTP 服务生成时 meta 信息,目前支持功能有:
// 1. 路由分组
// 2. 中间件声明
// 3. 路由前缀
// 4. 超时配置
// 5. jwt 鉴权开关
// 所有声明仅对当前 service 中的路由有效
@server (
// 代表当前 service 代码块下的所有路由均需要 jwt 鉴权
// goctl 生成代码时会将当前 service 代码块下的接口
// 信息添加上 jwt 相关代码,Auth 值为 jwt 密钥,过期
// 等信息配置的 golang 结构体名称
jwt: Auth
// 代表当前 service 代码块下的路由生成代码时都会被放到 user 目录下
group: user
// 定义路由前缀为 "/v1"
prefix: /v1
)
// 注意,定义多个 service 代码块时,服务名称必须一致,因此这里的服务名称必须
// 和上文的 service 名称一样,为 user 服务。
service user {
// 定义 http.HandleFunc 转换的 go 文件名称及方法,每个接口都会跟一个 handler
@handler getUserInfo
// 定义接口
// 请求方法为 post
// 路由为 /user/info
// 请求体为 GetUserInfoReq
// 响应体为 GetUserInfoResp,响应体必须有 returns 关键字修饰
post /user/info (GetUserInfoReq) returns (GetUserInfoResp)
// 定义 http.HandleFunc 转换的 go 文件名称及方法,每个接口都会跟一个 handler
@handler updateUserInfo
// 定义接口
// 请求方法为 post
// 路由为 /user/info/update
// 请求体为 UpdateUserInfoReq
// 由于不需要响应体,因此可以忽略不写
post /user/info/update (UpdateUserInfoReq)
}

RPC

rpc採用同樣的方式
相關指令和程式碼如下:
goctl rpc protoc user.proto --go_out=. --go-grpc_out=. --zrpc_out=.
// 声明 proto 语法版本,固定值
syntax = "proto3";
// proto 包名
package greet;
// 生成 golang 代码后的包名
option go_package = "example/proto/greet";
// 定义枚举
enum Status{
UNSPECIFIED = 0;
SUCCESS = 1;
FAILED = 2;
}
// 定义结构体
message Base{
int32 code = 1;
string msg = 2;
}
message SendMessageReq{
string message = 1;
}
message SendMessage{
// 使用枚举
Status status = 1;
// 数组
repeated string array = 2;
// map
map<string,int32> map = 3;
// 布尔类型
bool boolean = 4;
// 序列号保留
reserved 5;
}
message SendMessageResp{
Base base = 1;
SendMessage data = 2;
}
// 定义 Greet 服务
service Greet {
// 定义客户端流式 rpc
rpc SendMessage(stream SendMessageReq) returns (SendMessageResp);
}

Model

以SQL為例,建立sql檔案,透過下面指令生成相關程式碼
goctl model mysql ddl -src"./user.sql" -dir="./sql/model" -c
