In this Microservices Architecture Spring Boot tutorial, we will discuss to creating a microservices with spring and will see microservices architecture. Microservices allow large systems to be built up from a number of collaborating components. Microservices allows doing loose coupling between application processes instead of loose coupling between application components as Spring does.
Microservices is not a new term. It coined in 2005 by Dr Peter Rodgers then called micro web services based on SOAP. It became more popular since 2010. Microservices allows us to break our large system into the number of independent collaborating processes. Let us see below microservices architecture.
Microservices architecture allows avoiding monolith application for the large system. It provides loose coupling between collaborating processes which running independently in different environments with tight cohesion. So let’s discuss it by an example as below.
For example imagine an online shop with separate microservices for user-accounts, product-catalog order-processing and shopping carts. So these components are inevitably important for such a large online shopping portal. For online shopping system, we could use following architectures.
In this architecture we are using Monolith architecture i.e. all collaborating components combine all in one application.
In this architecture style, the main application divided into a set of sub-applications called microservices. One large Application divided into multiple collaborating processes as below.
There are a number of moving parts that you have to set up and configure to build such a system. For implementing this system is not too obvious you have to know about spring boot, spring cloud and Netflix. In this post, I will discuss one example for this architecture before the example lets first discuss pros and cons of microservices architecture.
Popular Tutorials
There are many use-cases supported by Spring Cloud like Cloud Integration, Dynamic Reconfiguration, Service Discovery, Security, Client-side Load Balancing etc. But in this post we concentrate on following microservices support
Spring Cloud support several ways to implement service discovery but for this, I am going to use Eureka created by Netflix. Spring Cloud provides several annotation to make it use easy and hiding lots of complexity.
Each service typically deployed as multiple instances for fault tolerance and load sharing. But there is the problem how to decide which instance to use?
We will use Netflix Ribbon, it provides several algorithms for Client-Side Load Balancing. Spring provides smart RestTemplate for service discovery and load balancing by using @LoadBalanced annotation with RestTemplate instance.
@ImageSource-Spring.io
<dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.hsqldb</groupId> <artifactId>hsqldb</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies>
Step 1: Creating Discovery Service (Creating Eureka Discovery Service)
application.yml
# Configure this Discovery Server eureka: instance: hostname: localhost client: #Not a client registerWithEureka: false fetchRegistry: false # HTTP (Tomcat) port server: port: 1111
DiscoveryMicroserviceServerApplication.java
package com.doj.discovery; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer; @SpringBootApplication @EnableEurekaServer public class DiscoveryMicroserviceServerApplication { public static void main(String[] args) { SpringApplication.run(DiscoveryMicroserviceServerApplication.class, args); } }
pom.xml
<!-- Eureka registration server --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka-server</artifactId> </dependency>
For Whole Source Code for the Discover Server Application, you could download from GitHub as below link.
Run this Eureka Server application with right click and run as Spring Boot Application and open in browser http://localhost:1111/
Step 2: Creating Account Producer MicroService
Microservice declares itself as an available service and register to Discovery Server created in Step 1.
Let’s see the service producer application structure as below.
application.yml
### Spring properties # Service registers under this name spring: application: name: accounts-microservice # Discovery Server Access eureka: client: serviceUrl: defaultZone: http://localhost:1111/eureka/ # HTTP Server (Tomcat) Port server: port: 2222 # Disable Spring Boot's "Whitelabel" default error page, so we can use our own error: whitelabel: enabled: false
AccountsMicroserviceServerApplication.java
package com.doj.ms.accounts; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; @SpringBootApplication @EnableDiscoveryClient public class AccountsMicroserviceServerApplication { public static void main(String[] args) { SpringApplication.run(AccountsMicroserviceServerApplication.class, args); } }
pom.xml
<dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> </dependencies>
Other required source files related to this application you could download from GitHub link as given below
Now run this account service application as Spring Boot application and after few seconds refresh the browser to the home page of Eureka Discovery Server at http://localhost:1111/ in previous Step 1. Now one Service registered to the Eureka registered instances with Service Name “ACCOUNT-MICROSERVICE” as below
Step 3: Consumer Service
Let’s see the consumer application structure as below.
application.yml
# Service registers under this name # Control the InternalResourceViewResolver: spring: application: name: accounts-web mvc: view: prefix: /WEB-INF/views/ suffix: .jsp # Discovery Server Access eureka: client: serviceUrl: defaultZone: http://localhost:1111/eureka/ # Disable Spring Boot's "Whitelabel" default error page, so we can use our own error: whitelabel: enabled: false
WebclientMicroserviceServerApplication.java
package com.doj.web; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; import org.springframework.cloud.client.loadbalancer.LoadBalanced; import org.springframework.context.annotation.Bean; import org.springframework.web.client.RestTemplate; @SpringBootApplication @EnableDiscoveryClient public class WebclientMicroserviceServerApplication { public static final String ACCOUNTS_SERVICE_URL = "http://ACCOUNTS-MICROSERVICE"; public static void main(String[] args) { SpringApplication.run(WebclientMicroserviceServerApplication.class, args); } @Bean @LoadBalanced public RestTemplate restTemplate() { return new RestTemplate(); } @Bean public AccountRepository accountRepository(){ return new RemoteAccountRepository(ACCOUNTS_SERVICE_URL); } }
pom.xml
<dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-ribbon</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <!-- These dependencies enable JSP usage --> <dependency> <groupId>org.apache.tomcat.embed</groupId> <artifactId>tomcat-embed-jasper</artifactId> <scope>provided</scope> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>jstl</artifactId> </dependency> </dependencies>
Other required source files related to this application you could download from GitHub link as given below
web client-microservice-server
Now run this consumer service application as Spring Boot application and after few seconds refresh the browser to the home page of Eureka Discovery Server at http://localhost:1111/ in previous Step 1. Now one more Service registered to the Eureka registered instances with Service Name “ACCOUNTS-WEB” as below
Lets our consumer consume the service of producer registered at discovery server.
package com.doj.web; import java.util.Arrays; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.client.RestTemplate; /** * @author Dinesh.Rajput * */ public class RemoteAccountRepository implements AccountRepository { @Autowired protected RestTemplate restTemplate; protected String serviceUrl; public RemoteAccountRepository(String serviceUrl) { this.serviceUrl = serviceUrl.startsWith("http") ? serviceUrl : "http://" + serviceUrl; } @Override public List<Account> getAllAccounts() { Account[] accounts = restTemplate.getForObject(serviceUrl+"/accounts", Account[].class); return Arrays.asList(accounts); } @Override public Account getAccount(String number) { return restTemplate.getForObject(serviceUrl + "/accounts/{id}", Account.class, number); } }
Let’s open web application which is a consumer of the account microservice registered at Eureka Discovery Server.
http://localhost:8080/ as below
Now click on View Account List then fetch all accounts from account microservice.
http://localhost:8080/accountList
Now click on any account from the list of accounts to fetch the details of the account for account number from account microservice.
http://localhost:8080/accountDetails?number=5115
Load Balanced RestTemplate
Create using @LoadBalanced– Spring enhances it to service lookup & load balancing
@Bean @LoadBalanced public RestTemplate restTemplate() { return new RestTemplate(); }
Must inject using the same qualifier-
@Autowired @LoadBalanced protected RestTemplate restTemplate;
Load Balancing with Ribbon
Our smart RestTemplate automatically integrates two Netflix utilities
Eureka returns the URL of all available instances
Ribbon determine the best available service too use
Just inject the load balanced RestTemplate automatic lookup by logical service-name
7. Summary
After completion of this article you should have learned:
Spring Boot Related Topics
Strategy Design Patterns We can easily create a strategy design pattern using lambda. To implement…
Decorator Pattern A decorator pattern allows a user to add new functionality to an existing…
Delegating pattern In software engineering, the delegation pattern is an object-oriented design pattern that allows…
Technology has emerged a lot in the last decade, and now we have artificial intelligence;…
Managing a database is becoming increasingly complex now due to the vast amount of data…
Overview In this article, we will explore Spring Scheduler how we could use it by…