2

我有一组处理 SQS 堆栈上的消息的 lambda 函数。他们获取数据集,对其进行处理并将结果存储在 RDS MySQL 数据库中,并通过 VPC 连接到该数据库。Lambda 函数和 RDS 数据库都在同一个可用区中。

在过去的几个月里,这一直有效,没有任何问题,但是今天凌晨 (2019-01-12) 01:00,我开始看到 lambda 超时和消息被移入死信队列。

我进行了一些故障排除并确认超时的原因是 Lambda 无法建立与数据库服务器的连接。

RDS 服务器是公共的,但被锁定以仅允许通过 VPC 和 2 个公共 IP 进行访问。

到目前为止,我已采取以下步骤来尝试解决问题:

  • 给定 lambda 服务角色管理员权限以排除 IAM 问题
  • 从 lambda 函数中取消分配 VPC 并从 0.0.0.0/0 打开 RDC 入站访问以排除 VPC 问题。
  • 重新启动 RDS 主机,再次开启良好状态。
  • 使用无服务器通过测试数据在本地调用 lambda 函数(有效)。我的本地计算机连接到公共 RDS IP,而不是通过 VPC。
  • 将运行时环境从 3.6 更改为 3.7

这似乎不是代码问题,因为在过去的几个月中它一直在完美运行,我可以毫无问题地在本地调用,而位于同一 VPC 子网上的 Elastic Beanstalk 实例继续通过 VPC 连接而没有问题。

这是我用来连接的代码:

connectionString = 'mysql+pymysql://{0}:{1}@{2}/{3}'.format(os.environ['DB_USER'], os.environ['DB_PASSWORD'], os.environ['DB_HOST'], os.environ['DB_SCHEMA'])
        engine = create_engine(connectionString, poolclass=NullPool)
        with engine.connect() as con: <--- breaking here
            meta = MetaData(engine, reflect=True) <-- never gets to here

我仔细检查了连接字符串和用户帐户,两者都是正确的/在本地工作。

如果有人能指出我正确的方向,我将不胜感激!

4

2 回答 2

0

所以...

我正在更改安全组,但它对 RDS 主机没有影响,有一次我删除了所有访问权限,但我仍然可以连接,这太疯狂了。此时我开始认为周五晚上的中断使底层 RDS 主机进入了一个奇怪的状态。我将安全组恢复到应有的状态,停止并启动(重新启动无效)RDS 主机,一切又开始工作。

非常沮丧,但很高兴它终于解决了。

于 2019-01-13T13:15:02.027 回答
0

我的第一个猜测是您已达到 RDS 数据库的连接限制。因为 Lambda 可以并发执行(如果 SQS 队列中突然出现大量消息,很容易出现这种情况),并且每次执行都会打开一个与数据库的新连接,因此连接池可能会饱和。

如果是这种情况,您可以在 Lambda 函数上设置并发执行限制以防止这种情况发生。

附注 - 正是出于这个原因,不建议在无服务器架构中使用具有持久连接的数据库。AFAIK,AWS 正在开发一个更好的解决方案来使用来自 Lambda 的 RDS,但它尚不可用。

于 2019-01-12T18:27:56.803 回答