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

时间:2018-03-08 16:08:30

标签: postgresql aws-lambda serverless

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

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

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

解决此问题的推荐模式是什么?可以限制Lambda中函数的同时实例数吗?你可以跨函数的实例共享连接池(我对此表示怀疑)。

2 个答案:

答案 0 :(得分:3)

有几种方法可以用完数据库连接:

  1. 与可用的数据库连接相比,您有更多的并发Lambda执行。这当然是可能的。
  2. 您的Lambda函数正在打开数据库连接但不关闭它们。这可能是罪魁祸首,因为Web框架倾向于保持数据库连接在请求之间保持开放(这样更有效),但Lambda没有机会关闭它们,因为AWS将以静默方式终止实例。
  3. 您可以通过控制数据库服务器上的可用连接数(PostgreSQL上的max_connections设置)和最大并发Lambda函数调用数(如记录here)来解决1。当然,这只会将一个问题换成另一个问题,因为Lambda在达到限制时会返回429个错误。

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

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

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

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

答案 1 :(得分:0)

您有两种方法可以解决此问题:

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

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

相关问题