如何在无服务器环境中管理 postgres 数据库句柄?



我有一个使用 Up 在 AWS Lambda 和 AWS Gateway 中运行的 API。我的 API 在启动时创建数据库连接,因此 Lambda 会在首次触发函数时执行此操作。我的 API 是使用 Express 和 pg-promise 在节点中编写的,用于连接和查询数据库。

问题在于 Lambda 会根据需要创建函数的新实例,有时看起来好像一次有多个函数实例。

由于我的 Lambda 函数占用了太多数据库句柄,我的数据库连接数不断用完。如果我登录Postgres并查看pg_stat_activity表,我可以看到很多与数据库的连接。

解决此问题的建议模式是什么?是否可以限制 Lambda 中函数的同时实例数?您能否在函数实例之间共享连接池(我对此表示怀疑)。

更新

AWS现在提供了一个名为RDS Proxy的产品,这是一种托管连接池解决方案,可以解决此问题:https://aws.amazon.com/blogs/compute/using-amazon-rds-proxy-with-aws-lambda/

有几种方法可能会耗尽数据库连接:

  1. 您的并发 Lambda 执行数多于可用的数据库连接数。这当然是可能的。
  2. 您的 Lambda 函数正在打开数据库连接,但未关闭它们。这可能是罪魁祸首,因为 Web 框架倾向于在请求之间保持数据库连接打开(效率更高),但在 Lambda 上没有机会关闭它们,因为 AWS 会静默终止实例。

您可以通过控制数据库服务器上的可用连接数(PostgreSQL 上的max_connections设置)和并发 Lambda 函数调用的最大数量(如此处所述)来解决 1。当然,这只是用一个问题换另一个问题,因为 Lambda 在达到限制时会返回 429 个错误。

寻址 2 更棘手。处理数据库连接耗尽的传统和正确方法是使用连接池。但是使用 Lambda,您无法在客户端上执行此操作,而对于 RDS,您无法选择在服务器上执行此操作。您可以设置中间持久连接池,但这会使设置更加复杂。

在没有池化的情况下,一种选择是在每次函数调用时创建和销毁数据库连接。不幸的是,这将为您的请求增加相当多的开销和延迟。

另一种选择是仔细控制客户端和服务器端连接参数。这个想法是首先让数据库在相对较短的空闲时间后关闭连接(在PostgreSQL上,这是由tcp_keepalives_*设置控制的)。然后,为了确保客户端永远不会尝试使用关闭的连接,请在客户端上设置一个短于该值的连接超时(如何执行此操作将取决于框架)。

我希望AWS会在某个时候为我们提供解决方案(例如服务器端RDS连接池)。您可以在此 AWS 论坛帖子中看到各种建议的解决方案。

您有两种选择可以解决此问题:

  1. 您可以调整 Postgres 以断开这些空闲连接。这是最好的方法,但可能需要一些反复试验。

  2. 您必须确保连接到处理程序中的数据库,并在函数返回或退出之前断开连接。在express中,您必须在路由处理程序中连接/断开连接。

相关内容

  • 没有找到相关文章

最新更新