With the dawn of microservices the software development has been taken to a new level. The performance of your applications is defined by the level of your expertise in building microservice architecture. Indeed, you cannot take a monolith and simply break it down, or else there wouldn’t be 101 articles, handbooks and guidelines on how to take this cutting-edge technology by the horns. We, too, have made a humble contribution into explaining the ABCs of microservices (you can read the article here). But if you still feel that you’re treading on thin ice trying to split your application into small and efficient services, contact us, and our engineers will gladly answer your questions or help you with the migration.
One way to turn your Java app into a refined system of microservices is to use frameworks. Of course, everybody has heard about the most famous of them, i.e. Spring. However, no matter how delicious this cake is, it is always nice to have a selection of dainties, right? So, in this article we are going to discuss another framework that is still gaining popularity: Quarkus.
Why Quarkus?
Quarkus is an open-source stack of technologies with MicroProfile support aimed at optimizing Jakarta EE for building microservices. It is a Java framework oriented to Kubernetes and adapted to OpenJDK HotSpot and GraalVM. To create microservices, Quarkus implements Eclipse MicroProfile APIs along with other useful tools, such as Apache Kafka, Camel, dependency injection, Hibernate ORM (JPA and JTA annotations), RESTEasy (JAX-RS), etc. It also provides Maven and Gradle plugins so that you could run your application in the development mode on a local or a remote machine.
What makes Quarkus stand out among its competitors?
The fact that it supports GraalVM lets the developers use ahead-of-time (AOT) compilation to convert the bytecode into native machine code. This way, apps can be compiled to native executables with no need for dynamical scanning and loading all classes into a JVM. By default, all classes are initialized at build time. As a result, the application starts much faster and consumes significantly less resources. Some tests1 have shown that “Quarkus is 2 times faster to start and consumes half the heap size used by Spring’’.
In addition, compliance with Java EE standards enables developers to use existing APIs and run their applications in an optimized runtime without the need to re-write them. Basically, you can use enterprise API’s and extend them according to your own requirements (for example, use Quarkus extensions for reactive messaging, Vert.x, or Camel).
However, there are certain limitations related to the Quarkus framework. For instance, Quarkus relies on Kubernetes to a great extent, so if your team hasn’t worked with this software, it might take some time before you migrate to this software successfully. Furthermore, Quarkus doesn’t support all Java EE standards yet and it has fewer libraries as compared to Spring Boot.
Nevertheless, Quarkus is being constantly improved, so these gaps may be closed in the near future.
For now, let’s take a look at what Quarkus is capable of in the native image environment.
Quarkus + Liberica Native Image Kit: turn it up!
As you have already understood, Quarkus is tailored to native images approach, which is perfect for deployment in the cloud and serverless development. You could be pleasantly surprised to find out that Quarkus efficiency can be boosted even more. How? Use it with a tool, created especially for accelerating your applications ー Liberica Native Image Kit.
Liberica Native Image Kit (NIK) is a GraalVM-based technology that converts a JVM-based application into a fully AOT compiled native executable under the closed-world assumption with an almost instant startup time. It supports a wide variety of platforms, including lightweight musl-based Alpine Linux. Full-fledged support for Alpine Linux musl makes Liberica NIK a perfect choice if you strive to minimize resource consumption, achieve record startup times (up to 1/10 of a second), and save on memory. Moreover, NIK allows you to create seamless polyglot projects in different programming languages.
In addition, NIK runs with most JDK versions, which gives you full control over your build. And the fact that it is based on LTS Liberica JDK means that you can enjoy at least 8 years of access to bug fixes, security updates, and other fixes as needed.
Obviously, you can’t go wrong with the combination of these two powerful tools, Quarkus framework and Liberica NIK. Without further ado, let’s see how to run them together.
How to use Quarkus and NIK together?
Before building a native executable for Quarkus, we need to get all necessary tools and software ready.
First, set up a working C compiler toolchain.
-
On Linux, GCC, and the glibc and zlib headers are necessary. *
# dnf (rpm-based) sudo dnf install gcc glibc-devel zlib-devel libstdc++-static # Debian-based distributions: sudo apt-get install build-essential libz-dev zlib1g-dev
- On Windows, you will have to install the Visual Studio 2017 Visual C++ Build Tools.
-
In the case of MacOS, the dependencies are provided by XCode.
xcode-select --install
To demonstrate how to integrate Liberica NIK into Quarkus, we are going to use the basic Hello World Quarkus application. Go ahead and follow the instructions on the site to create a simple Quarkus app.
Now that you have your Hello World application ready, let’s configure Native Image Kit.
Start with downloading the appropriate version of Liberica NIK (the package already contains Liberica VM, native image and language installables). After the download is finished, check the file by verifying the checksum in the command line (the checksum should match the one next to the link on the downloads page).
- Configure the runtime environment. For Linux and macOs, in case you have
.tar.gz / zip
archive, setJAVA_HOME
environment variable to the NIK installation directory:
export JAVA_HOME=$HOME/Development/bellsoft-liberica-vm-openjdk11-21.2.0/
If the installation is performed using the package (deb, pkg/dmg), the installation path for macOS will be the conventional one.
On Windows, you will have to go through the Control Panel to set your environment variables.
- Install the
native-image
tool usinggu install.
Alternatively, you can download NIK Core version, which contains Liberica VM and native image without additional languages. In this case, useni install
:
$JAVA_HOME/bin/gu install native-image
As a result, the native executable for your application will contain the application code, necessary libraries, Java APIs, as well as a reduced version of a virtual machine.
If you followed the instructions and constructed the Quarkus application, you will find the following profile in the pom.xml:
<profiles>
<profile>
<id>native</id>
<properties>
<quarkus.package.type>native</quarkus.package.type>
</properties>
</profile>
</profiles>
- To create a native executable, run
./mvnw package -Pnative.
Note that it may take some time (several minutes usually) to package the native executable, so be patient.
Here we are! You have built a native executable for your application! Find the resulting executable file as target/getting-started-1.0.0-SNAPSHOT-runner
.
To make sure that everything works correctly, launch the application. You should see the following:
The application will listen on http://localhost:8080.
Conclusion
In this article, we discovered the benefits of using Quarkus framework to build cloud-native Java applications and learned how to spike its performance with Liberica Native Image Kit. The process of integrating these technologies is not that complicated, but in the end you get a triple bonus:
- Small image size to build tiny containers;
- Outstandingly faster startup time;
- Significantly reduced memory usage.
Introduce your application to this superhero combo and you won’t be disappointed!