部署在Heroku上的NodeJS/Express应用访问ClearDb MySQL数据库超时问题求助
我正尝试把搭载MySQL数据库的React/NodeJS/Express应用部署到Heroku(使用免费dynos),生产环境采用ClearDb的"Punch"授权级别托管MySQL数据库,通过mysql2 npm包的连接池实现数据库连接。目前应用已部署成功,Heroku staging环境中可正常显示登录界面,但当应用执行首个数据库查询时,等待10秒后日志中出现以下错误信息:
2021-08-30T15:04:44.867293+00:00 app[web.1]: executing DB query
2021-08-30T15:04:54.877125+00:00 app[web.1]: Error: connect ETIMEDOUT
2021-08-30T15:04:54.877132+00:00 app[web.1]: at /app/server/common/db.js:27:19
2021-08-30T15:04:54.877133+00:00 app[web.1]: at processTicksAndRejections (internal/process/task_queues.js:95:5)
该查询逻辑非常简单,且数据库内数据极少,仅针对不到20行数据的表执行操作。
我已进行以下尝试:
- 本地运行的应用连接ClearDb生产实例,可正常工作;
- 通过MySQL Workbench连接ClearDb生产实例,可正常工作;
- 搭建了执行
select 1查询的简单健康检查端点,日志中仍出现上述相同错误。
以下是我的数据库连接代码(应用正式上线前会迁移至SSL连接):
const mysql = require('mysql2/promise') const config = { host: process.env.DB_HOSTNAME, port: process.env.DB_PORT, user: process.env.DB_USERNAME, password: process.env.DB_PASSWORD, insecureAuth : true, database: process.env.DB_NAME, timezone:'+00:00' }; const pool = mysql.createPool(config)
排查与解决方案
我之前帮朋友处理过几乎一模一样的问题,给你几个实用的排查方向和解决办法:
1. 先确认Heroku环境变量完全正确
别小看拼写错误!有时候部署时环境变量没同步全,或者像DB_PORT写成DB_PROT这种低级失误,都会导致连接失败。你可以用Heroku CLI直接查看当前应用的环境变量:
heroku config:get DB_HOSTNAME DB_PORT DB_USERNAME DB_NAME -a 你的应用名称
把这些值和本地能正常连接的配置逐一对比,确保完全一致,尤其是端口号(ClearDB默认是3306,别乱改)。
2. 给连接池加上超时和重试配置
免费的Heroku dyno和ClearDB Punch实例偶尔会有网络波动,默认的连接池配置可能没处理这种情况。你可以给配置加几个参数,让连接池更“耐造”:
const config = { // 保留你原有的配置项... connectTimeout: 5000, // 把连接超时缩短到5秒,不用等10秒才报错 acquireTimeout: 5000, waitForConnections: true, connectionLimit: 3, // ClearDB Punch有连接数限制(默认5个),别设太高 queueLimit: 0, retryDelay: 1000, // 超时后1秒重试 reconnect: true };
这样连接池会在超时后自动重试,而不是直接抛出错误。
3. 强制开启SSL连接试试
虽然你说上线前才弄SSL,但ClearDB的Punch实例可能要求从Heroku访问必须用SSL(本地和Workbench可能没这个限制)。你可以临时加个SSL配置测试:
const config = { // 原有的配置... ssl: { rejectUnauthorized: false // 暂时关闭证书验证,先测试是否是SSL的问题 } };
如果加了之后能正常连接,那说明必须用SSL才能从Heroku访问ClearDB,之后你再换成合法的证书验证即可。
4. 检查ClearDB的连接数是否超限
ClearDB Punch级别的最大连接数有限制,如果你应用的连接池配置过高,或者之前的连接没正常释放,可能导致新连接被拒绝。你可以登录ClearDB控制台查看当前的连接数,或者把连接池的connectionLimit设得更低(比如2)试试。
5. 重启Heroku dyno
有时候dyno的网络状态会莫名其妙出问题,重启一下说不定就好了:
heroku restart -a 你的应用名称
内容的提问来源于stack exchange,提问作者havab

