Introduction
In , or read my article . In my example, I used the 25.0.2-graal version, but you can use the newest one.
Sample application using GraalVM Native Image
We'll reuse the , but adjust it. The goal is to be able to build GraalVM Native Image and deploy it on AWS Lambda as a Custom Runtime.
Here is the final version of the , . As we can see, we need to declare there the following:
- all our Lambda functions like GetProductByIdHandler] and CreateProductHandler
- entities like Product that Jackson converts from JSON payload and back
- APIGatewayProxyRequestEvent and all its inner classes because we declared this event type as a request event in our Lambda functions, like GetProductByIdHandler and CreateProductHandler
- org.joda.time.DateTime, which will be used to convert a timestamp from a string and back. Such a timestamp is a part of the API Gateway proxy request and response events. In my opinion, it's time to switch from .
To avoid errors with Loggers during the initialization described in the article :
CODEArgs=--allow-incomplete-classpath \
--initialize-at-build-time=org.slf4j.simple.SimpleLogger,\
org.slf4j.LoggerFactory
-- --trace-class-initialization=org.slf4j.simple.SimpleLogger,\
org.slf4j.LoggerFactory
The native-image.properties should be placed in the META-INF/native-image/${MavenGroupIid}/${MavenArtifactId}
As we use slf4j-simple Logger in our application, we need to place native-image.properties in the path META-INF/native-image/org.slf4j/slf4j-simple.
If you use another Logger implementation (e.g., log4j or logback), you need to adjust this file and place it accordingly.
To save the manual work of defining all this metadata, you can use . For this, we need to package everything into a file with a .zip extension, which includes the file with the name bootstrap. This file can either be the GraalVM Native Image or contain instructions on how to invoke the GraalVM Native Image placed in another file. We'll use the latter way; let's explore it.
Building GraalVM Native Image
We'll build GraalVM Native Image automatically in the package phase defined in the plugin, whose configuration is very similar. This plugin requires the definition of the main class, which a Lambda function doesn't have. That's why we use descriptor:
CODE<assembly>
<id>native-zip</id>
<formats>
<format>zip</format>
</formats>
<baseDirectory/>
<fileSets>
<fileSet>
<directory>src/shell/native</directory>
<outputDirectory>/</outputDirectory>
<useDefaultExcludes>true</useDefaultExcludes>
<fileMode>0775</fileMode>
<includes>
<include>bootstrap</include>
</includes>
</fileSet>
<fileSet>
<directory>target</directory>
<outputDirectory>/</outputDirectory>
<useDefaultExcludes>true</useDefaultExcludes>
<fileMode>0775</fileMode>
<includes>
<include>aws-lambda-java-25-with-dynamodb-as-graalvm-native-image</include>
</includes>
</fileSet>
</fileSets>
</assembly>
This descriptor defines what files from which directories with what permissions will be added to the zip as an assembly format. fileMode equal to 0775 means it has permission to be executable on the Linux operating system. We include previously built GraalVM Native Image with the name aws-lambda-java-25-with-dynamodb-as-graalvm-native-image there. We also include the already defined , we set the Lambda runtime as provided.al2023, which is the newest version of the Lambda function mapped to the .
I did the measurements with provided:al2023.v124 version, and the deployed artifact size of this application was 25.186 KB.
Approach
c p50
c p75
c p90
c p99
c p99.9
c max
w p50
w p75
w p90
w p99
w p99.9
w max
Lambda Custom Runtime with GraalVM Native Image
559
568
593
692
739
739
3.84
4.23
4.88
10.00
55.92
124
Conclusion
In this part of the series, we first introduced GraalVM Native Image. Then we explained step-by-step how to convert the sample application to one where the native image can be built. When we deployed the native image on AWS Lambda using the Lambda Custom Runtime. Finally, we measured the performance of the Lambda function. We observed that the cold and warm start times were lower compared to using the Lambda SnapStart, even with priming techniques, see the measurements table in where I use a relational serverless instead of DynamoDB to do the same Lambda performance measurements.
If you like my content, please follow me on for more technical content and upcoming public speaking activities.
↗ Original-Artikel auf dev.to lesenVollständiger Original-BerichtAusführliche Details, Code-Beispiele & Hersteller-Stellungnahme auf dev.to.
SOCIAL SHARE CARD GENERATOR