我在尝试从 Heroku 建立连接时看到间歇性连接超时 one-off dyno通过 Heroku 的 Private Space Peering Connection 到一个 MySQL RDS 实例.错误是 ETIMEDOUT
使用 Node 时出错 mysql2图书馆。它以大约 1/100 次尝试的频率发生,没有一天中时间的模式。还值得注意以下几点:
- 这是一个暂存环境,流量极少,因此 RDS 指标基本持平。资源争用可能不是问题所在。 CPU 徘徊在 1%,IOPS 可以忽略不计,连接数 <10,存储和内存配置过剩。
- 此错误仅在我切换到使用对等连接而不是通过公共(public)互联网连接到数据库时才开始发生。
- 在运行时间较长的进程上使用连接池时,我没有看到此错误。
- MySQL 错误日志是干净的
这些是我调查并排除的潜在问题:
- 通过正确的对等连接使用 10.0.0.0/16 (Heroku CIDR) 的所有 RDS 子网都存在 VPC 路由
- 在子网级别应用的网络 ACLS 对所有 RDS 子网都是 ANY/ANY
- RDS 允许通过 10.0.0.0/16 (Heroku CIDR) 的入口流量
- DNS 解析适用于对等连接
当前的 MySQL 连接配置使用默认的 10000 连接超时。我在不了解根本原因的情况下犹豫是否提出这个问题,因为 10 秒应该足以建立连接。下面是连接和断开连接的代码:
const mysql = require('mysql2/promise');
// Heroku dyno boots up via the scheduler add-on
const connection = await mysql.createConnection({
timezone: '+00:00',
dateStrings: ['DATE', 'DATETIME'],
decimalNumbers: true,
host: process.env.MYSQL_HOST,
database: process.env.MYSQL_DATABASE,
user: process.env.MYSQL_USER,
password: process.env.MYSQL_PASSWORD,
port: parseInt(process.env.MYSQL_PORT, 10),
ssl: fs.readFileSync('...', 'utf8')
});
// Do some work
await connection.end();
// Heroku dyno is torn down
很难深入了解 Heroku 私有(private)空间方面的事情,因为它太抽象了,但有人见过这种问题吗?
更新 1
能够在一次性 dynos 上安装一些工具,并且可以成功地远程登录并连接到 mysql 客户端,尽管从 Node mysql 库中获得超时。所以看起来 Node mysql2 lib 在运行这些命令时没有超时。为什么会这样?
# prints Connected to [HOST]. Escape character is '^]'.
$ echo -e '\x1dclose\x0d' | telnet ${process.env.MYSQL_HOST} ${process.env.MYSQL_PORT}
# prints 8.0.17
$ echo "SELECT VERSION() AS version" | mysql -h ${process.env.MYSQL_HOST} -u ${process.env.MYSQL_USER} -p${process.env.MYSQL_PASSWORD}
更新 2
当我们看到超时时,我梳理了 RDS ENI 的流日志,我看到流量来自经历超时的机器的 IP。这确认了来自 debug telnet <HOST> <PORT>
的流量和 mysql -h <HOST> ...
命令正确执行。
最佳答案
这不是一个令人满意的答案,但考虑到 Heroku 的黑盒性质,这就是我们得到的全部。我们的数据库托管在与我们的 Heroku dynos 不同的区域。将它们置于同一个 AWS 区域解决了这个问题。
关于mysql - 通过 Heroku 到 AWS 对等连接的 RDS MySQL 连接超时,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64880895/