必须显式配置 Timeout 字段,否则 middleware.TimeoutWithConfig 会 panic;超时后原 handler 中的 DB 写入、HTTP 调用等操作不会自动中断或回滚,需手动检查 ctx.IsAborted() 或监听 ctx.Context().Done() 做清理。

必须显式配置 Timeout 字段,否则 middleware.TimeoutWithConfig 会 panic;超时后原 handler 中的 DB 写入、HTTP 调用等操作不会自动中断或回滚,需手动检查 ctx.IsAborted() 或监听 ctx.Context().Done() 做清理。
全局注册 Timeout 中间件要填满 Timeout 字段
你不能只传空结构体 {},Fiber 会直接 panic。必须给 Timeout 字段赋值,单位是 time.Duration:
-
app.Use(middleware.TimeoutWithConfig(middleware.TimeoutConfig{Timeout: 5 * time.Second}))—— 最简可用写法 - 可选加
ErrorMessage和StatusCode自定义响应,比如ErrorMessage: "Slow operation rejected"+StatusCode: http.StatusRequestTimeout - 若漏掉
Timeout:这一行,运行时报错:panic: timeout config requires Timeout field to be set
按路由组差异化设超时,每个 Group 都要单独 Use()
Fiber 的子路由组(app.Group("/api"))不继承父级中间件,也不会共享超时配置。每个 Group 必须独立挂载 Timeout:
-
api := app.Group("/api")→api.Use(middleware.TimeoutWithConfig(...)) -
upload := app.Group("/upload")→upload.Use(middleware.TimeoutWithConfig(middleware.TimeoutConfig{Timeout: 10 * time.Minute})) - 注意:
app.Use()后再建 Group 并调用Use(),新中间件只对该 Group 生效,不影响其他路径
超时触发后,DB/IO 不会自动停止,必须手动干预
Timeout 中间件只是“在超时时刻返回 HTTP 响应”,它不会 kill 当前 goroutine,更不会 cancel 正在执行的数据库查询或 HTTP 请求:
- 你在 handler 里调用了
db.Exec("UPDATE ..."),超时后这条 SQL 仍可能继续执行并最终提交 - 正确做法是在 handler 开头创建带超时的 context:
ctx, cancel := context.WithTimeout(c.Context(), 3*time.Second),然后立刻defer cancel() - 所有下游操作必须显式传入该
ctx:比如db.QueryRowContext(ctx, ...)、httpc.Do(req.WithContext(ctx)) - 别依赖
c.Context()的Done()—— Fiber 底层用的是 fasthttp,它的c.Context()只反映连接关闭,不反映业务超时
常见失效写法:看似加了 timeout,其实完全没用
很多写法在日志里看不出问题,但实际超时逻辑形同虚设:
- 在 goroutine 内部才调用
context.WithTimeout→ 超时只杀 goroutine,主 handler 仍在跑 - 用
db.QueryRow(...)而非db.QueryRowContext(ctx, ...)→ 数据库驱动根本无视你的 ctx - 在超时后还调用
c.SendString(...)→ 连接可能已被复用或关闭,导致 panic 或静默失败 - 误以为
c.Next()或中间件链能感知超时 → 它们对Timeout中间件的触发完全无感
最易被忽略的一点:Fiber 的 Timeout 是纯 HTTP 层控制,它和底层 fasthttp 的连接复用模型深度耦合——你不主动注入可取消 context 并传递到底层 IO,就永远无法真正中断耗时操作。这和 net/http 的 request.Context 行为完全不同,不能凭经验迁移。


















