AWS NLB后MongoDB连接间歇性超时问题求助
问题场景
当前架构:Mongo客户端 → AWS内部TCP网络负载均衡器(NLB) → Traefik反向代理 → MongoDB(docker镜像mongo:4.4.17)
使用Node.js测试脚本连接时出现间歇性失效:多次正常执行db.find()后突然挂起,MongoDB日志仅显示客户端因超时断开,无其他异常;但直接连接Traefik或MongoDB实例时无此问题,故障定位为NLB相关。
核心原因分析
AWS NLB的TCP连接默认空闲超时为350秒,若客户端与NLB之间的连接长时间无数据交互,NLB会主动断开连接。而MongoDB Node.js客户端默认未启用TCP keep-alive机制,无法及时感知连接已断开,导致后续请求因无效连接挂起。
解决方案
1. 客户端侧配置TCP保活
在MongoDB连接字符串或客户端配置中添加保活参数,确保连接在NLB超时前持续发送心跳:
const client = new MongoClient(uri, { keepAlive: true, keepAliveInitialDelay: 300000, // 5分钟,小于NLB默认350秒 socketTimeoutMS: 600000, // 延长套接字超时,避免误判 connectTimeoutMS: 30000 });
2. 调整NLB空闲超时时间
在AWS控制台修改NLB的TCP监听超时设置,将空闲超时调整为更长时间(如1小时),匹配业务场景的连接空闲需求。
3. 验证Traefik连接配置
确保Traefik的TCP转发超时设置与NLB、MongoDB客户端保持一致,避免中间层提前断开连接:
- 检查Traefik的
timeout配置(针对TCP服务),确保不小于NLB的超时时间。
相关日志与测试代码
MongoDB超时日志片段
202X-XX-XXT12:34:56.789+0000 I NETWORK [conn123] client caused connection to close: connection timed out
202X-XX-XXT12:34:56.790+0000 I NETWORK [listener] connection accepted from 10.0.0.123:45678 #124 (5 connections now open)
Node.js测试脚本
const { MongoClient } = require('mongodb'); // 使用NLB端点连接 const uri = 'mongodb://internal-nlb-endpoint:27017/testdb?directConnection=true'; // 未配置保活的原客户端实例(会触发问题) const client = new MongoClient(uri); async function runTest() { try { await client.connect(); console.log('Connected to MongoDB via NLB'); const db = client.db('testdb'); const col = db.collection('test_data'); // 循环查询+长时间空闲,模拟触发NLB超时 for (let i = 0; i < 10; i++) { const docs = await col.find({}).limit(5).toArray(); console.log(`[${i}] Query returned ${docs.length} documents`); // 等待400秒(超过NLB默认350秒超时) await new Promise(resolve => setTimeout(resolve, 400000)); } } catch (err) { console.error('Error occurred:', err); } finally { await client.close(); } } runTest();
内容的提问来源于stack exchange,提问作者jsharpe

