Quarkus – A New Look At Cloud Native Java

Hello, Habr!

In the coming new year, we plan to seriously develop container themes, Cloud-Native Java and Kubernetes. A logical continuation of these topics in Russian will be the story about the Quarkus framework, already considered in a good article on Habré. Today's article focuses not so much on the "subatomic ultrafast Java device" as the perspectives that Quarkus brings to Enterprise.

Java and the JVM are still extremely popular, but when working with serverless technologies and cloud-oriented microservices, Java and other languages ​​for the JVM are used less and less, as they take up too much memory space and load too slowly, which makes them unsuitable for use with short-lived containers. Fortunately, this situation is currently starting to change thanks to Quarkus.

Introduction

The tighter I do DevOps, containers and serverless technologies, the more I find that I'm writing my containerized code in light containers or FaaS in Python or JavaScript. Java is just too heavy to bootto use it in a serverless framework. Regarding microservices, JavaScript or Python provide faster loading and more compact containers, making Java more efficient.

Python and JavaScript are the best languages ​​for creating cloud-based microservices

Java language more than 20 years, and at the time of its inception, the world was completely different than now. With the advent of the JVM, huge problems were resolved – we were able to write code once and run it on many platforms and operating systems. Containers allow you to pack applications, libraries, and operating system resources into separate containers, and each such container can work anywhere. The portability provided by the JVM is now less relevant. At one time, we were ready to incur additional costs to ensure portability, but now these times have passed. Now you need fast work with minimal delays and reactive applications that will always be available. Containers and container orchestration tools such as Kubernetes provide these capabilities regardless of programming language.

Companies that are transitioning to the use of microservice architectures take their existing Spring services, written in Java, link them to weighty jar archives, add Jdk and run in a container running Linux. This solution works, but you have to deal with heavy containers of 500MB in size, which are brought into an accessibility state for 10-30 seconds each; this is a serious problem. After the migration, many companies are slowly switching to using Python, leaving the server-side services in Java, and, in the end, stop at FaaS.

Serverless technologies and FaaS are very popular today because they allow you to concentrate on writing functions without worrying about the infrastructure. Be that as it may, they all work in containers, but the cloud provider manages their life cycle. The best part is that, after a certain time, the provider completely stops the container and resumes its work only after the next call, that is, you only pay for the actual work time. The first function call may last a little longer than usual, this is the famous cold start. The fact is that the container needs primary loading. Using Python or JavaScript is not such a big problem, but in the case of Java, initial loading can take 10-15 seconds, and this is a sentence and one of the reasons for the decline in popularity of Java. Now we need code that can run, complete the task, and then stop. We don’t want to deal with many threads or long-running processes, we need short-lived processes that can load very quickly.

Introducing Quarkus

If you read technical blogs or follow the news, then you probably think that the serverless paradigm is taking over the world, and everyone takes it with extreme enthusiasm. Now, a startup can write functions and provide them in the cloud as a service – thanks to the use of JavaScript – and also scale them to support millions of users, without the need to manage the infrastructure. True, there is also a real world outside Silicon Valley: financial institutions, government, retail, and many other industries served with millions of Java lines, which are too expensive to rewrite. Therefore, we have to take for granted the fact that in these industries it remains to continue to use heavy containers.

GraalVM and, in particular, Substrate VM, today open the door to the glorious and long-term future of the Java language. GraalVM is universal virtual machine to run applications written in JavaScript, Python, Ruby, R and languages ​​for the JVM, in particular Java, Scala or Kotlin. The coolest thing GraalVM allows you to pre-compile (in AOT mode) programs into a native executable file. This means that you can compile your Java code directly into machine-specific code. The resulting program does not work on Java HotSpot VM, but uses all the necessary components, in particular, memory management, scheduling threads from another implementation of a virtual machine called Substrate VM. Substrate VM is written in Java, and its code is compiled into a native executable. The resulting program starts up faster and, therefore, has lower memory overhead compared to the Java VM. This is great, but you probably think: compilation in advance? It contradicts the basic idea for which the JVM was created, that is, the use of once-written code everywhere! This is crazy !!! However, think for yourself: now we have containers, and they don’t need a JVM. Ordinary container applications created using Spring boot have an extra level of abstraction, which is absolutely unnecessary in the world where Kubernetes is. You have a Java application running on the JVM inside the container, this container remains unchanged, because today the finished product is a container, not an application. Now we are packing containers, not WAR files. Therefore, all costs associated with using the JVM application inside the container become useless, and AOT becomes a very logical decision if you are going to pack your applications in containers.

True, AOT compilation seriously limits the dynamic capabilities of Java (loading classes at runtime, reflection, proxies, etc.). In practice, this means that 90% of the Java ecosystem will not work without change. Respectively, Java ecosystem needs to adapt. There is good news: most of this can be done during assembly!

This is the power of Quarkus. It uses GraalVM and provides an ecosystem that supports AOT compilation at build time; thus, using Java, you can create native binaries. Thanks Quarkus, GraalVM available to Java developers.

Getting started with Quarkus

As explained above, Quarkus provides early compilation for Java applications, and thus produces an ecosystem of supersonic subatomic Java; Quarkus is characterized by ultra-fast loading – and Java returns to the game on the field of cloud-oriented development. For years, no new technology has inspired me – and I'm not alone in this.

Read the beginner's guide – and see for yourself. There are still many companies using Java + JPA inside the container, but in such a configuration, loading may take 15 seconds, and in the case of Quarkus, 0.005!

Quarkus Stats

You use the same IDE and the same tools you are used to in the Spring Boot world. To build your project, use Maven or Gradle. The project can be run directly in the IDE and on top of it, a hot live reboot is available for you with any changes, and you do not need to restart the application. Quarkus is not Spring, so if you use Spring Boot, you will have to migrate Spring-specific code. Fortunately, Quarkus provides a level of compatibility for implementing Spring dependencies, which greatly simplifies the work. The Quarkus framework is standards-compliant, which means ease of porting and support for its code.

Quarkus Development Process

Quarkus can be used in development mode, which is reminiscent of Spring Boot. With it you can also pack your project in thick jar. This is very convenient for testing and debugging your code, since live rebooting is supported; but you need to compile in advance to get into production. The whole process is shown in the following diagram:

  • First, build the application in your favorite IDE, and then you can run it in developer mode with: “mvnw compile quarkus: dev”, As a Spring Boot application would do. You can also pack it in a thick jar.
  • As soon as you finish the previous step and the result suits you – you are ready to create the Java binary file, just run: “mvnw package -Pnative" This will take some time, as native code will be generated during compilation in advance! When this step is completed, you will have at your disposal an ultra-small and ultra-fast executable file, but it can only work on your platform / OS, that is, it will not be ported! But this is normal, since we can put it in a container – and thus ensure portability. Here's how to do it: ./mvnw package -Pnative -Dnative-image.docker-build = true4 – and we remove the executable from the Docker container, that is, we perform native assembly inside the container and create a binary file. This technique may not work on your laptop if its operating system differs from the target platform indicated in the file. Dockerfilegenerated by Quarkus during the creation of the project.
  • Then, after you have the binary, just create an image based on the docker file. docker build -f src / main / docker / Dockerfile.native -t quarkus-quickstart / quickstart .
  • Finally, the application can be launched in Docker or Kubernetes: docker run -i --rm -p 8080: 8080 quarkus-quickstart / quickstart

Quarkus Features

Quarkus has much more features than native Java code.

  • Unification of imperative and reactive capabilities: allows you to combine familiar imperative code with non-blocking code written in a reactive style.
  • The developer is pleased: a unified configuration, Zero config, live-reboot in no time, optimized streamlined code for 80% of common cases and flexible code for the remaining 20% ​​of cases, generation of native executable files without fuss, live-coding.
  • Amazingly fast loading, an incredibly small resident memory area (yes, it’s not only about the size of the heap!), Which provides almost instant vertical scaling and very dense memory use when orchestrating containers on platforms such as Kubernetes. See more details.
  • Quarkus offers a holistic, user-friendly full-stack framework, with first-class libraries that you know and love embedded in the supporting structures. More details.
  • Hibernate, JPA, REST, JWT, etc. libraries are supported.
  • Supported configurations deployed in Kubernetes and OpenShift
  • Open tracing using Jaeger
  • Kotlin Support
  • Messaging with Kafka, Camel …
  • And much more, check out the list of extensions!

Quarkus ecosystem

In short, you can now run traditional JPA / JTA transactional services in super-fast lightweight containers – both in the cloud and on the premises.

Quarkus example

In this section, let's take a simplified look at the beginner's guide to give you an impression of the power of Quarkus.

The easiest way to create a new Quarkus project is to open a command prompt window and run the following command in it:

mvn io.quarkus: quarkus-maven-plugin: 0.12.0: create
-DprojectGroupId = org.acme
-DprojectArtifactId = getting-started
-DclassName = "org.acme.quickstart.GreetingResource"
-Dpath = "/ hello"

This generates a Maven project with GreetingResuce providing the endpoint / hello. Dockerfile docker images for native files and jvm (traditional images in the form of thick jar) are also generated. The code is very clean and simple:

@Path ("/ hello")
public class GreetingResource {@GET
    @Produces (MediaType.TEXT_PLAIN)
    public String hello () {
        return "hello";
    }
}

To start the application, use: ./mvnw compile quarkus: dev

The application is packaged using the ./mvnw package. The result is 2 jar files:

  • getting-started-1.0-SNAPSHOT.jar – contains only classes and project resources. This is a common artifact resulting from the assembly of Maven;
  • getting-started-1.0-SNAPSHOT-runner.jar is an executable jar. Note that this is not super-jar, there are dependencies here, they are copied to the target / lib directory.

You can start the application using: java -jar target / getting-started-1.0-SNAPSHOT-runner.jar

Then you need to download and install GraalVM and set the environment variable GRAALVM_HOME.
Now you can create a native executable with: ./mvnw package -Pnative -Dnative-image.docker-build = true.
Here's how to create a Docker image: docker build -f src / main / docker / Dockerfile.native -t quarkus-quickstart / quickstart .
Now it can be launched using any container orchestration engine, in case you use minishift:

kubectl run quarkus-quickstart --image = quarkus-quickstart / quickstart: latest --port = 8080 --image-pull-policy = IfNotPresent

kubectl expose deployment quarkus-quickstart –type = NodePort

That's all!; Now you have a container with a Java REST service that starts in 0.004 seconds!

Conclusion

Now I understand why I am so fascinated by the Quarkus framework supported by Red Hat. I really believe that it will change the technological landscape of Java and provide large traditional enterprises with a real opportunity to migrate to the cloud.

Kubernetes + Knative + Quarkus Change the rules of the game in a cloud-oriented development and will please any Java developer.

This repository has many interesting examples!

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *