在 Lambda 函数快照之前或之后实现代码 - AWS Lambda

在 Lambda 函数快照之前或之后实现代码

在 Lambda 创建快照之前或 Lambda 还原快照后,使用运行时挂钩实施代码。运行时挂钩作为开源检查点协调还原(CRaC)项目的一部分提供。CRaC 正在开发开放 Java 开发工具包(OpenJDK)。有关如何将 CRaC 与参考应用程序结合使用的示例,请参阅 GitHub 上的 CRaC 存储库。CRaC 使用三个主要元素:

  • Resource – 具有两种方法的接口,beforeCheckpoint()afterRestore()。使用这些方法实施要在快照之前和还原之后运行的代码。

  • Context <R extends Resource> – 若要接收检查点和还原的通知,Resource 必须注册到 Context

  • Core – 协调服务,该服务通过静态方法 Core.getGlobalContext() 提供默认全局 Context

有关 ContextResource 的更多信息,请参阅 CRaC 文档中的 Package org.crac(程序包 org.crac)。

使用以下步骤通过 org.crac 程序包实施运行时挂钩。Lambda 运行时包含自定义的 CRaC 上下文实施现,该实施会在检查点检查之前和还原后调用运行时挂钩。

步骤 1:更新构建配置

org.crac 依赖项添加到构建配置中。下面的示例使用了 Gradle。有关其他构建系统的示例,请参阅 Apache Maven 文档

dependencies { compile group: 'com.amazonaws', name: 'aws-lambda-java-core', version: '1.2.1' # All other project dependecies go here: # ... # Then, add the org.crac dependency: implementation group: 'org.crac', name: 'crac', version: '1.4.0' }

第 2 步:更新 Lambda 处理程序

Lambda 函数处理程序是函数代码中处理事件的方法。当调用函数时,Lambda 运行处理程序方法。您的函数会一直运行,直到处理程序返回响应、退出或超时。

有关更多信息,请参阅 定义采用 Java 的 Lambda 函数处理程序

以下示例处理程序介绍如何在检查点检查(beforeCheckpoint())之前和还原(afterRestore())之后运行代码。该处理程序还将 Resource 注册到运行时管理的全局 Context 中。

注意

Lambda 创建快照时,初始化代码最多可以运行 15 分钟。时间限制为 130 秒或配置的函数超时(最大 900 秒),以较高者为准。您的 beforeCheckpoint() 运行时挂钩计入初始化代码时限。Lambda 还原快照时,必须加载运行时(JVM),并且 afterRestore() 运行时挂钩必须在超时限制(10 秒)内完成。否则,您将收到 SnapStartTimeoutException。

... import org.crac.Resource; import org.crac.Core; ... public class CRaCDemo implements RequestStreamHandler, Resource { public CRaCDemo() { Core.getGlobalContext().register(this); } public String handleRequest(String name, Context context) throws IOException { System.out.println("Handler execution"); return "Hello " + name; } @Override public void beforeCheckpoint(org.crac.Context<? extends Resource> context) throws Exception { System.out.println("Before checkpoint"); } @Override public void afterRestore(org.crac.Context<? extends Resource> context) throws Exception { System.out.println("After restore");

Context 仅对注册对象保持 WeakReference。如果 Resource 是垃圾回收,则不会运行运行时挂钩。您的代码必须保持对 Resource 的强引用,以保证运行时挂钩正常运行。

以下是两个应避免的模式示例:

例 – 没有强引用的对象
Core.getGlobalContext().register( new MyResource() );
例 – 匿名类的对象
Core.getGlobalContext().register( new Resource() { @Override public void afterRestore(Context<? extends Resource> context) throws Exception { // ... } @Override public void beforeCheckpoint(Context<? extends Resource> context) throws Exception { // ... } } );

相反,保持强引用。在以下示例中,注册的资源不是垃圾回收的,运行时挂钩可以持续运行。

例 – 具有强引用的对象
Resource myResource = new MyResource(); // This reference must be maintained to prevent the registered resource from being garbage collected Core.getGlobalContext().register( myResource );