This is the first post in what will be a 4-part series on building a microservice architecture with Spring Boot & Docker. This post will provide an overview of what we mean when we talk about a microservice architecture, as well as the concept of containerization.
As more products are being built around reusable REST-based services, it has been quickly discovered that splitting out your business functions into reusable services is very effective, but also introduces a risk point. Every time you update a service, you have to re-test every other service that is deployed along with it — even if you’re confident the code change wouldn’t impact the other service, you could never really guarantee it because the services inevitably share code, data, and other components.
With the rise of containerization, you can run code in complete isolation very efficiently; combining these two together allows for a product architecture that optimizes for fine-grained scalability and versioning, but at the cost of increased complexity and some duplicated code.
Not exactly. It does share some similarity, in that containers and virtual machines are isolated environments that are managed by a controlling process (container manager and hypervisor respectively), but the primary difference between the two is that for each virtual machine, an entire stack of components are running — the Operating system up to the application server, and virtual hardware is emulated including network components, CPUs, and memory.
For containers, they operate more as fully isolated sandboxes, with only the minimal kernel of the operating system present for each container. The system resources of the underlying system are shared. The biggest advantage of containerization is the substantially smaller footprint means that for the same hardware, substantially more containers can be run than virtual machines. There are some key limitations of containers: the biggest one is that containers can only run Linux-based operating systems (this kernel isolation is Linux-specific technology).
Related to this limitation is that running Docker – the most popular container provider system — doesn’t run directly on Mac or Windows systems because they are not Linux. Instead, to run Docker containers, you need to start up a Linux Virtual Machine using VirtualBox, then run the Docker containers inside this virtual machine. Fortunately, the vast majority of this is managed by Docker Toolbox (formerly known as boot2docker).
Docker has received so much traction that the public repository of container images, Docker Hub, contains over 136,000 public images. Many of these are created by private individuals, some extending “official” images and customizing them to their needs, but others are entire platform configurations customized from “base” images. We will be leveraging some of these “base” and “official” container images for our study.
I’ve chosen to build my microservices using Java, specifically the Spring Boot framework. This was primarily chosen due to being familiar with Spring, and the ease of developing REST-service controllers, business services, and data repositories with it. This could just as easily be done in Scala with Akka/Play; one of the touted benefits of microservice architecture is full independence of the services, so it shouldn’t matter what language or platform each is built and deployed in.
Personally, I think the maintenance costs of developing with multiple languages is greater than the gains of flexibility, but there are applicable use cases, such as one could be in a situation where one department within a large organization has chosen different technology stacks as “standard.” Another possible scenario where this benefit would apply is if you decide to transition from one language/platform to another — you can migrate one microservice at a time, provided the end web service interface remains the same. Some goals for this effort:
The business scenario that I will model is an employee tasking and recognition system at a software development company. The system covers the following tasks:
This closes out part I pretty well — we have the beginnings of an understanding around microservices, containerization, and a business scenario that we will use as a backdrop for the rest of the discussions. As we move onto part II, we’ll get set up with tooling and dive into how to work with Docker and setting up our first container.
This blog is the first of four parts: