我们如何在AWS Lambda中使用JDBC连接池?

Sum*_*ora 12 amazon-web-services aws-lambda

我们可以在AWS Lambda中使用JDBC连接池吗?AS AWS lambda函数在特定事件上被调用,因此即使在完成其中一个调用之后它的生命周期仍然存在?

And*_*iak 13

从技术上讲,您可以在处理程序函数之外创建一个连接池,但由于每次调用只能使用任何一个连接,所以您要做的就是占用数据库连接并分配一个您只能使用的池.使用1.

将Lambda函数上传到AWS后,第一次调用它时,AWS将创建一个容器并在调用处理程序代码之前运行设置代码(处理程序函数之外的代码,创建池,比如N个连接).

当下一个请求到达时,AWS可能会再次使用该容器(或者可能不会.通常会重新使用该容器,但这取决于AWS并且不受您的控制).

假设它重用了容器,你的处理函数将被调用(设置代码将不再运行),你的函数将使用N中的一个连接到池中的数据库(在容器级别保存).这很可能是池中的第一个连接,因为它保证不被使用,所以它是第1个连接,因为两个函数不可能在同一个容器中同时运行.请继续阅读以获得解释.

如果AWS不重用容器,它将创建一个新容器,您的代码将分配另一个N连接池.根据容器的周转率,您可能会完全耗尽数据库池.

如果两个请求同时到达,AWS无法同时调用同一个处理程序.如果这是可能的,那么在容器范围级别定义的变量存在共享状态问题.相反,AWS将使用两个单独的容器,这些容器将分别分配一个N个连接池,即与数据库的2N连接.

单个调用函数永远不需要多个连接(除非您需要在同一个上下文中与两个独立的数据库进行通信).

连接池唯一有用的是它是否位于容器范围之上的某个级别,即AWS环境本身传递给容器.这是不可能的.

您可以希望的最佳情况是每个容器只有一个连接.即使这样,您也必须管理此单个连接以确保数据库服务器未断开连接或重新启动.如果是这样,您的容器的连接将会死亡,您的处理程序将永远无法再次连接(直到容器死亡),除非您在函数中编写一些代码来检查连接断开.在繁忙的服务器上,容器可能需要很长时间才能消亡.

还要记住,如果处理程序函数失败,例如事务的一半或锁定了表,则下一个请求调用将从容器中获取脏连接状态.第一次调用可能已经打开了一个事务而死了.第二次调用可以提交并包括直到失败的所有先前查询.

我建议不要在处理程序函数之外管理状态,除非您有特定的优化需求.如果这样做,则使用单个连接,而不是池.

  • 使用大小为 1 的连接池可能仍然是一个好主意,这样您就不必管理测试和替换连接的逻辑。 (5认同)

ata*_*lor 6

是的,lambda主要是持久的,因此JDBC连接池应该可以工作.第一次调用lambda函数时,将创建环境并且可能会或可能不会重用它.但实际上,如果您的触发事件经常发生,后续调用通常会重用相同的lambda进程以及所有程序状态.

这个简短的lambda函数证明了这一点:

package test;

import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;

public class TestLambda implements RequestHandler<String, String> {

    private int invocations = 0;

    public String handleRequest(String request, Context context) {
        invocations++;
        System.out.println("invocations = " + invocations);
        return request;
    }
}
Run Code Online (Sandbox Code Playgroud)

使用任何字符串作为测试事件从AWS控制台调用此方法.在CloudWatch日志中,您每次都会看到调用次数增量.

  • 不幸的是,这个答案部分不正确。池化行不通。两个并发调用将导致使用两个容器。看我下面的回答。 (3认同)

gun*_*tar 6

感谢AWS RDS 代理,现在您可以使用池化MySql和连接,而无需在您的或其他特定于 AWS Lambda 的代码postgrese中进行任何额外的配置。Java您所需要做的就是创建Add a Database proxy您想要重用/池化连接的 AWS Lambda 函数。请参阅此处的操作方法。

注意:AWS RDS 代理不包含在免费套餐中(更多信息请参见此处)。