How to Create Microservices Using Spring
Let’s consider the use case of BookMyHotel Web Application, developed by a company known as MyInternetSolutions.
Join the DZone community and get the full member experience.
Join For FreeIn this article, we will understand how to create Spring-based Microservices using a Use Case.
Use Case
Let’s consider the use case of BookMyHotel Web Application, developed by a company known as MyInternetSolutions.
Customer visits this site gets registered, search for the hotels, and book the selected hotel.
Modules in this application are —
Customer Registration, Search, Hotel, and Booking.
The Registration module will be used to register the customer in the web application. A search module will be used to search the hotels based on city, state, and country. The hotel module is used to retrieve the existing hotel details. The booking module is used to book the hotel and view all the bookings of a specific customer.
Monolithic Architecture
The above screenshot shows a monolithic application that takes care of all the scenarios of BookMyHotel.
Let’s look at some of the characteristics of this monolithic application -
Persistence: All the data related to the monolithic BookMyHotel application is stored in a single database type.
Language/Framework: All Modules – Search, Hotel, etc. are developed using a single language/framework, and there is a long term commitment to a technology stack.
Testing and Deployment: Changes require a lot of testing, and the complete application is required to be deployed and redeployed. This is an obstacle to frequent deployments.
Scaling: Scaling is inefficient. For example, The search module requires more scaling than other modules as a lot of different searches are done. Hotel Module requires more scaling than the booking part of the application as many hotels are checked before actual booking. But as this is a monolithic application, the complete application has to be scaled individually.
Onboarding Time: New developers get intimidated and take a long time to understand the complete design and code.
Microservices Architecture
Let’s break our monolithic BookMyHotel application into microservices.
Microservices represent the decomposition of monolithic business systems into independently deployable services. Each service represents — a business capability or the smallest unit of a large system that delivers business value. Each microservice runs in its own process, and all the independent units work together to build the complete application.
As per our use case, we are creating 4 microservices -
Let’s look into the advantages of breaking BookMyHotel monolithic application into microservices –
Polygot persistence: We can have multiple storage systems. Registration Database and Hotel Database can be different if required as per the use case.
Language/ Framework: The microservices are not required to depend on a single Language/Framework. For search microservice, we can use a framework that provides fast searching techniques. For other microservices, we can choose a different framework as per our requirement.
Change in Technical Stack: This eliminates Long-Term Commitment to a single Technical Stack. If we get a better framework for searching than presently available, we can change our search microservice without impacting other microservices.
Independent Codebase/Deployments: Microservices’ change cycles are decoupled.Independent/ frequent deploys are possible.
Testing: - Only the changed microservice can be tested.
Efficient Scaling:- Scaling can be efficient now. Scaling can be done according to the hits expected per microservice.
Faster Onboarding and code maintenance:- Developers can be assigned to one or two microservices. Less code/business logic is less intimidating to developers. Teams can be independent of each other.
Microservices With Spring
We can create microservices using Spring Boot and Spring Cloud.
Spring Boot
Spring Boot helps in auto-configuration and dependency management.
Auto Configuration
Spring Boot is used to reducing the configuration and work with sensible defaults. It is mostly based on classpath contents and some input property values in certain cases. But you are not stuck with whatever spring boot is offering you.
A sample code using Spring Boot is shown below –
@SpringBootApplication annotation consists of multiple annotations, and one of them is @EnableAutoConfiguration. When this annotation is used, Spring Boot automatically creates needed beans. Spring boot makes these decisions whenever an application starts up.
For example, Spring boot checks - Is Spring Security library on the classpath? If it is, then configure a fundamental security setup. But if the user has configured security settings, then give that preference.
Spring Boot does not generate code to start the application. There is already code written which will evaluate the classpath contents and make decisions accordingly.
Dependency Management
All of us have done dependency management in our project. We have added Hibernate libraries, Jackson libraries, etc., and we all know that if the library versions are incompatible with each other, we face a lot of issues, right?
It kills a lot of our time. We need to decide which versions of the libraries will play well with others. Spring boot helps in this area also.
Notice this screenshot where spring boot parent is defined with the version as 2.3.7
And in the screenshot below, some of the starters are specified as dependencies -
We add spring boot dependencies known as starters. We do not need to provide a version for any of these dependencies in our build configuration as the dependency jar files are downloaded based on the spring boot starter parent version.
The library included by each starter is compatible with each other under some spring boot parent version. When we upgrade the Spring Boot parent starter version, these dependencies will also be upgraded consistently.
Deploying Spring Boot Web Applications
Let’s look into the options to deploy the spring boot web application -
Deployment on External Server
Web application deployment is possible on any Servlet 3 container.
Deployment on Embedded Server
With Spring Boot Application, a server - tomcat/jetty/undertow can be started when we start our application instead of picking and deploying our application to the external server. The deployable unit contains an Embedded Server. So we can run our web application as a java application, and the server also starts up.
Spring Cloud
Spring Cloud helps developers to build distributed applications quickly. We face many problems while working with distributed systems, and this framework helps with some of the common patterns in this area:-
- Discovering a distributed service
- Load balancing
- Routing
- Service failures
- Configuration management etc.
For microservices architecture, spring cloud helps in all the above things and more, making it easier to develop, use, and manage microservices.
Spring Cloud is a set of libraries to create applications that run on On-Premises or Cloud-like Cloud Foundry, AWS, etc.
Some of the Spring Cloud libraries for MicroServices are –
- Spring Cloud Netflix
- Spring Cloud Consul
In this article, we will create microservices using Spring Cloud Netflix.
Netflix Components Overview
Netflix is one of the organizations that switched from monolithic to microservices architectures. Netflix has a set of frameworks and libraries for developing microservices.
Spring Cloud Netflix integrates the Netflix components in the Spring environment using the auto-configuration of Spring Boot.
Let's have an overview of some of the Netflix components -
Netflix Eureka
What Is Eureka Server?
Eureka is Discovery Server with REST Endpoints. Microservices call the Eureka REST API to register themselves. The Eureka client locates the registered microservice by connecting to the REST endpoint of Eureka Server.
This discovery server maintains a service registry that has a microservice identity and its details.
In the above example, Search Hotel Microservice is registered with Eureka, and the web application is locating the Search Hotel Microservice using Eureka.
Microservices can also locate each other through the Eureka Server.
Eureka Server and Client Component
Eureka consists of a server component and a client-side component. The server is the registry in which all microservices register their availability.
The microservices and consuming clients like WebApp use the Eureka Client to register itself with Eureka Server and discover the other microservices.
Netflix Ribbon
In the real world, there could be many instances for a single microservice.
But if there are multiple instances of a single microservice, then ideally, we should use a load balancer.
Companies have initially thought of using Server-side load balancers but didn’t find the results satisfactory, so they have decided to use a client-side load balancer.
In the above screenshot, two instances of Registration Microservice are registered with Eureka. BookMyHotel WebApp has retrieved all the instances of Registration Microservice from Eureka Server.
Netflix Ribbon is a client-side library for load balancing. So BookMyHotel WebApp will use the Ribbon to load balance between these microservice instances, choose a microservice instance-based other on the load balancing algorithm, and connect to it.
In Eureka Clients, a background thread runs at the client-side, connecting to the Eureka Server and retrieving the complete registry. The complete registry is cached at the client-end, so WebApp will look at its local cache to retrieve registration. Background instances thread will sync with Discovery server at the interval of 30 seconds.
If WebApp tries to connect the Registration microservice instance which is down, it will get an error. But we don’t want WebApp to fail; we want it to retry to next available instance anRibbon can configure this retryRibbon can configure this retryn. We can also configure the count of retry and timeout for the same i.e. it will help BookMyHotel WebApo keep retyinuntilll some count until ifindsnd a working instance if not found, then time out.
Open Feign
Feign is a declarative web service client. Instead of writing the client code to call REST Services, use feign at the client side to call webservices.
We just need to declare and annotate the interface while the implementation is auto generated at runtime.
The aim of feign is to connect the client to the REST Services with minimal overhead and code.
Netflix has stopped supporting Feign and transferred Feign to open-source community . The new project is known as OpenFeign.
Building a Microservices System With Spring Cloud Netflix
Understand MONOLITHIC APPLICATION — BookMyHOTEL
How to Start Eureka Server
How to Register Microservices to Eureka Server
How to Use Ribbon for Client Side Load Balancing
How to Use Feign for Declarative Rest API Calls
Hope this article is helpful in starting you on microservices.
Opinions expressed by DZone contributors are their own.
Comments