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

How should I manage postgres database handles in a serverless environment?

我在 AWS Lambda 和 AWS 网关中有一个 API 运行,使用 Up. My API creates a database connection on startup, and therefore Lambda does this when the function is triggered for the first time. My API is written in node using Express and pg-promise 连接和查询数据库。

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

我将 运行 排除在数据库连接之外,因为我的 Lambda 函数用完了太多数据库句柄。如果我登录到 Postgres 并查看 pg_stat_activity table,我可以看到很多与数据库的连接。

解决此问题的推荐模式是什么?可以限制 Lambda 中函数的同时实例数吗?你能在一个函数的实例之间共享一个连接池吗(我怀疑)。

更新

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

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

  1. 您可以调整 Postgres 以断开那些空闲连接。这是最好的方法,但可能需要一些 trial-and-error.

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

有几种方法可以 运行 脱离数据库连接:

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

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

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

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

另一种选择是仔细控制您的 client-side 和 server-side 连接参数。这个想法首先是让数据库在相对较短的空闲时间后关闭连接(在 PostgreSQL 上,这由 tcp_keepalives_* 设置控制)。然后,为确保客户端永远不会尝试使用已关闭的连接,您可以在客户端上设置一个短于该值的连接超时(如何设置取决于框架)。

我希望 AWS 会在某个时候为我们提供解决方案(例如 server-side RDS 连接池)。您可以在 AWS forum thread.

中看到各种建议的解决方案