必须手动集成 mongo-go-driver,Iris 不提供 MongoDB 封装;需在 main() 中用带超时的 context 创建全局 mongo.Client,启动时 Ping 验证,退出前 Disconnect;连接串应设 maxPoolSize/minPoolSize;handler 中通过闭包或 DI 注入 mongo.Collection,禁用 ctx.Values() 存储;所有 DB 操作须用请求上下文并设操作级超时,同时配置 serverSelectionTimeoutMS 和 maxIdleTimeMS。

必须手动集成 mongo-go-driver,Iris 不提供任何 MongoDB 封装或自动连接能力——硬连是唯一路径。
启动时建立全局复用的 *mongo.Client
Iris 本身不管理数据库生命周期,*mongo.Client 必须在 main() 启动阶段创建一次,并作为全局变量或 DI 容器实例持有。反复在 handler 中调用 mongo.Connect() 会导致连接池爆炸、FD 耗尽、DNS 频繁解析。
- 用
context.WithTimeout(context.Background(), 10*time.Second)包裹连接上下文,避免因网络卡死阻塞服务启动 - 连接后立即执行
client.Ping(ctx, readpref.Primary()),否则错误会延迟到首次查询才暴露(比如认证失败、副本集不可达) - 注册
os.Interrupt信号监听,在退出前调用client.Disconnect(ctx);Iris 没有内置关机钩子,漏掉这步会导致连接残留甚至 Atlas 账单异常 - 连接字符串里建议显式指定
maxPoolSize和minPoolSize(例如&maxPoolSize=20&minPoolSize=5),避免默认 100 连接在低并发服务中浪费资源
handler 中安全传入 *mongo.Collection
别在每个路由函数里写 client.Database("db").Collection("coll")——它虽轻量,但字段名拼错、DB 名硬编码、测试难 mock、切换分库逻辑散落各处。
- 初始化时就构造好:比如
usersColl := db.Collection("users"),然后通过闭包注入:app.Get("/users", userHandler(usersColl)) - 若用 DI 风格,需启用
app.ConfigureContainer(),注册*mongo.Collection类型,再在 handler 签名中声明接收:func(ctx iris.Context, coll *mongo.Collection) - 绝对不要用
ctx.Values().Set()存 collection 实例——值类型不安全,中间件可能覆盖,且无法被 DI 容器管理或生命周期控制
所有 DB 操作必须使用请求上下文
传 context.Background() 是最常见也最危险的写法:HTTP 请求已断开,MongoDB 查询还在后台跑,连接池被占满,超时机制完全失效。
- 从
iris.Context提取真实请求上下文:reqCtx := c.Request().Context() - 按操作粒度加超时,例如查询用户:
ctx, cancel := context.WithTimeout(reqCtx, 5*time.Second),之后务必defer cancel() -
Find、InsertOne、UpdateByID、Aggregate全部接口都要求传context.Context,漏一个就埋雷 - 聚合管道等耗时操作,建议额外加
context.WithDeadline或结合cursor.All(ctx, &results)的 ctx 控制整体生命周期
最容易被忽略的是连接字符串里的 serverSelectionTimeoutMS 和 maxIdleTimeMS:前者决定发现故障节点要等多久,后者影响 NAT/防火墙下空闲连接是否被悄无声息地干掉。线上环境不设这两个值,偶尔的网络抖动就会让整批请求 hang 30 秒以上。


















