全书目录

第三十二篇:Gin 完全指南 —— 高速交警中枢宇宙

第十二章:真正上线时别只会 `Run()` —— 生产环境要像正规中枢,不像临时岗亭

2 分钟 559 字 第 603 / 962 个阅读单元

r.Run(":8080") 很方便,但生产里你往往需要更细的服务配置。

#1. Gin 本质上就是一个 http.Handler

这件事一定要吃透。

go
srv := &http.Server{
    Addr:           ":8080",
    Handler:        r,
    ReadTimeout:    10 * time.Second,
    WriteTimeout:   10 * time.Second,
    MaxHeaderBytes: 1 << 20,
}

log.Fatal(srv.ListenAndServe())

这说明:

text
Gin 不是替代 net/http
而是站在 net/http 上面,自己就是一个可交给 http.Server 的 Handler
#2. 为什么生产更常自己建 http.Server

因为你要控制:

  • 读超时
  • 写超时
  • Header 限制
  • TLS
  • 优雅停机
  • 自定义监听方式
#3. 优雅停机

真实中枢下班不能粗暴拉闸。

go
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)
}()

它的心智是:

text
收到停机通知
  │
  ▼
不再接新车
  │
  ▼
让站内正在处理的车尽量办完
  │
  ▼
再平稳关门
#4. 反向代理场景下的 TrustedProxies

这是 Gin 生产安全里非常容易被忽略的一条。

如果你的服务跑在:

  • Nginx 后面
  • 负载均衡后面
  • 云网关后面
  • CDN 后面

那客户端 IP 往往来自 X-Forwarded-For 一类 header。

问题是:
这些 header 不是天然可信的。

Gin 官方明确提醒过:如果你不配置可信代理,默认信任所有代理是不安全的。

go
if err := r.SetTrustedProxies([]string{"10.0.0.0/8", "192.168.1.0/24"}); err != nil {
    log.Fatal(err)
}

如果你根本没用代理,反而应该显式关掉:

go
if err := r.SetTrustedProxies(nil); err != nil {
    log.Fatal(err)
}

别小看这件事。它直接影响:

  • ClientIP()
  • 基于 IP 的权限控制
  • 基于 IP 的限流
  • 审计日志可信度
#5. HTTPS 与自动证书

Gin 官方还维护了 autotls 方案,可以比较顺手地接 Let’s Encrypt。
不过真正生产上,你更常见的路线仍然是:

  • 让 Nginx / 网关处理 TLS
  • Gin 跑在内网或容器网络里