MongoDB执行操作后Express服务器崩溃问题求助
我来帮你排查这个棘手的问题,结合你的场景,咱们从几个核心方向入手分析:
1. 先修复Mongoose连接的配置问题
你当前用的useMongoClient是Mongoose 4.x版本的旧配置项,在5.x及以上版本已经被废弃了!这种过时的连接参数很可能导致驱动和MongoDB服务器之间的连接不稳定,当TTL后台清理任务执行时,就容易触发连接断开,进而引发socket hang up错误。
建议把连接代码改成对应Mongoose版本的正确配置:
// Mongoose 5.x版本写法 mongoose.connect("mongodb://127.0.0.1/wisehome", { useNewUrlParser: true, useUnifiedTopology: true, useCreateIndex: true // 确保索引能正确创建 }) .then(() => console.log('MongoDB连接成功')) .catch(err => console.error('MongoDB连接失败:', err)); // 如果是Mongoose 6+版本,上述选项默认已启用,可以简化为: mongoose.connect("mongodb://127.0.0.1/wisehome") .then(() => console.log('MongoDB连接成功')) .catch(err => console.error('MongoDB连接失败:', err));
2. 放弃第三方TTL包,改用Mongoose原生TTL支持
mongoose-ttl这个包其实底层也是封装了MongoDB的TTL索引,但它的维护可能跟不上Mongoose的版本迭代,容易出现兼容性问题。推荐直接用Mongoose内置的TTL索引定义,更稳定可靠:
const weatherMeasurementsSchema = Schema({ parentRoomId: { type: Schema.Types.ObjectId, ref: "Room" }, temperature: Number, humidity: Number, createdAt: { type: Date, default: Date.now, // 自动设置文档创建时间 expires: 60 // 文档创建60秒后自动过期删除 } });
这样Mongoose会自动帮你创建正确的TTL索引,不需要手动执行db.measurements.createIndex命令,也避免了第三方包的潜在问题。
3. 给MongoDB连接添加错误监听,避免服务器崩溃
socket hang up本质是驱动的连接被意外断开,如果没有捕获这类错误,就会导致整个Express进程崩溃。给Mongoose连接加上错误监听,优雅处理异常:
const db = mongoose.connection; db.on('error', (err) => { console.error('MongoDB连接异常:', err); // 这里可以添加重连逻辑,比如延迟几秒后重新连接 }); db.on('disconnected', () => { console.log('MongoDB连接已断开,尝试重新连接...'); setTimeout(() => mongoose.connect("mongodb://127.0.0.1/wisehome"), 3000); });
4. 检查MongoDB服务器本身的状态
TTL索引的清理是MongoDB后台线程定期执行的(默认60秒一次),如果你的MongoDB服务器出现以下情况,也可能导致连接异常:
- 磁盘空间不足,无法执行删除操作
- 服务器资源耗尽(CPU/内存过高),导致后台任务阻塞
- 日志中有索引相关的错误
你可以查看MongoDB的日志文件(默认路径/data/db/mongod.log),看看在TTL执行清理时有没有报错信息,同时用db.measurements.getIndexes()命令确认TTL索引是否正确创建。
总结调整步骤
- 更新Mongoose连接配置到对应版本的正确参数
- 替换第三方TTL包为Mongoose原生的
expires字段定义 - 添加MongoDB连接的错误监听和重连逻辑
- 检查MongoDB服务器的运行状态和日志
按照这个流程调整后,应该能解决socket hang up导致服务器崩溃的问题。
内容的提问来源于stack exchange,提问作者Aleksander Sadaj

