我们可以在AWS Lambda中使用JDBC连接池吗? AS AWS lambda函数会在特定事件中被调用,因此即使在完成其中一个调用之后它的生命周期仍然存在吗?
答案 0 :(得分:10)
没有。从技术上讲,您可以在处理函数之外创建一个连接池,但由于每次调用只能使用任何一个连接,所以您要做的就是占用数据库连接并分配一个您只能使用的池1
将Lambda函数上传到AWS后,第一次调用它时,AWS将创建一个容器并在调用处理程序代码之前运行设置代码(处理程序函数之外的代码,用于创建池,比如N个连接)
当下一个请求到达时,AWS可能会再次使用该容器(或者可能不会。通常会重新使用该容器,但这取决于AWS并且不受您的控制)。
假设它重用了容器,你的处理函数将被调用(设置代码将不再次运行),你的函数将使用N中的一个从池中连接到你的数据库(持有在容器层面)。这很可能是池中的第一个连接,因为它保证不被使用,所以它是第1个连接,因为两个函数不可能在同一个容器中同时运行。继续阅读以获得解释。
如果AWS不重用容器,它将创建一个新容器,您的代码将分配另一个N连接池。根据容器的周转率,您可能会完全耗尽数据库池。
如果两个请求同时到达,AWS无法同时调用同一个处理程序。如果这是可能的,那么在容器范围级别定义的变量存在共享状态问题。相反,AWS将使用两个单独的容器,这些容器将分别分配一个N个连接池,即与数据库的2N连接。
单个调用函数永远不需要多个连接(除非您需要在同一个上下文中与两个独立的数据库进行通信)。
连接池唯一有用的是它是否位于容器范围之上的某个级别,即AWS环境本身传递给容器。这是不可能的。
您可以希望的最佳情况是每个容器单个连接。即使这样,您也必须管理此单个连接以确保数据库服务器未断开连接或重新启动。如果是这样,您的容器的连接将会死亡,您的处理程序将永远无法再次连接(直到容器死亡),除非您在函数中编写一些代码来检查连接断开。在繁忙的服务器上,容器可能需要很长时间才能消亡。
还要记住,如果处理程序函数失败,例如事务的一半或锁定了表,则下一个请求调用将从容器中获取脏连接状态。第一次调用可能已经打开了一个事务而死了。第二次调用可以提交并包括所有先前的查询,直至失败。
我建议不要在处理程序函数之外管理状态,除非您有特定的优化需求。如果这样做,则使用单个连接,而不是池。
答案 1 :(得分: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;
}
}
使用任何字符串作为测试事件从AWS控制台调用此方法。在CloudWatch日志中,您每次都会看到调用次数增量。
答案 2 :(得分:0)
有警告 没有销毁方法可以确保关闭池。有人可能会说数据库连接空闲时间会处理。 如果同一数据库用于常规机器Luke EC2中的池维护等其他用例,该怎么办。 就像很多人说的那样,如果请求突然激增,那么会对数据库造成混乱,因为每个用户在数据库端总会有一些最大连接设置。
答案 3 :(得分:0)
对AWS RDS proxy表示敬意,现在您可以使用池化MySql
和postgrese
连接,而无需在Java
或任何特定于AWS Lambda的代码中进行任何额外配置。您所需要做的就是创建和Add a Database proxy
您要重用/合并连接的AWS Lambda函数。请参阅操作方法here。
注意:Free-Tier(more here)中不包含AWS RDS代理。