r.Run(":8080") 很方便,但生产里你往往需要更细的服务配置。
#1. Gin 本质上就是一个 http.Handler
这件事一定要吃透。
srv := &http.Server{
Addr: ":8080",
Handler: r,
ReadTimeout: 10 * time.Second,
WriteTimeout: 10 * time.Second,
MaxHeaderBytes: 1 << 20,
}
log.Fatal(srv.ListenAndServe())这说明:
Gin 不是替代 net/http
而是站在 net/http 上面,自己就是一个可交给 http.Server 的 Handler#2. 为什么生产更常自己建 http.Server
因为你要控制:
- 读超时
- 写超时
- Header 限制
- TLS
- 优雅停机
- 自定义监听方式
#3. 优雅停机
真实中枢下班不能粗暴拉闸。
ctx, stop := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM)
defer stop()
go func() {
<-ctx.Done()
shutdownCtx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
_ = srv.Shutdown(shutdownCtx)
}()它的心智是:
收到停机通知
│
▼
不再接新车
│
▼
让站内正在处理的车尽量办完
│
▼
再平稳关门#4. 反向代理场景下的 TrustedProxies
这是 Gin 生产安全里非常容易被忽略的一条。
如果你的服务跑在:
- Nginx 后面
- 负载均衡后面
- 云网关后面
- CDN 后面
那客户端 IP 往往来自 X-Forwarded-For 一类 header。
问题是:
这些 header 不是天然可信的。
Gin 官方明确提醒过:如果你不配置可信代理,默认信任所有代理是不安全的。
if err := r.SetTrustedProxies([]string{"10.0.0.0/8", "192.168.1.0/24"}); err != nil {
log.Fatal(err)
}如果你根本没用代理,反而应该显式关掉:
if err := r.SetTrustedProxies(nil); err != nil {
log.Fatal(err)
}别小看这件事。它直接影响:
ClientIP()- 基于 IP 的权限控制
- 基于 IP 的限流
- 审计日志可信度
#5. HTTPS 与自动证书
Gin 官方还维护了 autotls 方案,可以比较顺手地接 Let’s Encrypt。
不过真正生产上,你更常见的路线仍然是:
- 让 Nginx / 网关处理 TLS
- Gin 跑在内网或容器网络里