26 KiB
26 KiB
中间件工具文档
概述
中间件工具提供了常用的HTTP中间件功能,包括CORS处理、时区管理、请求日志、Panic恢复和限流等。
功能特性
- CORS中间件:支持跨域资源共享配置
- 时区中间件:从请求头读取时区信息,支持默认时区设置
- 日志中间件:自动记录每个HTTP请求的详细信息
- Recovery中间件:捕获panic并恢复,防止服务崩溃
- 限流中间件:基于令牌桶算法的请求限流
- 中间件链:提供便捷的中间件链式调用
CORS中间件
功能说明
CORS中间件用于处理跨域资源共享,支持:
- 配置允许的源(支持通配符)
- 配置允许的HTTP方法
- 配置允许的请求头
- 配置暴露的响应头
- 支持凭证传递
- 预检请求缓存时间设置
使用方法
基本使用(默认配置)
import (
"net/http"
"git.toowon.com/jimmy/go-common/middleware"
)
func main() {
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// 处理请求
})
// 使用默认CORS配置
corsHandler := middleware.CORS()(handler)
http.Handle("/api", corsHandler)
http.ListenAndServe(":8080", nil)
}
自定义配置
import (
"net/http"
"git.toowon.com/jimmy/go-common/middleware"
)
func main() {
// 自定义CORS配置
corsConfig := &middleware.CORSConfig{
AllowedOrigins: []string{
"https://example.com",
"https://app.example.com",
"*.example.com", // 支持通配符
},
AllowedMethods: []string{"GET", "POST", "PUT", "DELETE", "OPTIONS"},
AllowedHeaders: []string{
"Content-Type",
"Authorization",
"X-Requested-With",
"X-Timezone",
},
ExposedHeaders: []string{"X-Total-Count"},
AllowCredentials: true,
MaxAge: 3600, // 1小时
}
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// 处理请求
})
corsHandler := middleware.CORS(corsConfig)(handler)
http.Handle("/api", corsHandler)
http.ListenAndServe(":8080", nil)
}
允许所有源(开发环境)
corsConfig := &middleware.CORSConfig{
AllowedOrigins: []string{"*"},
AllowedMethods: []string{"GET", "POST", "PUT", "DELETE", "OPTIONS"},
AllowedHeaders: []string{"*"},
}
corsHandler := middleware.CORS(corsConfig)(handler)
CORSConfig 配置说明
| 字段 | 类型 | 说明 | 默认值 |
|---|---|---|---|
| AllowedOrigins | []string | 允许的源,支持 "" 和 ".example.com" | ["*"] |
| AllowedMethods | []string | 允许的HTTP方法 | ["GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS"] |
| AllowedHeaders | []string | 允许的请求头 | ["Content-Type", "Authorization", "X-Requested-With", "X-Timezone"] |
| ExposedHeaders | []string | 暴露给客户端的响应头 | [] |
| AllowCredentials | bool | 是否允许发送凭证 | false |
| MaxAge | int | 预检请求缓存时间(秒) | 86400 |
注意事项
- 如果
AllowCredentials为true,AllowedOrigins不能使用 "*",必须指定具体的源 - 通配符支持:
"*.example.com"会匹配"https://app.example.com"等子域名 - 预检请求(OPTIONS)会自动处理,无需在业务代码中处理
时区中间件
功能说明
时区中间件用于从请求头读取时区信息,并存储到context中,方便后续使用。
- 从请求头
X-Timezone读取时区 - 如果未传递时区信息,使用默认时区
AsiaShanghai - 时区信息存储到context中,可通过Handler的
GetTimezone()方法获取 - 自动验证时区有效性,无效时区会回退到默认时区
使用方法
基本使用(默认时区 AsiaShanghai)
import (
"net/http"
"git.toowon.com/jimmy/go-common/middleware"
commonhttp "git.toowon.com/jimmy/go-common/http"
"git.toowon.com/jimmy/go-common/datetime"
)
func handler(w http.ResponseWriter, r *http.Request) {
h := commonhttp.NewHandler(w, r)
// 从Handler获取时区
timezone := h.GetTimezone()
// 使用时区
now := datetime.Now(timezone)
datetime.FormatDateTime(now, timezone)
h.Success(map[string]interface{}{
"timezone": timezone,
"time": datetime.FormatDateTime(now),
})
}
func main() {
handler := middleware.Timezone(http.HandlerFunc(handler))
http.Handle("/api", handler)
http.ListenAndServe(":8080", nil)
}
自定义默认时区
import (
"net/http"
"git.toowon.com/jimmy/go-common/middleware"
"git.toowon.com/jimmy/go-common/datetime"
)
func handler(w http.ResponseWriter, r *http.Request) {
// 处理请求
}
func main() {
// 使用自定义默认时区
handler := middleware.TimezoneWithDefault(datetime.UTC)(http.HandlerFunc(handler))
http.Handle("/api", handler)
http.ListenAndServe(":8080", nil)
}
在业务代码中使用时区
import (
"net/http"
commonhttp "git.toowon.com/jimmy/go-common/http"
"git.toowon.com/jimmy/go-common/datetime"
)
func GetUserList(w http.ResponseWriter, r *http.Request) {
h := commonhttp.NewHandler(w, r)
// 从Handler获取时区
timezone := h.GetTimezone()
// 使用时区进行时间处理
now := datetime.Now(timezone)
// 查询数据时使用时区
startTime := datetime.StartOfDay(now, timezone)
endTime := datetime.EndOfDay(now, timezone)
// 返回数据
h.Success(map[string]interface{}{
"timezone": timezone,
"startTime": datetime.FormatDateTime(startTime),
"endTime": datetime.FormatDateTime(endTime),
})
}
请求头格式
客户端需要在请求头中传递时区信息:
X-Timezone: Asia/Shanghai
支持的时区格式(IANA时区数据库):
Asia/ShanghaiAmerica/New_YorkEurope/LondonUTC- 等等
注意事项
- 如果请求头中未传递
X-Timezone,默认使用AsiaShanghai - 如果传递的时区无效,会自动回退到默认时区
- 时区信息存储在context中,可以在整个请求生命周期中使用
- 建议在CORS配置中包含
X-Timezone请求头
日志中间件
功能说明
日志中间件用于自动记录每个HTTP请求的详细信息,帮助监控和调试应用。
记录内容包括:
- 请求方法、路径、查询参数
- 响应状态码、响应大小
- 请求处理时间(毫秒)
- 客户端IP地址(支持X-Forwarded-For)
- User-Agent、Referer等信息
使用方法
基本使用(使用默认logger)
import (
"net/http"
"git.toowon.com/jimmy/go-common/middleware"
)
func main() {
chain := middleware.NewChain(
middleware.Logging(nil), // 使用默认配置
middleware.CORS(),
middleware.Timezone,
)
handler := chain.ThenFunc(apiHandler)
http.Handle("/api", handler)
http.ListenAndServe(":8080", nil)
}
使用自定义logger
import (
"git.toowon.com/jimmy/go-common/middleware"
"git.toowon.com/jimmy/go-common/logger"
)
func main() {
// 创建自定义logger(异步模式,输出到文件)
loggerConfig := &logger.LoggerConfig{
Level: "info",
Output: "file",
FilePath: "./logs/app.log",
Async: true, // 异步模式,不阻塞请求
BufferSize: 1000,
}
myLogger, _ := logger.NewLogger(loggerConfig)
// 配置日志中间件
loggingConfig := &middleware.LoggingConfig{
Logger: myLogger,
SkipPaths: []string{"/health", "/metrics"}, // 跳过健康检查接口
}
chain := middleware.NewChain(
middleware.Logging(loggingConfig),
middleware.CORS(),
middleware.Timezone,
)
handler := chain.ThenFunc(apiHandler)
http.Handle("/api", handler)
http.ListenAndServe(":8080", nil)
}
LoggingConfig 配置说明
| 字段 | 类型 | 说明 | 默认值 |
|---|---|---|---|
| Logger | *logger.Logger | 日志记录器 | 创建默认logger(stdout) |
| SkipPaths | []string | 跳过记录的路径列表 | [] |
| LogRequestBody | bool | 是否记录请求体(慎用) | false |
| LogResponseBody | bool | 是否记录响应体(慎用) | false |
日志输出示例
[INFO] HTTP Request method=GET path=/api/users query= status=200 size=1024 duration=45 ip=192.168.1.100 user_agent=Mozilla/5.0 referer=
[WARN] HTTP Request method=POST path=/api/users query= status=400 size=128 duration=12 ip=192.168.1.100 user_agent=PostmanRuntime/7.29
[ERROR] HTTP Request method=GET path=/api/error query= status=500 size=256 duration=89 ip=192.168.1.100 user_agent=curl/7.64.1 referer=
注意事项
- 异步模式推荐:生产环境建议使用异步logger,避免日志写入阻塞请求
- 跳过路径:健康检查、监控接口等高频接口建议跳过日志记录
- 日志级别:根据状态码自动选择日志级别(5xx=ERROR, 4xx=WARN, 2xx-3xx=INFO)
- 客户端IP:自动从X-Forwarded-For、X-Real-IP或RemoteAddr获取真实IP
Recovery中间件
功能说明
Recovery中间件用于捕获HTTP处理过程中的panic,防止panic导致整个服务崩溃。
功能包括:
- 捕获panic并恢复服务
- 记录panic信息和堆栈跟踪
- 返回500错误响应
- 支持自定义错误处理
使用方法
基本使用(使用默认配置)
import (
"net/http"
"git.toowon.com/jimmy/go-common/middleware"
)
func main() {
chain := middleware.NewChain(
middleware.Recovery(nil), // 使用默认配置
middleware.Logging(nil),
middleware.CORS(),
middleware.Timezone,
)
handler := chain.ThenFunc(apiHandler)
http.Handle("/api", handler)
http.ListenAndServe(":8080", nil)
}
使用自定义logger
import (
"git.toowon.com/jimmy/go-common/middleware"
"git.toowon.com/jimmy/go-common/logger"
)
func main() {
myLogger, _ := logger.NewLogger(nil)
recoveryConfig := &middleware.RecoveryConfig{
Logger: myLogger,
EnableStackTrace: true, // 启用堆栈跟踪
}
chain := middleware.NewChain(
middleware.Recovery(recoveryConfig),
middleware.Logging(nil),
)
handler := chain.ThenFunc(apiHandler)
http.Handle("/api", handler)
http.ListenAndServe(":8080", nil)
}
自定义错误响应
import (
"net/http"
commonhttp "git.toowon.com/jimmy/go-common/http"
"git.toowon.com/jimmy/go-common/middleware"
)
func main() {
recoveryConfig := &middleware.RecoveryConfig{
EnableStackTrace: true,
CustomHandler: func(w http.ResponseWriter, r *http.Request, err interface{}) {
// 使用统一的JSON响应格式
h := commonhttp.NewHandler(w, r)
h.SystemError("服务器内部错误")
},
}
chain := middleware.NewChain(
middleware.Recovery(recoveryConfig),
)
handler := chain.ThenFunc(apiHandler)
http.Handle("/api", handler)
http.ListenAndServe(":8080", nil)
}
RecoveryConfig 配置说明
| 字段 | 类型 | 说明 | 默认值 |
|---|---|---|---|
| Logger | *logger.Logger | 日志记录器 | 创建默认logger |
| EnableStackTrace | bool | 是否记录堆栈跟踪 | true |
| CustomHandler | func(...) | 自定义错误处理函数 | nil(返回500文本) |
注意事项
- 放在最外层:Recovery中间件应该放在中间件链的最前面,以捕获所有panic
- 日志记录:建议配置logger,确保panic信息被记录下来
- 堆栈跟踪:生产环境建议启用,方便排查问题
- 自定义响应:可以自定义错误响应格式,统一错误处理
限流中间件
功能说明
限流中间件用于限制请求频率,防止API被滥用或遭受攻击。
特性:
- 基于令牌桶算法
- 支持按IP、用户ID等维度限流
- 自动设置限流响应头
- 内存存储,自动清理过期数据
使用方法
基本使用(默认配置:100请求/分钟)
import (
"net/http"
"git.toowon.com/jimmy/go-common/middleware"
)
func main() {
chain := middleware.NewChain(
middleware.Recovery(nil),
middleware.Logging(nil),
middleware.RateLimit(nil), // 默认100请求/分钟,按IP限流
middleware.CORS(),
)
handler := chain.ThenFunc(apiHandler)
http.Handle("/api", handler)
http.ListenAndServe(":8080", nil)
}
自定义限流规则
import (
"time"
"git.toowon.com/jimmy/go-common/middleware"
)
func main() {
// 创建限流器:10请求/分钟
limiter := middleware.NewTokenBucketLimiter(10, time.Minute)
rateLimitConfig := &middleware.RateLimitConfig{
Limiter: limiter,
}
chain := middleware.NewChain(
middleware.RateLimit(rateLimitConfig),
)
handler := chain.ThenFunc(apiHandler)
http.Handle("/api", handler)
http.ListenAndServe(":8080", nil)
}
按用户ID限流
import (
"net/http"
"time"
"git.toowon.com/jimmy/go-common/middleware"
)
func main() {
limiter := middleware.NewTokenBucketLimiter(100, time.Minute)
rateLimitConfig := &middleware.RateLimitConfig{
Limiter: limiter,
KeyFunc: func(r *http.Request) string {
// 从请求头或JWT token中获取用户ID
userID := r.Header.Get("X-User-ID")
if userID != "" {
return "user:" + userID
}
// 如果没有用户ID,使用IP
return "ip:" + r.RemoteAddr
},
OnRateLimitExceeded: func(w http.ResponseWriter, r *http.Request, key string) {
// 记录限流事件
println("Rate limit exceeded for:", key)
},
}
chain := middleware.NewChain(
middleware.RateLimit(rateLimitConfig),
)
handler := chain.ThenFunc(apiHandler)
http.Handle("/api", handler)
http.ListenAndServe(":8080", nil)
}
便捷函数
// 按IP限流:10请求/分钟
chain := middleware.NewChain(
middleware.RateLimitByIP(10, time.Minute),
)
// 或使用自定义速率
chain := middleware.NewChain(
middleware.RateLimitWithRate(50, time.Minute),
)
RateLimitConfig 配置说明
| 字段 | 类型 | 说明 | 默认值 |
|---|---|---|---|
| Limiter | RateLimiter | 限流器实例 | 100请求/分钟 |
| KeyFunc | func(*http.Request) string | 生成限流键的函数 | 使用客户端IP |
| OnRateLimitExceeded | func(...) | 限流触发回调 | nil |
响应头说明
限流中间件会自动设置以下响应头:
| 响应头 | 说明 |
|---|---|
| X-RateLimit-Limit | 窗口期内允许的请求数 |
| X-RateLimit-Remaining | 当前窗口剩余配额 |
| X-RateLimit-Reset | 配额重置时间(Unix时间戳) |
| Retry-After | 限流时,建议重试的等待时间(秒) |
响应示例
正常请求:
HTTP/1.1 200 OK
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 95
X-RateLimit-Reset: 1640000000
触发限流:
HTTP/1.1 429 Too Many Requests
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1640000000
Retry-After: 45
Too Many Requests
注意事项
- 内存存储:当前实现使用内存存储,适用于单机部署。如需分布式限流,建议使用Redis
- 键设计:合理设计限流键,可以按IP、用户、API等维度限流
- 清理机制:自动清理过期的限流数据,避免内存泄漏
- 算法选择:使用令牌桶算法,支持突发流量
中间件链
功能说明
中间件链提供便捷的中间件组合方式,支持链式调用。
使用方法
import (
"net/http"
"git.toowon.com/jimmy/go-common/middleware"
)
func handler(w http.ResponseWriter, r *http.Request) {
// 处理请求
}
func main() {
// 创建中间件链
chain := middleware.NewChain(
middleware.CORS(),
middleware.Timezone,
)
// 应用到处理器
handler := chain.ThenFunc(handler)
http.Handle("/api", handler)
http.ListenAndServe(":8080", nil)
}
链式追加中间件
chain := middleware.NewChain(middleware.CORS())
chain.Append(middleware.Timezone)
handler := chain.ThenFunc(handler)
完整示例
示例1:完整的生产级中间件配置
package main
import (
"log"
"net/http"
"time"
"git.toowon.com/jimmy/go-common/middleware"
"git.toowon.com/jimmy/go-common/logger"
commonhttp "git.toowon.com/jimmy/go-common/http"
"git.toowon.com/jimmy/go-common/datetime"
)
func apiHandler(w http.ResponseWriter, r *http.Request) {
h := commonhttp.NewHandler(w, r)
// 从Handler获取时区
timezone := h.GetTimezone()
now := datetime.Now(timezone)
h.Success(map[string]interface{}{
"message": "Hello",
"timezone": timezone,
"time": datetime.FormatDateTime(now),
})
}
func main() {
// 1. 配置logger(异步模式,输出到文件)
loggerConfig := &logger.LoggerConfig{
Level: "info",
Output: "both", // 同时输出到stdout和文件
FilePath: "./logs/app.log",
Async: true,
BufferSize: 1000,
}
myLogger, err := logger.NewLogger(loggerConfig)
if err != nil {
log.Fatal(err)
}
defer myLogger.Close() // 确保程序退出时关闭logger
// 2. 配置CORS
corsConfig := &middleware.CORSConfig{
AllowedOrigins: []string{"*"},
AllowedMethods: []string{"GET", "POST", "PUT", "DELETE", "OPTIONS"},
AllowedHeaders: []string{"Content-Type", "Authorization", "X-Timezone"},
}
// 3. 配置日志中间件
loggingConfig := &middleware.LoggingConfig{
Logger: myLogger,
SkipPaths: []string{"/health", "/metrics"},
}
// 4. 配置Recovery中间件
recoveryConfig := &middleware.RecoveryConfig{
Logger: myLogger,
EnableStackTrace: true,
CustomHandler: func(w http.ResponseWriter, r *http.Request, err interface{}) {
h := commonhttp.NewHandler(w, r)
h.SystemError("服务器内部错误")
},
}
// 5. 配置限流中间件(100请求/分钟)
rateLimiter := middleware.NewTokenBucketLimiter(100, time.Minute)
rateLimitConfig := &middleware.RateLimitConfig{
Limiter: rateLimiter,
OnRateLimitExceeded: func(w http.ResponseWriter, r *http.Request, key string) {
myLogger.Warnf(map[string]interface{}{
"key": key,
"path": r.URL.Path,
}, "Rate limit exceeded")
},
}
// 6. 创建中间件链(顺序很重要!)
chain := middleware.NewChain(
middleware.Recovery(recoveryConfig), // 最外层:捕获panic
middleware.Logging(loggingConfig), // 日志记录
middleware.RateLimit(rateLimitConfig), // 限流
middleware.CORS(corsConfig), // CORS处理
middleware.Timezone, // 时区处理
)
// 7. 应用中间件
http.Handle("/api", chain.ThenFunc(apiHandler))
http.HandleFunc("/health", func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("OK"))
})
log.Println("Server started on :8080")
log.Fatal(http.ListenAndServe(":8080", nil))
}
示例2:基础的CORS + 时区中间件
package main
import (
"log"
"net/http"
"git.toowon.com/jimmy/go-common/middleware"
commonhttp "git.toowon.com/jimmy/go-common/http"
"git.toowon.com/jimmy/go-common/datetime"
)
func apiHandler(w http.ResponseWriter, r *http.Request) {
h := commonhttp.NewHandler(w, r)
// 从Handler获取时区
timezone := h.GetTimezone()
now := datetime.Now(timezone)
h.Success(map[string]interface{}{
"message": "Hello",
"timezone": timezone,
"time": datetime.FormatDateTime(now),
})
}
func main() {
// 创建简单的中间件链
chain := middleware.NewChain(
middleware.CORS(nil), // 使用默认CORS配置
middleware.Timezone, // 使用默认时区
)
http.Handle("/api", chain.ThenFunc(apiHandler))
log.Println("Server started on :8080")
log.Fatal(http.ListenAndServe(":8080", nil))
}
示例2:与路由框架集成
package main
import (
"net/http"
"git.toowon.com/jimmy/go-common/middleware"
commonhttp "git.toowon.com/jimmy/go-common/http"
)
func main() {
mux := http.NewServeMux()
// 创建中间件链
chain := middleware.NewChain(
middleware.CORS(),
middleware.Timezone,
)
// 应用中间件到所有路由
mux.Handle("/api/users", chain.ThenFunc(getUsers))
mux.Handle("/api/posts", chain.ThenFunc(getPosts))
http.ListenAndServe(":8080", mux)
}
func getUsers(w http.ResponseWriter, r *http.Request) {
h := commonhttp.NewHandler(w, r)
timezone := h.GetTimezone()
// 处理逻辑
h.Success(nil)
}
func getPosts(w http.ResponseWriter, r *http.Request) {
h := commonhttp.NewHandler(w, r)
timezone := h.GetTimezone()
// 处理逻辑
h.Success(nil)
}
API 参考
CORS中间件
CORS(config ...*CORSConfig) func(http.Handler) http.Handler
创建CORS中间件。
参数:
config: 可选的CORS配置,不指定则使用默认配置
返回: 中间件函数
DefaultCORSConfig() *CORSConfig
返回默认的CORS配置。
时区中间件
Timezone(next http.Handler) http.Handler
时区处理中间件(默认时区为 AsiaShanghai)。
TimezoneWithDefault(defaultTimezone string) func(http.Handler) http.Handler
时区处理中间件(可自定义默认时区)。
参数:
defaultTimezone: 默认时区字符串
返回: 中间件函数
GetTimezoneFromContext(ctx context.Context) string
从context中获取时区。
日志中间件
Logging(config *LoggingConfig) func(http.Handler) http.Handler
创建日志中间件。
参数:
config: 日志配置,nil则使用默认配置
返回: 中间件函数
Recovery中间件
Recovery(config *RecoveryConfig) func(http.Handler) http.Handler
创建Recovery中间件。
参数:
config: Recovery配置,nil则使用默认配置
返回: 中间件函数
RecoveryWithLogger(log *logger.Logger) func(http.Handler) http.Handler
使用指定logger的Recovery中间件(便捷函数)。
RecoveryWithCustomHandler(customHandler func(...)) func(http.Handler) http.Handler
使用自定义错误处理的Recovery中间件(便捷函数)。
限流中间件
RateLimit(config *RateLimitConfig) func(http.Handler) http.Handler
创建限流中间件。
参数:
config: 限流配置,nil则使用默认配置(100请求/分钟)
返回: 中间件函数
NewTokenBucketLimiter(rate int, windowSize time.Duration) RateLimiter
创建令牌桶限流器。
参数:
rate: 每个窗口期允许的请求数windowSize: 窗口大小
返回: 限流器实例
RateLimitWithRate(rate int, windowSize time.Duration) func(http.Handler) http.Handler
使用指定速率创建限流中间件(便捷函数)。
RateLimitByIP(rate int, windowSize time.Duration) func(http.Handler) http.Handler
按IP限流(便捷函数)。
中间件链
NewChain(middlewares ...func(http.Handler) http.Handler) *Chain
创建新的中间件链。
(c *Chain) Then(handler http.Handler) http.Handler
将中间件链应用到处理器。
(c *Chain) ThenFunc(handler http.HandlerFunc) http.Handler
将中间件链应用到处理器函数。
(c *Chain) Append(middlewares ...func(http.Handler) http.Handler) *Chain
追加中间件到链中。
注意事项
1. CORS配置
- 生产环境建议明确指定允许的源,避免使用 "*"
- 如果使用凭证(cookies),必须明确指定源,不能使用 "*"
- CORS中间件应该在Recovery和Logging之后,以便正确处理预检请求
2. 时区处理
- 时区信息存储在context中,确保中间件在处理器之前执行
- 时区验证失败时会自动回退到默认时区,不会返回错误
- 建议在CORS配置中包含
X-Timezone请求头
3. 日志记录
- 生产环境推荐异步模式:避免日志写入阻塞请求,提升性能
- 跳过高频接口:健康检查、监控接口等高频接口建议跳过日志
- 日志轮转:使用文件输出时,建议配合日志轮转工具(如logrotate)
- 敏感信息:不要记录请求体和响应体,避免泄露敏感信息
4. Panic恢复
- 放在最外层:Recovery中间件应该放在中间件链的最前面
- 记录日志:务必配置logger,确保panic信息被记录
- 监控告警:建议将panic事件接入监控系统,及时发现问题
- 堆栈跟踪:生产环境建议启用,方便排查问题
5. 限流配置
- 合理设置阈值:根据实际业务需求设置限流阈值
- 分布式部署:当前实现使用内存存储,适用于单机。分布式部署建议使用Redis
- 键设计:合理设计限流键,可以按IP、用户、API等维度限流
- 响应头:客户端可以根据X-RateLimit-*响应头实现智能重试
6. 中间件顺序(推荐)
建议的中间件顺序(从外到内):
- Recovery - 最外层,捕获所有panic
- Logging - 记录所有请求(包括限流的请求)
- RateLimit - 限流保护
- CORS - 处理跨域
- Timezone - 时区处理
- 业务中间件 - 认证、授权等
chain := middleware.NewChain(
middleware.Recovery(recoveryConfig), // 1. Panic恢复
middleware.Logging(loggingConfig), // 2. 日志记录
middleware.RateLimit(rateLimitConfig), // 3. 限流
middleware.CORS(corsConfig), // 4. CORS
middleware.Timezone, // 5. 时区
)
7. 性能考虑
- 异步日志:使用异步logger,避免IO阻塞
- 限流算法:令牌桶算法支持突发流量
- 自动清理:限流数据会自动清理,避免内存泄漏
- 跳过路径:合理使用SkipPaths,减少不必要的处理
8. 生产环境建议
- 使用异步logger,配置日志文件和轮转
- 启用Recovery中间件,配置告警
- 根据业务设置合理的限流阈值
- 配置监控指标(请求量、错误率、限流触发次数等)
- 定期review日志,优化性能瓶颈