Runtime hooks for Lambda SnapStart - AWS Lambda

Runtime hooks for Lambda SnapStart

You can use runtime hooks to implement code before Lambda creates a snapshot or after Lambda resumes a function from a snapshot. Runtime hooks are available as part of the open-source Coordinated Restore at Checkpoint (CRaC) project. CRaC is in development for the Open Java Development Kit (OpenJDK). For an example of how to use CRaC with a reference application, see the CRaC repository on GitHub. CRaC uses three main elements:

  • Resource – An interface with two methods, beforeCheckpoint() and afterRestore(). Use these methods to implement the code that you want to run before a snapshot and after a restore.

  • Context <R extends Resource> – To receive notifications for checkpoints and restores, a Resource must be registered with a Context.

  • Core – The coordination service, which provides the default global Context via the static method Core.getGlobalContext().

For more information about Context and Resource, see Package org.crac in the CRaC documentation.

Use the following steps to implement runtime hooks with the org.crac package. The Lambda runtime contains a customized CRaC context implementation that calls your runtime hooks before checkpointing and after restoring.

Step 1: Update the build configuration

Add the org.crac dependency to the build configuration. The following example uses Gradle. For examples for other build systems, see the Apache Maven documentation.

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' }

Step 2: Update the Lambda handler

The Lambda function handler is the method in your function code that processes events. When your function is invoked, Lambda runs the handler method. Your function runs until the handler returns a response, exits, or times out.

For more information, see AWS Lambda function handler in Java.

The following example handler shows how to run code before checkpointing (beforeCheckpoint()) and after restoring (afterRestore()). This handler also registers the Resource to the runtime-managed global Context.

Note

When Lambda creates a snapshot, your initialization code can run for up to 15 minutes. The time limit is 130 seconds or the configured function timeout (maximum 900 seconds), whichever is higher. Your beforeCheckpoint() runtime hooks count towards the initialization code time limit. When Lambda restores a snapshot, the runtime (JVM) must load and afterRestore() runtime hooks must complete within the timeout limit (10 seconds). Otherwise, you'll get a 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 maintains only a WeakReference to the registered object. If a Resource is garbage collected, runtime hooks do not run. Your code must maintain a strong reference to the Resource to guarantee that the runtime hook runs.

Here are two examples of patterns to avoid:

Example – Object without a strong reference
Core.getGlobalContext().register( new MyResource() );
Example – Objects of anonymous classes
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 { // ... } } );

Instead, maintain a strong reference. In the following example, the registered resource isn't garbage collected and runtime hooks run consistently.

Example – Object with a strong reference
Resource myResource = new MyResource(); // This reference must be maintained to prevent the registered resource from being garbage collected Core.getGlobalContext().register( myResource );