Rethinking microservices

Emily Jiang
9 min readMay 10, 2023

--

Microservices have been around for over a decade. There are many misconceptions for microservices. Some people are wondering whether microservice is going to die especially in the fast-moving IT industry towards Cloud. Serverless becomes a hot topic. Will microservice survive in the Serverless era?

In this blog, I invite you to step back and rethink microservices. I will start with the history of microservices, then misconception about microservices, best practices of microservices and finally the future of microservices.

The history of microservices[1]

IBM released enterprise java bean (EJB) in 1997. It was to establish communications between the web-based services. However, EJB was too complex, and it only works in Java. Therefore, services using EJB could not communicate with the systems written in other languages. The service-oriented architecture (SOA) was born to address this limitation. The communication between two different services in SOA was accomplished using Simple Object Access Protocol (SOAP). SOAP was released in 1999 by Microsoft. It uses Hypertext transfer protocol (HTTP) to transfer information over the Internet. These messages are in an XML format and are usually sent via HTTP. This approach allows SOAP messages to pass through most firewalls, which don’t normally block HTTP traffic. Due to the complex of the XML styled messages, IT industry began to throw away SOAP during 2005–2007. Shortly after that, from 2008 to 2010, Representational State Transfer (REST) gained more momentum. A REST API uses HTTP request to POST, GET, PUT and DELETE data. These APIs are easy to integrate, easy to use and scalable. In 2011, the services using REST are often refer to small services, microservices. Hence the name of Microservice came into existence. The non-microservice applications have got a new name Monolith, partially due to its size. The history of microservices is illuminated by the diagram below.

The History of Microservices

The definition of Microservice

Microservices [2] are

● Maintainable and testable

● Independently deployable

● Loosely coupled

● Organized around business capabilities

● Owned by a small team

Microservices must be independently deployable, and they normally have frequent release cycle, which is the most important characteristics of being microservices. The releases of multiple microservices should not need any coordination.

There are some misconceptions of microservices.

Microservice Myths

Myth 1:

● The smaller the better

● The more the merrier

Some companies strive for creating a huge number of microservices. This will lead to more problems.

Myth 2:

● Microservices are the destiny

● Monolith will have to be migrated to Microservices

Monolith was badly labelled since the emerging of microservices. Many companies rushed to the migration plan from monolith to microservices. Then they found out the team velocity were decreased. They had to merge microservices back to monolith.

Myth 3:

● Microservices making developers job easier

● Microservices increase productivity

● Microservices boost performance

● Microservices are fast

When there are issues with monolith, such as the slow performance, developers automatically blame monolith and think adopting microservices will solve the problem.

Microservices Facts

To understand and then adopt microservices, you should know the following facts of microservices. Top three facts are listed below.

Microservice Fact 1

● Independent deployment

● Need continuous integration and deployment pipeline (CI/CD)

● Owned by a small team

These facts allow microservices to be independently deployed and isolated from other services. With CI/CD pipeline, microservices can be frequently released to production. Therefore, when adopting microservices, you need to have CI/CD pipeline in place.

Microservice Fact 2

● No code sharing

● No database sharing

Microservices should not share code nor database as microservices are independent and its release cycle must not rely on other services. With code sharing, you will have to coordinate update to the sharing code. The same thing applies to database. You should not share database among microservices to maintain the independent nature of microservices. In this case, you are free to update database schemes and update data without considering other microservices accessing the same data.

Microservice Fact 3

● Language agnostic: Java, Go, Python, etc

You can develop microservices in Java, Go, Python or other languages that you are comfortable with. Since Java has a rich ecosystem, it is an ideal choice for writing comprehensive microservices.

If you think you need to adopt microservices, you should understand that microservices are not the default answer to your questions. You should carefully analyse the issues. If you need to scale up or down part of your monolith, this is a valid reason to adopt microservices.

When adopting microservices, you should know the following microservice essentials.

Microservice Essentials

Microservice is NOT the default answer for your problem

You need to remember that microservices is not the default answer for your problems. If you have issues with the current monolith, you need to find the root cause. Otherwise, even after you convert the monolith to microservices, you might still carry the same problems. You might even end up with distributed monoliths.

Microservice needs a GOOD architecture

If you have decided to go with microservices, you need a good architecture for doing microservices in the correct way. Domain Driver Design (DDD) and Event Driven Design (EDD) are commonly adopted design patterns for designing microservices. I did a survey in May 2022 and it revealed 1/3 applications used DDD for their microservice development. Nearly ¼ applications adopted EDD.

Domain Driven Design (DDD)

Domain Driven Design is an approach to software development that centres the development on programming a domain model that has a rich understanding of the processes and rules of a domain. BoundedContext is an essential pattern in DDD. You can refer to Martin Fowlers’ blog to learn more about BoundedContext.

Event Driven Design (EDD)

Event Driven Design (EDD) is suitable for microservices that use event driven architecture where requires data to be consumed in the form of events. The main benefits of EDD are asynchronous behaviour and loosely coupling structure. Instead of relying on real-time communication, EDD can deliver the data before the request and then consumers can decide when to process the data. It is like the emailing systems. You can send an email with some information to the receiver but you can then move on to do other things without being blocked by the receivers. The receivers can decide what to do with the messages. Besides, with EDD, multiple consumers can consume the same message.

So far, we have explored what microservices are. The fact is that monolith will continue existing for many years and it has every reason to stay. Microservice is suitable for every kind of workload. Microservices and Monoliths will coexist. We should not spend time to debate whether we should do Monolith or Microservice. We should focus on the deployment environment we are aiming for, which is Cloud. What we really need is to build Cloud-Native Applications.

Cloud Native Applications

Cloud Native Application refers to an application that works natively in the cloud. To work natively in the cloud, it should have the following characteristics.

  1. RESTful — like a cattle not a pet, communicative

The application should be RESTful and stateless. In this way, the cloud infrastructure can easily scale up or down based on the workload without losing any information.

2. Configurable

The configuration should be externalized so that any configuration update should not lead application to be redeployed.

3. Fault tolerance

The application must be able to perform well regardless the situations. Even though the downstream services are not working, this application must return a reasonable response to the caller.

4. Can be discovered

When dealing with cloud native applications, normally many applications work together to achieve one common goal. It is important for the applications to self-document what they do.

5. Secure

When working in the Cloud, it is important to secure the end points to prevent unauthorized invokers from accessing some sensitive data.

6. Traceable, monitorable

In the cloud, Day2 operation is ever so important as normally the applications don’t have down time. Monitoring is a key to spot warnings and take some precaution. If something goes wrong, it is a must-have capability to have the diagnose information to identify which cloud-native application is the root cause.

7. Able to communicate with the cloud infrastructure

For being cloud native, the application must be able to communicate with cloud infrastructure such as Kubernetes. It should be able to tell Kubernetes whether it is ready to serve the requests or whether it is going to die so that Kubernetes can recycle the instance. This directly links to Kubernetes Readiness, Liveness and startup checks.

When you read till here, you might feel overwhelming with the above requirements. It could add a huge burden to Cloud Native application developers. Luckily, there are standards such as MicroProfile and Jakarta EE to help you on this.

Cloud Native APIs

MicroProfile and Jakarta EE are two popular standards for developing Cloud Native Applications. They offer very rich APIs for Cloud Native application developers. For being the open standards, they provide APIs in a vendor-neutral way, which means no vendor lock in and many implementations available for you to choose from. The latest Jakarta EE and MicroProfile releases are Jakarta EE 10, released in September and MicroProfile 6.0, released in December 2022.

Jakarta EE 10 Platform

MicroProfile 6.0

Containerisation and Deployment

After you have developed your application, the next step is to containerise the applications and get ready to the deployment. You can use either docker or podman to create an image and then run the image.

After you have verified the images are good, you can upload the image either in docker hub or other registries. Finally, you can deploy the image to the cloud of your choose, which could be private cloud or public cloud or hybrid cloud.

You journey could end here. Up to now, you probably have sensed that microservices are not going to die. However, with the advance of the serverless, is microservice going to live long? Let’s first explore what serverless is about.

Serverless

Serverless is a short name for Serverless computing, an execution model, which cloud providers allocate resources on demand. If a service is not running, it can scale to zero. The Serverless operates on “pay as you go” price model. It is for public cloud only as you will need to rent resources in the cloud. Visit this blog to learn more about Serverless. To make “Scale to Zero” practical, a fast startup is a must. If it takes long time to start a microservice, it will defeat the purpose of serverless. Therefore, fast startup is a key to the success of serverless for microservices. Luckily, microservices can achieve fast startup via GraalVM and CRIU (Checkpoint and Restore in User Space).

GraalVM improves the startup via build time compilation and then generate machine code. However, the runtime performance is static, where the runtime performance for normal VM are improving over time. The other disadvantage is that after generating the machine code, all of the runtime tools for instrumentation are no longer usable. It is not easy to monitor the operation when dealing with machine code.

Due to the disadvantages of the GraalVM, another technology CRIU based on Linux technology was researched. Open J9 and Open Liberty both adopts CRIU technologies called InstantOn (refer here for more details) to improve the startup performance. Liberty InstantOn allows to take checkpoints at three stages (features, runtime and application). The most performant checkpoint is at application, where the application has started before a request was process. In this case, no transaction was performed, nor database was modified. This is the safe point to take point. After taking the checkpoint, the docker image can be committed to the checkpoint image. At runtime, the checkpoint image can be restored due to load. For more information about InstantOn, please visit this Open Liberty blog. The StartUp Time comparison with and without InstantOn are shown below. These experiments were run on a 24 core system. I used taskset -c to allocate 4 CPUs to the Liberty process running in container. The InstantOn times were taken using the applications checkpoint phase.

As you see, microservices can run as a function due to its fast start up.

Summary

In this blog, we looked at the microservice history, followed by the common misconception about microservices. If you decide to adopt microservice, the blog listed some must-know facts, design patterns and best practices. It concludes that microservices and monolith co-existing for a long time. What you really need to concentrate is Cloud Native Applications, which should adopt MicroProfile, Jakarta EE programming model to achieve portability. When we are entering Serverless, will microservice still useable for running as a function? The answer is yes as microservices can start very fast with the help of GraalVM and InstantOn. Let’s finish this blog with “Long live microservices”!

Reference

  1. https://www.dataversity.net/a-brief-history-of-microservices/
  2. https://microservices.io/
  3. Open Liberty

--

--

Emily Jiang

Java Champion, Cloud Native Architect, Conference Speaker, Book Author (ibm.biz/MicroProfileBook), Working on MicroProfile, Jakarta EE, Open Liberty and more