Quarkus (https://quarkus.io/) is SUPERSONIC SUBATOMIC JAVA
,
A Kubernetes Native Java stack tailored for OpenJDK HotSpot and GraalVM, crafted from the best of breed Java libraries and standards.
That's right. I don't know what you're saying, but it looks great.
Since it is possible to convert Java programs natively with the function of GraalVM, it can be combined with AWS Lambda's custom runtime to solve the ** cold start problem ** which is a characteristic of Java applications running on AWS Lambda. You can expect it.
I tried it according to the procedure on the official website, so I will leave the procedure.
QUARKUS - BUILDING A NATIVE EXECUTABLE https://quarkus.io/guides/building-native-image
QUARKUS - AMAZON LAMBDA https://quarkus.io/guides/amazon-lambda
Amazon Linux 2 of Docker image can not tar
or ʻunzip`, so I will put various things.
I don't know if I need all of them, but I've put in this much.
yum install -y sudo shadow-utils procps tar.x86_64 gzip xz unzip witch git python3 tree
Download it from the official website and expand it.
curl -s -L -o /tmp/graalvm-ce-java11-linux-amd64-20.1.0.tar.gz https://github.com/graalvm/graalvm-ce-builds/releases/download/vm-20.1.0/graalvm-ce-java11-linux-amd64-20.1.0.tar.gz
tar zxf /tmp/graalvm-ce-java11-linux-amd64-20.1.0.tar.gz -C /opt/
ln -s /opt/graalvm-ce-java11-20.1.0 /opt/graalvm
Set JAVA_HOME
to GraalVM and use GraalVM to build with Maven.
export GRAALVM_HOME=/opt/graalvm
export JAVA_HOME=$GRAALVM_HOME
export PATH=$GRAALVM_HOME/bin:$PATH
Finally, install the native-image
required for Native build. The command is gu
(GraalVM Updater).
gu install native-image
Maven used to build Quarkus requires version 3.6.2 or higher. The version that can be installed with yum
was old, so I downloaded it from the official website and installed it.
curl -s -L -o /tmp/apache-maven-3.6.3-bin.tar.gz https://downloads.apache.org/maven/maven-3/3.6.3/binaries/apache-maven-3.6.3-bin.tar.gz
tar zxf /tmp/apache-maven-3.6.3-bin.tar.gz -C /opt/
ln -s /opt/apache-maven-3.6.3 /opt/apache-maven
maven version check
bash-4.2# mvn --version
Apache Maven 3.6.3 (cecedd343002696d0abb50b32b541b8a6ba2883f)
Maven home: /opt/apache-maven
Java version: 11.0.7, vendor: GraalVM Community, runtime: /opt/graalvm-ce-java11-20.1.0
Default locale: en_US, platform encoding: UTF-8
OS name: "linux", version: "4.19.76-linuxkit", arch: "amd64", family: "unix"
bash-4.2#
You can see that it is running on the GraalVM JVM.
Create a project with the mvn
command.
mvn archetype:generate \
-DarchetypeGroupId=io.quarkus \
-DarchetypeArtifactId=quarkus-amazon-lambda-archetype \
-DarchetypeVersion=1.6.0.Final
After a while, you will be asked a question at the prompt, so answer it. The part enclosed in [] is the user input.
Define value for property 'groupId': [myGroup]
Define value for property 'artifactId': [myArtifact]
Define value for property 'version' 1.0-SNAPSHOT: : []
Define value for property 'package' myGroup: : [example]
Confirm properties configuration:
groupId: myGroup
artifactId: myArtifact
version: 1.0-SNAPSHOT
package: example
Y: : [Y]
A directory is created with ʻartifactId` (myArtifact) and a project is generated.
The project structure immediately after creation looks like this.
bash-4.2# tree myArtifact/
myArtifact/
├── build.gradle
├── gradle.properties
├── payload.json
├── pom.xml
├── settings.gradle
└── src
├── main
│ ├── java
│ │ └── example
│ │ ├── InputObject.java
│ │ ├── OutputObject.java
│ │ ├── ProcessingService.java
│ │ ├── StreamLambda.java
│ │ ├── TestLambda.java
│ │ └── UnusedLambda.java
│ └── resources
│ └── application.properties
└── test
├── java
│ └── example
│ └── LambdaHandlerTest.java
└── resources
└── application.properties
9 directories, 14 files
bash-4.2#
The Handler called by Lambda is set in quarkus.lambda.handler
of resources / application.properties
.
resources/application.properties
quarkus.lambda.handler=test
With the above settings, the class named test
below will be called.
java:main/java/example.TestLambda.java
@Named("test")
public class TestLambda implements RequestHandler<InputObject, OutputObject> {
}
The rest is coded like normal Lambda.
In addition to test
, stream
is also available as a template.
Let's create a deployment package with the template as it is.
mvn clean package -Pnative
It takes a lot of time. I think it will take more than 10 minutes.
When the deploy package is successfully created, target / function.zip
will be generated. When I tried to expand it, the contents were only bootstrap
.
bash-4.2# unzip function.zip
Archive: function.zip
inflating: bootstrap
bash-4.2#
A file called manage.sh
is also generated in the target
directory, and it seems that you can deploy it on AWS from here.
I was new to the custom runtime, so I tried it from the management console.
After creating the deployment package, a file called target / sam.native.yaml
is also generated, so I referred to this for the handler name and environment variables.
Create a new function.
Let's say the runtime is providing your own bootstrap
.
After creating the function, upload the program.
Select Upload .zip file
from Action
in the function code and select function.zip
.
The handler will be not.used.in.provided.runtime
.
Add DISABLE_SIGNAL_HANDLERS
to the environment variable and set the value to true
.
The setting is completed up to this point. Let's test run with the following JSON as input.
{
"name": "Bill",
"greeting": "hello"
}
Here is the operation result. It worked safely.
To use the AWS SDK, you need to make some settings, not just add it to pom.xml.
Add the following to resources / application.properties
. (Although it seems that the official document says that it is valid by default)
resources/application.properties
quarkus.ssl.native=true
First of all, quarkus-jaxb
is required, so add this.
pom.xml
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-jaxb</artifactId>
</dependency>
Next, I will add the AWS SDK library.
For native image, however the URL Connection client must be preferred over the Apache HTTP Client when using synchronous mode, due to issues in the GraalVM compilation (at present).
When translated `However, for native images, due to GraalVM compilation issues (currently), URL-connected clients should be prioritized over Apache HTTP clients when using synchronous mode. `` That's right. Therefore, the description is as follows.
pom.xml
<properties>
<aws.sdk2.version>2.10.69</aws.sdk2.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>bom</artifactId>
<version>${aws.sdk2.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>url-connection-client</artifactId>
</dependency>
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>apache-client</artifactId>
<exclusions>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>s3</artifactId>
<exclusions>
<!-- exclude the apache-client and netty client -->
<exclusion>
<groupId>software.amazon.awssdk</groupId>
<artifactId>apache-client</artifactId>
</exclusion>
<exclusion>
<groupId>software.amazon.awssdk</groupId>
<artifactId>netty-nio-client</artifactId>
</exclusion>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.jboss.logging</groupId>
<artifactId>commons-logging-jboss-logging</artifactId>
<version>1.0.0.Final</version>
</dependency>
</dependencies>
In this example of accessing S3, when creating S3Client, explicitly specify ʻUrlConnectionHttpClient in
httpClient`.
S3Client s3 = S3Client.builder()
.region(Region.AP_NORTHEAST_1)
.httpClient(software.amazon.awssdk.http.urlconnection.UrlConnectionHttpClient.builder().build())
.build();
The deployment package must include the following for SSL communication:
First, create the src / main / zip.native /
directory and create the bootstrap
.
zip.native/bootstrap
#!/usr/bin/env bash
./runner -Djava.library.path=./ -Djavax.net.ssl.trustStore=./cacerts
Then copy libsunec.so
and cacerts
. These two files are included in GraalVM.
cp $GRAALVM_HOME/lib/libsunec.so $PROJECT_DIR/src/main/zip.native/
cp $GRAALVM_HOME/lib/security/cacerts $PROJECT_DIR/src/main/zip.native/
The procedure for creating a deployment package remains the same.
mvn clean package -Pnative
If you create a deployment package with SSL enabled, the contents of target / function.zip
will change.
bash-4.2# unzip function.zip
Archive: function.zip
inflating: bootstrap
inflating: cacerts
inflating: libsunec.so
inflating: runner
bash-4.2#
You can see that it contains the pre-prepared bootstrap``cacerts``libsunec.so
.
Check here for verification results that cold start faster than the normal Java runtime.
Quarkus saves Java Lambda! ?? https://qiita.com/moritalous/items/4de31a66edac728ba088
Recommended Posts