Micronaut for Microservices

J Banks
Software Tidbits
Published in
6 min readJul 8, 2019

About

This article is the first of three sessions providing an introduction to a microservice framework called Micronaut. The framework was introduced to me at a NFJS conference in 2019. At first, I was thinking why would software developers need yet another a microservice framework as there are plenty of options available. What could Micronaut be providing at this point? I decided to dig deeper…

One key finding is that Micronaut appeared in the April 2019 ThoughtWorks Technology Radar as a framework to keep an eye on. It also includes a number of features offerings that are a bit “game changing” in that they address important challenges found in popular frameworks being used for enterprise microservice solutions. Throughout the three sessions, Micronaut’s offerings will be covered and examples of supported modules will be illustrated to get comfortable with the framework.

Session One

The purpose of session one is to introduce Micronaut’s capabilities at a broad-level and assist with determining if Micronaut is worth further investigation. But first, let’s introduce the creators of the framework and the need for yet another framework.

Inception of Micronaut

Micronaut was developed by Object Computing (OCI), creators of the Grails framework. OCI has experience constructing solutions in a number of industries such as commerce, energy, and aerospace. With Micronaut, they have baked-in lessons-learned over years of migrating from monoliths to microservices. Some followers of Micronaut identify the framework as having the best features offered by popular tools such as Spring, Spring Boot, and Grails.

If there are any ownership concerns, it is important to know that Micronaut is an Open Source project licensed under the Apache License v2. There is support, training, and resources offered by OCI. Since the inspiration for Micronaut is from Spring, and the core developers of Micronaut are former SpringSource/Pivotal engineers you get the connection.

Another Microservice Framework?

Wait, don’t we already have Spring and Spring Boot for building microservices? That is correct, Spring and Spring Boot are used to build microservices, and have evolved over the years to be extremely productive for developers. To Spring’s credit, it had to evolve and adapt with features to continue support for monolith application development while the microservices adoption occurred.

As such, Spring, Spring Boot, and Grails all have the ability to construct microservice as well as monolith applications. However, with this support for both models, brings with it a collection of “cruft” that is now being addressed with Micronaut.

New frameworks are specifically built for microservice and serverless development, not having to carry the “extra goodies” required for monolith application development.

Many newer frameworks are now able to address trouble areas in older frameworks that had to build-in support for non-microservice application development. Three such trouble areas that Micronaut address are:

  • service startup
  • memory footprint
  • processing throughput

Performance & Efficiency

Many inversion of control (IOC) frameworks utilize reflection, and with that approach, need to load and cache all constructors, methods, and fields. This makes a framework’s memory footprint and startup time impacted by the size of the code base.

Spring (and Grails), can be costly for startup time and memory. For instance, at startup, Spring has to read all of the bytecode of the beans (*.class files). The I/O and reflection activities are expensive depending on the size of the codebase, hardware, and memory capacity.

Micronaut does at compile time, what Spring does at runtime. If something goes wrong, steps are done at compile time in the IDE as opposed to runtime.

This is a big deal as this really shifts the responsibility to the compiler as opposed to the running virtual machine. This translates to saved developer time as opposed to finding this type of issue outside of the IDE and compiler.

With minimal use of reflection in Micronaut, the startup difference can be drastic. In some cases, this capability can result in a startup of less than 3 seconds for Micronaut. That same code base may take 30 seconds or more with Spring.

The “magic” behind the scenes for dependency injection (DI) involves the following based on the primary language used (remember, Micronaut is a polyglot framework):

  • When using Groovy, AST transformations are used as Micronaut knows the injection points ahead of time. The ASM byte-code library is used to generate those classes.
  • When using Java, annotation processors are used.

In both cases, the classes are generated at compile time due to knowledge of classes implementing the BeanDefinition interface. This interface currently resides in the io.micronaut.inject package and when implemented, the bean type is provided.

public interface BeanDefinition<T>
extends AnnotationMetadataDelegate, Named, BeanType<T>

Contrasted with Spring, with Micronaut there is no need to scan all fields, methods, and classes at runtime. All of that is done at compile time! Also, from a memory standpoint, since Micronaut doesn’t use reflection, there is no need to cache large amounts of reflection metadata. This results in a smaller cache and lower memory footprint for a Micronaut application.

Throughput & Metrics

Processing speed is impacted in a positive way when using Micronaut as it provides fast data access as well as reactive asynchronous invocations. Like any technology, results may vary based on the complexity of your design and application implementation.

When ready to measure processing performance, it’s important to wire-in a library for metrics collection. Micronaut Micrometer is one such project that exists and assists with integration. As of this writing, Micrometer is at 1.2.0.

Using metrics collection is a great way to determine change impacts, bottlenecks, trending, etc. It is highly recommended to establish a metrics collector prior to deploying to production. Having metrics collected in test (especially load & stress) environments can reveal some interesting things you might not expect!

Maturity

As stated earlier, Micronaut, from the ground-up, includes features that are improvements on existing frameworks used to develop and manage microservices. I was pleasantly surprised when I learned that Micronaut already has many of the Spring, Spring Boot, and Grails features that can be brought in with modules and without much of the dependency nightmare that occurs with other frameworks. It’s also important to note that Micronaut brings its own new capabilities, not just direct clones of existing framework features.

Since Micronaut is modular, it supports integration with a plethora of technologies. Examples of some Micronaut modules (not an extensive list) include: Kafka, AWS, Kubernetes, Neo4j, SQL/JDBC, Security, Tests (JUnit5 and Spock), Spring, etc.

When looking at a new technology, many users (developers, executives, operations, etc.) are rightfully skeptical of its maturity. It used to be that looking a version number for a software product or library would be telling of the maturity. That is not the case with Micronaut as at version 1.2.0.RC1, it is packed full of features.

Features

This is a summarized list of offerings currently provided as of version 1.2.0.RC1. When exploring deeper, you will notice that much thought and work was included in newer versions. Given the experience and background of the creators, along with their lessons-learned, it is not surprising to see these capabilities early in the framework‘s existence.

  • Full-stack polyglot framework (Java, Kotlin, & Groovy)
  • Built-in resiliency
  • Modular with reduced external dependencies
  • Reactive & non-blocking
  • Declarative HTTP clients with client-side load-balancing
  • HTTP Routing
  • Low memory consumption
  • Compile-time DI and AOP
  • Support for serverless application development
  • Fast startup, data access, & testing
  • Functions as both a client and server
  • Service Discovery
  • Auto-Configuration and Defaulting
  • Configuration with Sharing

--

--