Create a JVM microservice in less than 10MB with Micronaut

In this blog post, we will create a simple hello-world microservice by using the Micronaut framework. We will explore why Micronaut has gained so much popularity in the last few years despite being the presence of other famous framework like Spring, Dropwizard etc.

Micronaut is a modern, JVM based, full-stack framework for building modular, easily testable microservice applications. Micronaut integrates cloud technologies into the framework, and microservice patterns such as service discovery, distributed tracing, circuit breaker are baked into the framework.

Micronaut has 100% compile-time, reflection free, dependency injection and AOP. Thus, Micronaut applications are small and have a low memory footprint.

This post was first posted on : https://ishantgaurav.in/

Let’s create a simple microservice and deploy it to learn how Micronaut work. Later on we will also verify the cold boot time and memory foot print of the created microservice using VisualVM tool.

I will be using the micronaut-cli tool to create the micronaut application. You can install and read about it from here Micronaut Command Line Interface.

Run the below command to create new micronaut microservice.

mn create-app ishant.micronaut.sample-service --build=maven --lang=java

Once your above command is complete, you will have an application created like this.

Once the application is created we would have two main file which we need to look upon:

pom.xml :

We can see in the pom file that, by default micronaut install few dependencies like validation, test, http and http-server etc.

<dependencies>
    <dependency>
      <groupId>io.micronaut</groupId>
      <artifactId>micronaut-inject</artifactId>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>io.micronaut</groupId>
      <artifactId>micronaut-validation</artifactId>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>org.junit.jupiter</groupId>
      <artifactId>junit-jupiter-api</artifactId>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>org.junit.jupiter</groupId>
      <artifactId>junit-jupiter-engine</artifactId>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>io.micronaut.test</groupId>
      <artifactId>micronaut-test-junit5</artifactId>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>io.micronaut</groupId>
      <artifactId>micronaut-http-client</artifactId>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>io.micronaut</groupId>
      <artifactId>micronaut-http-server-netty</artifactId>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>io.micronaut</groupId>
      <artifactId>micronaut-runtime</artifactId>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>ch.qos.logback</groupId>
      <artifactId>logback-classic</artifactId>
      <scope>runtime</scope>
    </dependency>
  </dependencies

We can see in the pom file that, by default micronaut install few dependencies like validation, test, http and http-server etc.

Application.java

package ishant.micronaut;

import io.micronaut.runtime.Micronaut;

public class Application {

    public static void main(String[] args) {
        Micronaut.run(Application.class, args);
    }
}

Now let’s create a simple GET controller to return “Hello Micronaut” as below:

HelloController.java

package ishant.micronaut;

import io.micronaut.http.MediaType;
import io.micronaut.http.annotation.Controller;
import io.micronaut.http.annotation.Get;
import io.micronaut.http.annotation.Produces;

@Controller("/hello")
public class HelloController {

    @Get
    @Produces(MediaType.TEXT_PLAIN)
    public String hello() {
        return "Hello Micronaut";
    }
}

As our controller is created, now we will deploy and our application via IntelliJ idea itself and also we will make the maximum memory allocation to 10 MB.

Once the application is deployed, let’s go to VisualVM check the memory foot print of our microservice.

Memory Foot Print :

As you can see in the Heap space of our sample-service, it is only taking 7.2 MB, which is even less than the maximum space of 10MB which we allocated to this microservice.

Cold Boot Time :

From the above image, we can see the cold boot time of our sample service is 1.9s which would be more less if you have good configuration in your system. I am running this on Ubuntu 20.04, 8 GB Ram and i5 processor.

Conclusion

So we saw how Micronaut can help in developing cloud native microservice, which has very less foot print and the cold boot time. Micronaut achieved this through the use of Java’s annotation processors, which are usable on any JVM language that supports them, as well as an HTTP Server and Client built on Netty. To provide a similar programming model to Spring and Grails, these annotation processors precompile the necessary metadata to perform DI, define AOP proxies and configure your application to run in a low-memory environment.

This is all from this Post, if you find anything incorrect or have different thoughts, please comment below in the comment box.

20