在 AWS lambda java 中使用 JPA/Hibernate
Using JPA/Hibernate in AWS lambda java
我必须在 Java 中实现一个 AWS lambda 函数,它将使用 Kinesis 流和 read/write 数据到 MySQL 数据库。因为我已经在另一个应用程序中定义了模型实体,所以我想重用它们,而不是使用普通 SQL/JDBC。
所以我的目标是使用 JPA/Hibernate 实现 lambda。这在一般情况下可能吗?如果是,是否有任何实际示例或最佳实践?
我以前从事过 Spring 引导应用程序,其中类似的功能完全可用且易于配置,现在我什至不知道从哪里开始。
我将回答我自己的问题,以便为其他想要使用 JPA/Hibernate 尝试 AWS lambda 的人节省时间。虽然可以在没有应用程序服务器或容器的情况下使用 JPA,但在 AWS lambda 的情况下存在很多限制。例如,参见 this。这使得使用 JPA 和 lambda 变得不切实际。所以我决定直接通过 JDBC 与数据库交互(更准确地说,使用 Spring 的 JdbcTempate)。
我强烈反对您关于 JPA 在 Lambda 上不可行的评估,并且目前有几个函数 运行 证明了这一点,但要注意:只有在同步 lambda 中使用 JPA 才是真正可行的环境,或不经常使用的环境。 (稍后会详细介绍)
Persistence.createPersistenceFactory
每个应用程序只应执行一次,并将结果放在静态或单例上下文中。
您使用运行时关闭挂钩处理关闭 JPA 资源。
实际发生的情况是,即使没有数据正在处理,Lambda 函数也会启动并保持一段时间。 (对于同步函数和异步函数都是如此)在这种情况下,当下一次调用到来时,你的函数是在相同的运行环境下执行的,它可以re-use EntityManagerFactory
创建新的EntityManager
实例。同步调用和异步调用之间的主要区别在于并发量。同步函数的并发性非常有限,而异步函数可能变化很大,因此您需要承担更大的启动成本,因为它会随着函数实例池的扩大和缩小而更频繁地发生。
是的,函数的运行时环境会被周期性地杀死,无论是同步还是异步,尤其是当没有看到流量时,启动时间会变慢,但后续调用将 re-use 相同的运行时环境(s) 根据我的经验,尤其是在使用同步函数时,例如那些挂接到 Kinesis Stream 中的函数。
我强烈建议顺便将自己限制为同步编写器,因为它会限制 Lambda 实例的数量,从而限制有多少 JDBC 池连接到您的数据库。 (这在数据库端可能会成为一个严重的问题,它通常只接受几十或几百个连接,但每个 JDBC 池将有大约 10 个左右的连接!!!)对于 Kinesis Streams,这等于数量分片,如果您的记录很小,您可以使用 KPL 和记录聚合大大增加分片容量。 lambda 函数本身每次调用只会从流中接收 < 6MB 的数据。
我必须在 Java 中实现一个 AWS lambda 函数,它将使用 Kinesis 流和 read/write 数据到 MySQL 数据库。因为我已经在另一个应用程序中定义了模型实体,所以我想重用它们,而不是使用普通 SQL/JDBC。 所以我的目标是使用 JPA/Hibernate 实现 lambda。这在一般情况下可能吗?如果是,是否有任何实际示例或最佳实践? 我以前从事过 Spring 引导应用程序,其中类似的功能完全可用且易于配置,现在我什至不知道从哪里开始。
我将回答我自己的问题,以便为其他想要使用 JPA/Hibernate 尝试 AWS lambda 的人节省时间。虽然可以在没有应用程序服务器或容器的情况下使用 JPA,但在 AWS lambda 的情况下存在很多限制。例如,参见 this。这使得使用 JPA 和 lambda 变得不切实际。所以我决定直接通过 JDBC 与数据库交互(更准确地说,使用 Spring 的 JdbcTempate)。
我强烈反对您关于 JPA 在 Lambda 上不可行的评估,并且目前有几个函数 运行 证明了这一点,但要注意:只有在同步 lambda 中使用 JPA 才是真正可行的环境,或不经常使用的环境。 (稍后会详细介绍)
Persistence.createPersistenceFactory
每个应用程序只应执行一次,并将结果放在静态或单例上下文中。
您使用运行时关闭挂钩处理关闭 JPA 资源。
实际发生的情况是,即使没有数据正在处理,Lambda 函数也会启动并保持一段时间。 (对于同步函数和异步函数都是如此)在这种情况下,当下一次调用到来时,你的函数是在相同的运行环境下执行的,它可以re-use EntityManagerFactory
创建新的EntityManager
实例。同步调用和异步调用之间的主要区别在于并发量。同步函数的并发性非常有限,而异步函数可能变化很大,因此您需要承担更大的启动成本,因为它会随着函数实例池的扩大和缩小而更频繁地发生。
是的,函数的运行时环境会被周期性地杀死,无论是同步还是异步,尤其是当没有看到流量时,启动时间会变慢,但后续调用将 re-use 相同的运行时环境(s) 根据我的经验,尤其是在使用同步函数时,例如那些挂接到 Kinesis Stream 中的函数。
我强烈建议顺便将自己限制为同步编写器,因为它会限制 Lambda 实例的数量,从而限制有多少 JDBC 池连接到您的数据库。 (这在数据库端可能会成为一个严重的问题,它通常只接受几十或几百个连接,但每个 JDBC 池将有大约 10 个左右的连接!!!)对于 Kinesis Streams,这等于数量分片,如果您的记录很小,您可以使用 KPL 和记录聚合大大增加分片容量。 lambda 函数本身每次调用只会从流中接收 < 6MB 的数据。