生产环境中Sequelize与MySQL出现connect ETIMEDOUT连接超时问题求助
问题排查方向:Express+Sequelize生产环境偶发连接超时(ETIMEDOUT)
核心问题总结
PM2集群模式(8实例)下,生产环境服务器偶尔出现全请求抛出ConnectionError [SequelizeConnectionError]: connect ETIMEDOUT,持续数分钟自动恢复,开发环境正常,已调整MySQL和Sequelize连接池配置但未解决。
排查方向
1. PM2集群与Sequelize连接池的资源冲突
每个PM2实例都会独立维护一个Sequelize连接池,当前配置每个池max: 100,8个实例总连接池上限为800。结合MySQLmax_connections=1600看似有冗余,但需注意:
- MySQL会预留约10%的连接给超级用户(如root),实际可用连接数约1440,若业务高峰期连接接近上限,会导致新请求无法获取连接触发超时。
- 连接池参数配置不合理:
acquire: 1000000(16分钟)过长,请求会长时间等待空闲连接,导致连接堆积;建议缩短为30000(30秒)。idle: 100000(约27小时)过长,空闲连接长期占用资源且易因网络/MySQL配置失效;建议改为60000(1分钟)。evict: 2000(2秒)过短,频繁清理空闲连接会增加额外开销;建议改为60000(1分钟),与idle匹配。
- 建议降低单实例连接池上限:将每个实例的
max调整为50,总上限400,给MySQL预留足够缓冲空间。
2. MySQL连接超时与存活机制问题
MySQL默认的wait_timeout和interactive_timeout为8小时,若连接长时间空闲,MySQL会主动断开,但Sequelize连接池可能未感知到失效连接,导致请求使用失效连接触发超时:
- 检查MySQL配置:执行
show variables like '%timeout';,确保wait_timeout和interactive_timeout设置合理(如300秒)。 - 给Sequelize添加连接存活检测:
dialectOptions: { decimalNumbers: true, enableKeepAlive: true, keepAliveInitialDelay: 30000, connectTimeout: 10000 // 连接超时时间缩短为10秒 }, pool: { // ... 原有配置 testOnBorrow: true, // 借连接前测试可用性 testWhileIdle: true, // 空闲时测试连接 idle: 60000, evict: 60000 }
3. MySQL资源瓶颈排查
虽然服务器硬件规格充足,但MySQL本身的资源配置可能不足:
- 当前
innodb_buffer_pool_size=4G,对于64GB内存的服务器,建议调整为32G(约内存的50%~70%),提升InnoDB缓存能力,减少磁盘IO开销,避免因MySQL响应过慢导致连接超时。 - 问题发生时,执行
show processlist;查看连接状态:- 是否有大量
Sleep状态的连接?说明连接未及时释放。 - 是否有
Locked或Waiting for table metadata lock等阻塞状态?会导致连接排队超时。
- 是否有大量
- 查看MySQL错误日志(通常在
/var/log/mysql/error.log),检查是否有连接拒绝、资源耗尽的报错信息。
4. 网络与环境层面排查
- 若MySQL与应用服务器分离,检查两者之间的网络稳定性:是否存在偶尔的网络抖动、防火墙/安全组临时拦截连接?可通过
ping、traceroute工具在问题发生时测试连通性。 - 检查服务器的CPU、内存、带宽使用率:问题发生时是否有资源峰值?比如PM2实例过多导致CPU满载,或MySQL磁盘IO过高(可通过
top、iostat命令查看)。
5. PM2集群模式的额外检查
- 确保PM2的集群模式未导致端口占用或资源竞争:执行
pm2 monit查看各实例的CPU、内存使用情况,是否有某几个实例异常占用资源。 - 避免在PM2集群实例中共享数据库连接(Sequelize默认每个实例独立创建池,这是正确的,但需确保配置一致)。
内容的提问来源于stack exchange,提问作者Gamaliel Castro
相关产品推荐
相关产品推荐

