Microservice and Serverless With Micronaut + GraalVM
GraalVM and Micronauts - frenzy way to MicroServices, Serverless: Part2
Join the DZone community and get the full member experience.
Join For FreeMicronaut® framework is creating a buzz around cloud-native (microservice, serverless ) application development due to its enriched features and optimizations based out of modern Polyglot JVM — GraalVM optimizers.
For GraalVM optimizers go thought Part1 of this series — GraalVM — Byte Code to Bit Code.
Why Micronaut® and what makes it the next level stuff as a framework for Cloud-Native development :
- Natively Cloud Native
Micronaut®'s cloud support is built right in, including support for common discovery services, distributed tracing tools, cloud runtimes and leading vendors ( AWS, AZURE, GCP). - Ready for Serverless Development
Micronaut® low overhead compile-time DI and AOP make it perfect for writing functions for serverless environments like AWS Lambda, Azure Functions etc. - Fast Start Time — Low Memory Consumption
Reflection-based IoC framework load and cache reflection data for every single field, method, and constructor in your code. Whereas with Micronaut®, your application startup time and memory consumption are not bound to the size of your codebase. Micronaut® build around GraalVM. Micronaut features a dependency injection and aspect-oriented programming runtime that uses no reflection. This makes it easier for Micronaut applications to run on GraalVM.
Micronaut apps start in a tenth of millisecond with GraalVM! - Built with Non-Blocking Http Server on Netty
With a smooth learning curve, Micronaut’s HTTP server makes it as easy as possible to expose APIs that can be consumed by HTTP clients. - Design for Building Resilient Microservices
Distributed environments require planning for failure. Micronaut’s built-in support for retry, circuit breaker, and fallbacks help you plan. - Faster Data Layer Configuration
Micronaut provides sensible defaults that automatically configure your favorite data access toolkit and APIs to make it easy to write your own integrations. Supports like Caching, SQL, NoSQL, and different DB vendor products are readily available. - Fast and Easy Testing
Easily spin up servers and clients in your unit tests, and run them instantaneously with mostly auto-generated test stuff for main source code. - Reloading (or “hot-loading”)
Out of box excellent support of hot reloading, restart, and reinitialization with build-in JVM agent support rather than relying on classloader reloading or proprietary JVM agents like JRebel etc. It is an important feature to make the development cycle efficient and fast. - Refreshable feature
@Refreshable
is another interesting scope offered by Micronaut. You can refresh the state of a bean by calling the HTTP endpoint/refresh
or by publishingRefreshEvent
to the application context.
How to Get Started Along Microservice With Micronaut
Create an app using the Micronaut Command Line Interface.
Installing Micronaut® manually comes with a super-rich & intuitive CLI that we will be using for the rest of the project lifecycle ( its power-pack CLI features add to developers productivity). We will be doing 3case studies with Micronaut® to compare and benchmark its potential relative to today’s Cloud-Native de-facto framework — SpringBoot.
Case A : Micronaut ® app on GraalVM optimised JIT
Case B : Micronaut ® app on GraalVM “Native-Image”
Case C : SpringBoot on openJDK HotSpotVM JIT — conventional way
Let’s get to the suspense straight-in with below depiction of different benchmarking results :
Step 1: Install Micronaut® nm and test its installation with below steps:
$ brew install micronaut (using MacOS)
$ mn --version (testing installation success)
Step2: Simple command can create an app framework with all features generally required for microservice along with Dockerization.# creating an application with name demo-mn-jit
xxxxxxxxxx
# creating application with name demo-mn-jit
$ mn create-app demo-mn-jit --build=maven --lang=kotlin -t=junit
-l, --lang e.g. -l kotlin
-t, --test e.g. -t junit
-b, --build. e.g. -b gradle
-f, --features e.g. -f annotation-api, app-name, docker, file-watch, netty-server, readme, yaml
# creating aws lambda serverless function named demo-lambda
$ mn create-function-app demo-lambda --lang=kotlin --test=spook --build=gradle
# generic mn taxonomy
mn create-app [-hivVx] [ - list-features] [-b=BUILD-TOOL] [ - jdk=<javaVersion>] [-l=LANG]
Step 3: Open the generated project in your IDE (IntelliJ in my case) to see the complete project structure and files. Micronaut® has close resemblance with Spring Boot that developers can relate to when starting with it. Hence minimize the learning curve of getting on to Micronaut® and its super-rich features.
Step 4: Adding programming constructs like Controller, Beans, Interceptor, Security config, profilers, etc with cli.
xxxxxxxxxx
$ cd ~/<mn project directory>
# then use below cli command to create most of construct
$ mn create-controller Creates a controller and associated test
$ mn create-websocket-server Creates a Websocket server
$ mn create-bean Creates a singleton bean
$ mn create-websocket-client
$ mn create-test Creates a test for the project's testing framework
$ mn create-job Creates a job with scheduled method
$ mn create-client Creates a client interface
Example :
$ mn create-controller Customer
Case A : Micronaut® app on GraalVM optimised JIT
xxxxxxxxxx
$ cd ~/< Workspace dir>
# using CLI to generate Micronaut® app on GraalVM optimised JIT ( without native-image)
mn create-app demo-mn-jit -b=maven -jdk=11 -l=kotlin -f=graalvm
# then add controller to it
$ cd ~/< mn project dir>
$ mn create-controller CustomerHandler
$ mn create-bean Customer
Memory Space : 13.64MB — App + 265MB HotSpotVM/JRE = 278MB approx.
Start-up time = 1.01Sec = 1001ms
GitHub url for refrence demo app generated above used for stats :
https://github.com/scanpratik/micronauts-GraalVM--JIT
Case B : Micronaut® app on GraalVM - Native-Image
This is the main case study curiosity to way forward to modern cloud-native, lets observe it closely:
GitHub url for demo app generated above used for benchmarking :
https://github.com/scanpratik/micronauts-nativeImage-GraalVM
One can build a native image directly with Maven using the mvn package
command without running the native-image
plugin.
xxxxxxxxxx
<plugin>
<groupId>org.graalvm.nativeimage</groupId>
<artifactId>native-image-maven-plugin</artifactId>
<version>${graalvm.version}</version>
<executions>
<execution>
<goals>
<goal>native-image</goal>
</goals>
<phase>package</phase>
</execution>
</executions>
<configuration>
<skip>false</skip>
<imageName>example</imageName>
<buildArgs>
--no-fallback
</buildArgs>
</configuration>
</plugin>
Memory Space: 62MB only— App + native runtime
Start-up time = .022Sec = 22ms
Case C : SpringBoot on openJDK HotSpotVM JIT — conventional way
Leaving details of SpringBoot with HotSpot VM app generation as it has the de-facto framework and enough material is floating on the internet for reference
GitHub url for demo app generated above used for benchmarking :
https://github.com/scanpratik/graalVM-SpringBoot2.X

SpringBoot + HotSpotVm JIT
Memory Space : 16.51MB — App + 320MB HotSpotVM/JRE = 338MB approx.
Start-up time = 1.81 Sec = 1810ms
Seems, HotSpotVM + SpringBoot (proxy and reflection based) has hit bottom-line benchmark for memory footprint and execution startup time.
Design Decision — GraalVM Native-Image vs GraalVM JIT vs HotspotVM JIT :
Sometimes good performance means good throughput, sometimes it means low memory usage, and sometimes it means a fast cold-start startup time.
Benefits of a “Native-Image” aren’t for free — they come with a cost. Obviously, the native executable can only run on a single platform. Another limitation is caused by missing metadata during runtime. Since by default a native image doesn’t retain information about classes and methods, hence one’s ability to perform reflection is limited. As there are many Java frameworks that rely on reflective access, getting them to run on a Native Image may require additional configuration.
Having said that, it's obvious GraalVM is the way forward and will be encouraged over HotSpotVM. Micronaut® is a goto framework, to be used in conjunction with GraalVM based JIT or Native-Image for cloud-native development. Below flow chart will help in understanding the decision making logic.
Published at DZone with permission of Pratik Prakash. See the original article here.
Opinions expressed by DZone contributors are their own.
Comments