Let’s compile your Aws Lambda in Java

via Graalvm, docker and maven

Introduction

If you used Java for writing your Lambda code, you already noticed the response time can be impacted very badly by a cold start of the container behind your lambda including the startup time of the JVM.

Your Current lambda

Lambda Code

mvn package
  • Choose Java 11 (Corretto) as the Runtime
  • upload your deployment package (hello-lambda-java11–1.0-SNAPSHOT-shaded.jar) from the console or via S3
  • Define example.App::sayHello as the Handler (where example.App is the full classname and sayHello is the method name).

Current Performance

Cold Start

  • In that case, the user will see a total time of 1 ms only! (Note: We should include network time + de-serialization time...)
  • the custom lambda runtime and Java RIC
  • graalVM native-image
  • docker

Understanding the lambda execution environment

Architecture diagram of the execution environment
  • The Lambda Runtime responsible for providing the Lambda Function the event to use and controlling its. execution. It consists of an execution loop waiting for a new event and retrieving it from the Runtime API, then posting the return value from the Lambda Function to the Runtime API (see more here).
  • The Runtime API providing a REST API mainly GET /runtime/invocation/next and POST /runtime/invocation/<AwsRequestId>/response respectively for retrieving the AwsRequest and to send the response (see more here).

The custom lambda runtime and Java RIC

In order to execute some native code, we need to create a deployment package respecting the custom lambda runtime specifications:

  • But also bundle our custom lambda runtime inside the native code!
  • So the native code must be the compilation of our lambda function + the custom lambda runtime (for linux x86–64).
com.amazonaws.services.lambda.runtime.api.client.AWSLambda
bootstrap : our bootstrap scriptfunc : our native executable

GraalVM Native-Image

The project graalVM is providing 2 compatibles JDK: version 8 and version 11

native-image -jar hello-lambda-custom-1.0-SNAPSHOT.jar

Docker

One of the requirement of the custom runtime is to provide the native code for linux x86–64 and it is possible that the developer machine is on Mac or Windows… One way to deal with this problem is to use a docker container technology to run a linux x86–64 and inside it call the native-image command line.

docker build -t hello-lambda:latest .
docker create hello-lambda:latest
docker cp <container_id>:/function/function.zip .
docker container rm <container_id>

The Solution with the custom runtime

The new pom.xml:

  • set the Handler to: example.App::sayHello

Let’s test the performance

Cold Start

Bonus: Run the lambda inside a container

AWS introduced recently the possibility to run a lambda from a docker container (see more here).

docker run -p 9000:8080 hello-lambda:latest
curl -XPOST "http://localhost:9000/2015-03-31/functions/function/invocations" -d '{}'

Founder and CTO of Solusoft.Tech, Java Expert & Architect, AWS Serverless happy user and flutter early adopter.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store