Skip to content

第18章:限流、压缩与其他常用中间件 ​

本章目标 ​

学完本章后,你将能够:

  1. 使用令牌桶算法实现限流
  2. 配置 Gzip 压缩提升传输效率
  3. 使用安全头中间件保护应用
  4. 组合常用的中间件搭建生产级 Gin 服务

前置知识 ​

  • 需要先学习:第16-17章(自定义中间件、CORS)

18.1 Gzip 压缩 ​

bash
go get github.com/gin-contrib/gzip
go
import "github.com/gin-contrib/gzip"

r.Use(gzip.Gzip(gzip.DefaultCompression))
// 响应体 > 默认阈值时自动压缩,减少传输量 70%+

18.2 安全头中间件 ​

bash
go get github.com/gin-contrib/secure
go
import "github.com/gin-contrib/secure"

r.Use(secure.New(secure.Config{
	SSLRedirect:           true,
	STSSeconds:            315360000,
	STSIncludeSubdomains:  true,
	FrameDeny:             true,
	ContentTypeNosniff:    true,
	BrowserXssFilter:      true,
}))
// 自动添加:X-Frame-Options, X-XSS-Protection 等安全头

18.3 请求大小限制中间件 ​

go
func MaxBodySize(maxBytes int64) gin.HandlerFunc {
	return func(c *gin.Context) {
		c.Request.Body = http.MaxBytesReader(c.Writer, c.Request.Body, maxBytes)
		c.Next()
	}
}

// 限制请求体最大 1MB
r.Use(MaxBodySize(1 << 20))

18.4 生产环境中间件组合 ​

go
func SetupProductionRouter() *gin.Engine {
	r := gin.New()

	// 1. 安全相关(最外层)
	r.Use(secure.New(secure.DefaultConfig()))
	r.Use(CORSMiddleware())

	// 2. 性能相关
	r.Use(gzip.Gzip(gzip.DefaultCompression))
	r.Use(MaxBodySize(10 << 20))  // 10MB

	// 3. 追踪与日志
	r.Use(TraceID())
	r.Use(gin.Logger())
	r.Use(gin.Recovery())

	// 4. 业务中间件
	r.Use(RateLimiter(100, time.Minute))  // 全局限流

	return r
}

18.5 中间件顺序建议 ​

请求 →
  1. 安全中间件(CORS, Secure Headers)
  2. 性能中间件(Gzip, BodyLimit)
  3. 追踪中间件(TraceID, Logger)
  4. Recovery(捕获 panic)
  5. 认证中间件(Auth, JWT)
  6. 业务中间件(限流,权限)
  7. 路由处理函数(Handler)
→ 响应

常见错误 ​

错误1:Gzip 压缩了小文件 ​

go
// ⚠️ 小于 1KB 的文件压缩后可能更大
// ✅ 设置合理阈值
gzip.Gzip(gzip.BestSpeed, gzip.WithExcludedPaths([]string{"/api/"}))

错误2:安全头与 Nginx 重复 ​

如果你用了 Nginx 反向代理,安全头可能在 Nginx 层已经设置了,Gin 层不需要重复。


本章小结 ​

  • 生产环境中间件组合:安全 → 性能 → 追踪 → Recovery → 认证 → 业务
  • Gzip 大幅减少 JSON 传输量(70%+)
  • Secure Headers 防 XSS/点击劫持等攻击
  • 限流保护服务不被突发流量打垮

练习题 ​

  1. 集成 Gzip 中间件,对比启用前后的响应大小。
  2. 配置 secure 中间件,观察响应头的变化。
  3. 写一个限制请求体大小的中间件。
  4. (思考题)中间件顺序为什么重要?CORS 为什么要放在 Auth 前面?

把零散知识,整理成可以反复走的路。