mysql - 通过 Heroku 到 AWS 对等连接的 RDS MySQL 连接超时

标签 mysql node.js heroku amazon-rds amazon-vpc

我在尝试从 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/

相关文章:

php - 我可以在 PHP 中混合使用 MySQL API 吗?

javascript - 在 Node.js 中重新定义 "Object"关键字

heroku - 获取过去几周的 Heroku 日志

heroku - Q : Google OAuth 2 Error 400: redirect_uri_mismatch but redirect uri is compliant and already registered in Google Cloud Console

mysql - 如何创建MySQL分层递归查询

MySQL SUM、INNER JOIN 和 GROUP BY 在同一条语句中。语法错误

javascript - 当使用客户端函数填充 DOM 时,如何等待从 page.evaluate 中的 page.evaluate 函数加载所有图像

css - Rails 5 - 用户指定的 CSS 在具有自定义域的 Heroku 上不起作用

php - Codeigniter 允许在插入查询中使用单引号

json - 在 Node.js 中从 URL 检索 JSON 的最佳方法是什么