MongoDB连接超时主因是serverSelectionTimeoutMS而非connectTimeoutMS,它控制驱动从多个节点选择可用服务器的总时限,默认30秒,超时抛MongoServerSelectionError;需结合DNS、白名单、防火墙及连接数排查根本问题。

能连上,但连不上生产环境或反复断连,大概率不是代码写错了,而是连接参数、网络策略或连接池配置没对。
mongoose.connect() 的基本用法和必填参数
最简连接只需要 mongodb:// 或 mongodb+srv:// 开头的 URI 和一个 options 对象。URI 必须包含数据库名(如 mydb),否则 Mongoose 会默认连到 test 库,而你可能根本没建这个库。
-
uri中用户名密码需 URL 编码(比如@要写成%40),否则connect()会静默失败 -
useNewUrlParser: true和useUnifiedTopology: true必须设为true,旧版驱动在 Node.js 14+ 会报错或超时 - 推荐显式传
dbName选项,避免 URI 里带库名导致切换环境时出错
mongoose.connect('mongodb+srv://user:pass%40host@cluster.net/mydb', {
dbName: 'mydb',
useNewUrlParser: true,
useUnifiedTopology: true,
serverSelectionTimeoutMS: 5000
});
连接失败时常见的错误信息和对应排查点
看到 Server selection timed out after 30000 ms 不代表 MongoDB 挂了,更可能是网络不通或 DNS 解析失败;Authentication failed 多半是密码没 URL 编码,或用户没被授权访问目标库。
-
MongoNetworkError: connect ECONNREFUSED→ 检查本地是否启动mongod,或云服务是否开了白名单 IP -
MongoParseError: Invalid connection string→ URI 格式错,常见于漏掉mongodb://前缀、多写了斜杠、端口写成字符串 -
Topology was destroyed→ 通常发生在连接未关闭就调mongoose.disconnect(),或多次重复调connect()
如何安全复用连接而不是每次新建
Mongoose 默认全局单例,mongoose.connect() 第一次调用建立连接,后续再调只是返回已有连接的 Promise。但如果你在多个文件里都写了 require('./db') 并执行 connect(),又没加防重逻辑,就会触发警告甚至连接泄漏。
- 把连接逻辑封装进一个模块,导出
mongoose.connection,其他地方只require它 - 加个
if (mongoose.connections[0].readyState)判断,避免重复 connect - 不要在 model 文件里直接
connect(),model 只负责定义 schema,连接由入口文件统一管
连接池和超时参数的实际影响
maxPoolSize 默认是 100,开发机跑得动,但小内存 VPS 上开太高反而容易 OOM;socketTimeoutMS 设太短(比如 500ms)会导致慢查询直接断连,设太长(如 30s)会让故障恢复变慢。
- 生产环境建议设
maxPoolSize: 10~20,配合应用实例数调整 -
connectTimeoutMS控制握手时间,一般 3000~5000ms 足够;serverSelectionTimeoutMS控制选节点时间,别超过 10s - 如果用 MongoDB Atlas,务必加上
retryWrites=true&w=majority查询参数,否则写操作可能不满足一致性要求
真正麻烦的不是连不上,而是连上了却因为连接池耗尽、超时设置不合理、或没监听 error / disconnected 事件,在凌晨三点 quietly fail。这些细节不写进日志,光看代码根本看不出问题。


















