概述
go-zero 包含极简的 API 定义和生成工具 goctl,可以根据定义的 api 文件一键生成 Go, iOS, Android, Kotlin, Dart, TypeScript, JavaScript 代码,并可直接运行。
使用 go-zero 的好处:
- 轻松获得支撑千万日活服务的稳定性
- 内建级联超时控制、限流、自适应熔断、自适应降载等微服务治理能力,无需配置和额外代码
- 微服务治理中间件可无缝集成到其它现有框架使用
- 极简的 API 描述,一键生成各端代码
- 自动校验客户端请求参数合法性
- 大量微服务治理和并发工具包
快速上手
1 | # 安装 goct 软件 |
DSL 语言
在 Go Zero 框架中,DSL(Domain-Specific Language)通常用于定义 API 接口、数据库模型等。Go Zero 提供了 api
、model
等工具,可以通过简洁的 DSL 来生成对应的代码。
1. API DSL
在 Go Zero 中,API 的 DSL 文件通常以 .api
结尾,定义了 HTTP 路由、请求和响应结构。下面是一个简单的 API DSL 示例:
1 | info( |
解释:
info
: 定义了 API 的元信息,比如标题、描述、作者、版本等。type
: 定义了请求和响应的结构体。service
: 定义了服务,user-api
是服务名。@handler GetUser
: 指定了处理这个请求的处理函数。get /user/:userId
: 定义了一个 GET 请求,路径参数为userId
,请求体使用UserRequest
,响应体使用UserResponse
。
2. Model DSL
Go Zero 的 model
工具用于生成数据库模型。可以通过定义 DSL 文件,自动生成 CRUD 操作的代码。
1 | type ( |
解释:
type
: 定义了数据库表结构,这里的User
对应数据库中的user
表。method
: 定义了自动生成的数据库操作方法,比如FindOne
、Insert
、Update
和Delete
。
3. 如何生成代码
在定义好 .api
文件或模型的 DSL 文件后,可以使用 Go Zero 提供的工具生成对应的代码。
生成 API 代码:
1
goctl api go -api user.api -dir .
生成 Model 代码:
1
goctl model mysql ddl -src user.sql -dir .
通过这些 DSL,Go Zero 可以帮助开发者快速生成标准化的代码,减少手动编写的工作量。
使用gRpc方式来制作
1 | # 单个 rpc 服务生成示例指令 |
model 导出数据
1 | goctl model pg datasource --url "postgres://postgres:123456@127.0.0.1:5432/postgres?sslmode=disable" -table="tb_kline_config,tb_kline_data,tb_kline_rpc,tb_token_quote" |
在 go-zero 框架中,通过 gRPC 的拦截器机制,可以轻松实现对每个接口调用速度的监控。拦截器是一种中间层机制,允许你在 gRPC 请求处理的前后执行额外的逻辑,例如记录日志、统计调用时间、验证权限等。
以下是实现步骤和示例代码:
实现步骤
1. 定义一个拦截器
使用 UnaryServerInterceptor 来监控单次请求,或使用 StreamServerInterceptor 来监控流式请求。
2. 在拦截器中记录每次接口调用的开始和结束时间
使用 time.Now() 捕获起始时间,计算处理完成时的耗时。
3. 在 gRPC 服务注册时添加拦截器
在服务启动时,将拦截器注册到 gRPC 服务器。
示例代码
定义拦截器
package middleware
import (
“context”
“log”
“time”
"google.golang.org/grpc"
)
// UnaryServerInterceptor for monitoring request processing time
func UnaryLoggingInterceptor(
ctx context.Context,
req interface{},
info *grpc.UnaryServerInfo,
handler grpc.UnaryHandler,
) (resp interface{}, err error) {
start := time.Now()
// 调用实际的处理器
resp, err = handler(ctx, req)
// 计算处理时间
duration := time.Since(start)
log.Printf("Request - Method: %s, Duration: %s, Error: %v", info.FullMethod, duration, err)
return resp, err
}
// StreamServerInterceptor for monitoring stream request processing time
func StreamLoggingInterceptor(
srv interface{},
ss grpc.ServerStream,
info *grpc.StreamServerInfo,
handler grpc.StreamHandler,
) error {
start := time.Now()
// 调用实际的处理器
err := handler(srv, ss)
// 计算处理时间
duration := time.Since(start)
log.Printf("Stream Request - Method: %s, Duration: %s, Error: %v", info.FullMethod, duration, err)
return err
}
在服务启动时注册拦截器
在 go-zero 的 gRPC 服务中,拦截器可以通过配置 grpc.ServerOption 来注册。
package main
import (
“log”
“net”
"github.com/zeromicro/go-zero/zrpc"
"google.golang.org/grpc"
"your_project_path/middleware"
)
func main() {
// 创建一个 gRPC 服务器
s := zrpc.MustNewServer(zrpc.RpcServerConf{}, func(grpcServer *grpc.Server) {
// 注册服务实现(示例:注册 UserService)
RegisterUserServiceServer(grpcServer, &UserService{})
})
// 添加拦截器
s.AddUnaryInterceptors(middleware.UnaryLoggingInterceptor)
s.AddStreamInterceptors(middleware.StreamLoggingInterceptor)
// 启动服务
defer s.Stop()
log.Printf("Starting rpc server at %s...\n", s.Addr())
s.Start()
}
结果
1. 每次 gRPC 接口调用,UnaryLoggingInterceptor 或 StreamLoggingInterceptor 会自动记录接口的执行时间。
2. 日志会输出类似以下信息:
Request - Method: /UserService/GetUser, Duration: 3.2ms, Error:
3. 你可以根据 Duration 来分析接口的响应速度。
优化建议
1. 统计存储:
如果需要长时间分析接口性能,可以将数据存储到数据库或监控工具(如 Prometheus)中。
2. 结合 Metrics 工具:
使用 go-zero 提供的监控工具(如 Prometheus 集成)自动统计接口性能和调用量。
3. 区分接口类型:
根据 info.FullMethod 提取服务名和接口名,方便按模块统计。
进一步扩展
如果需要对调用速度设置阈值报警,可以在拦截器中添加逻辑:
if duration > time.Millisecond*500 { // 超过 500ms
log.Printf(“WARNING: Slow request detected - Method: %s, Duration: %s”, info.FullMethod, duration)
}
这样可以在代码中快速检测并报警慢接口问题。
引用
- [1] github-go-zero
- [2] go-zero