March 15, 2019 ( last updated : July 04, 2019 )
quarkus
kubernetes
camel
https://github.com/alainpham/quarkus-camel-first-impressions
On March 07, 2019 Red Hat & the JBoss Community announced Quarkus. It is a Java framework that enables ultra low boot times and tiny memory footprint for applications and services. It does that by taking advantage of GraalVM's native compilation capabilities to produce an executable out of your Java code. Why is this considered to be a game changer ? In this article I will give my view and first impressions on this framework as someone who spends a bit of time writing applications and services. I will get my hands dirty by building a working Quarkus + Apache Camel example.
When Quarkus was announced 1 week ago, many have commented that this is a game changer for the future of Java Application Development. I must say that I have rarely been so excited about a project as I am right now for Quarkus ! So what's the big deal here ?
The official website quarkus.io states that Quarkus can be qualified as "Supersonic Subatomic Java". It is a "A Kubernetes Native Java stack tailored for GraalVM & OpenJDK HotSpot, crafted from the best of breed Java libraries and standards".
To understand the huge value that Quarkus brings, we have to take a step back and get in the shoes of a typical Enterprise Dev Team. Java has been so broadly adopted that it has become the default technology for application development in many organizations. Throughout the years a huge ecosystem of tools and libraries flourished around Java to solve all kinds of challenges and problems.
The recent adoption of Containers and Kubernetes has lead to a wave of innovation around workload orchestration and scheduling. Still, organizations wanted to keep leveraging the expertise around Java their developers have acquired. It became a natural practice to put Java applications and micro services into containers to get the best of both worlds. Organizations wanted a rich ecosystem of libraries and all the innovations around container orchestration at the same time.
When a micro service needs to be scaled up and down quickly is when Java shows some weakness. In fact Java has not been designed for being a short lived process that might be scheduled anywhere on a distributed infrastructure. It has rather been designed and optimized to run application servers for a long time and taking up all the resources available on a VM or a bare metal server. The boot time was not such a critical constraint. In usual Java application the boot time of 4 to 10 seconds (and even more) was entirely acceptable. The initial memory footprint is usually also negligible due to the fact that a large amount of memory would be dedicated to the application server anyway.
The paradigm has shifted in the world of containers and Kubernetes. The boot time has become highly critical. A low boot time is what would allow a service to scale up and down quickly and achieve higher workload density on cloud infrastructures. A minimal initial memory footprint per instance is what would allow the service to start small and be scaled efficiently when needed. In the extreme case, when considering the rise of Functions as a Service booting up quickly becomes even more critical. In this case we aim at scaling the service down to zero instances when there are no requests and starting it only when client requests are coming in. We can see here that the boot time needs to be several orders of magnitude lower than what we are used to.
Given this context, we can now better understand the value that Quarkus brings. In short, it's a framework that enables dev teams to use widely adopted Java libraries to build applications that have an extreme low boot time and low initial memory footprint. Quarkus takes advantage of GraalVM to compile java projects into a native executable that can just run.
Now lets go ahead and build our first hello world to see how it performs.
This is the structure of the project :
The dependencies are pretty minimalist and clean since most of it is taken care of by the quarkus bom and plugins.
The plugin creates a simple project with a rest service operation returning hello as you can see in the file GreetingResource.java. It is pretty much the only thing that needs to be done here to have a running service. Quarkus is rather an opinionated framework that aims at accelerating development using configuration files and annotations.
Now lets go ahead and run this project to see how fast it actually boots up.
We should bare in mind that here we are using the OpenJDK HotSpot and are not yet compiling our project to a native executable. The results are already pretty remarkable as I could observe a boot time of 60.2 milliseconds.
In order to compile the project we need to setup GraalVM. Download the VM from the following website http://www.graalvm.org/downloads/. Extract the package somewhere and set the env variable GRAALVM_HOME to point to the root of its folder.
Now we can run the following command to build a native executable.
We run the native executable with the following command.
We can observe here that the boot time is enhanced by a significant order of magnitude which is just a fraction of a millisecond. To be precise 0.4 milliseconds. This is simply an incredible result.
Now the good surprises don't end there. Since the boot times are so good, it also solve a big challenge for development workflow. In fact, Quarkus also implements a livereload mechanism to reflect the changes performed on the code instantaneously. Try to change some of the code in the project, hit Ctrl+s and we can observe how fast the service reloads to take the changes into account. This is a big leap for developer productivity. As we can see here it took only 38.6 milliseconds to reload.
Now that we have our hello world running. Let's try to add Camel to the mix to enable reusable integration patterns and connectors in our projects. Quarkus already offers a variety extensions and Camel is one of those. At the time of writing there are just a few extensions available. We won't get the whole set of 200+ Camel components compiled to native executable packages, but I'm quite sure that the Quarkus ecosystem will grow quickly.
Let's list the available extensions.
mvn quarkus:list-extensions
Then let's add the camel extension to it.
mvn quarkus:add-extension -Dextensions=io.quarkus:quarkus-camel-core
As a result you should see the dependency to the quarkus camel extension being added to the pom file
Lets create a simple class containing a Camel route to see if things work. Add a new class called CamelRouteBuilder to the source folder. With the following content.
At the time of writing there is no documentation on how to get started with camel in Quarkus. I found an error just trying to run this class complaining about properties not being available.
Property with key [camel.defer] not found
Searching through the source code I found that it is looking some properties in the application.properties file. The one file of interest can be found here
Update July 4, 2019 : As of today, version 0.18 is out now the camel core plugin has changed and does not require to add those properties anymore
So lets go ahead and create a file named application.properties in the folder src/main/resources with the following content
camel.defer=false camel.conf= camel.confd= camel.routesUri= camel.dump=false
Now we can run our project with
mvn compile quarkus:dev
We can note that the boot time is a bit higher when including camel, it is now 1.509s.
Let's compile it to a native executable and see how it behaves.
mvn package -Pnative /target/quarkus-camel-first-impressions-1.0-SNAPSHOT-runner
We can see that the boot time is a fraction of a millisecond, 0.7 milliseconds which is absolutely amazing!
Other resources
Originally published March 15, 2019
Latest update July 04, 2019
Related posts :