07. Microservices Notes
07. Microservices Notes
Microservices
==============
++++++++++++++++++++++++++
What is Monolith Architecture
++++++++++++++++++++++++++
-> As monolith application contains all functionalities, it will become fat jar/war
+++++++++++++
Advantages
+++++++++++++
1) Simple to develop
++++++++++++++++
Dis-Advantages
+++++++++++++++
1) Difficult to maintain
++++++++++++
Advantages
+++++++++++++
1) Loosely Coupling
2) Easy To maintain
3) Faster Development
4) Quick Deployment
5) Faster Releases
6) Less Downtime
7) Technology Independence
Dis-Advantages
+++++++++++++
1) Bounded Context
2) Lot of configurations
3) Visibility
4) Pack of cards
++++++++++++++++++++++++++
Microservices Architecture
++++++++++++++++++++++++++
-> Most of the projects will use below components in Microservices Architecture
5) Admin Server
Service Registry
++++++++++++++++
-> Service Registry acts as DB of services available in the project
-> It provides the details of all the services which are registered with Service
Registry
-> We can identify how many services available in the project
-> We can identify how many instances available for each service
-> We can use "Eureka Server" as service registry
-> Eureka Server provided by "Spring Cloud Netflix" library
Services
+++++++++
-> Services means REST APIs / Microservices
-> Services contains backend business logic
-> In the project, some services will interact with DB
-> In the project, some services will interact with third party REST API ( external
communication )
-> In the project, some services will interact with another services with in the
project
( inter-service communication )
-> For inter-service communication we will use feign-client
-> To distribute the load, we can run one service with Multiple Instances (Load
Balancing)
+++++++++++
API Gateway
+++++++++++
-> API Gateway is used to manage our backend apis of the project
-> API Gateway acts as mediator between end users and backend apis
-> API Gateway can filter logic to decide request processing
-> API Gateway will contain Routing logic (which request should go to which REST
API)
-> API Gateway also will be registered with Service Registry
++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mini Project Implementation using Microservices Architecture
++++++++++++++++++++++++++++++++++++++++++++++++++++
2) Spring Boot Admin Server (To monitor & manage boot applications)
a) EurekaServer (spring-cloud-starter-netflix-eureka-server)
b) web-starter
c) devtools
server:
port: 8761
eureka:
client:
register-with-eureka: false
Note: If Service-Registry project port is 8761 then clients can discover service-
registry and will register automatically with service-registry. If service-registry
project running on any other port number then we have to register clients with
service-registry manually.
4) Once application started we can access Eureka Dashboard using below URL
URL : http://localhost:8761/
++++++++++++++++++++++++++++++++++++++++++++++++
Steps to develop Spring Boot Admin Server Project
+++++++++++++++++++++++++++++++++++++++++++++++++
a) web-starter
b) devtools
c) admin-server (codecentric)
3) Configure the port number and run the application (port : 1111)
URL : http://localhost:1111/
++++++++++++++++++++++++++++++++
Steps to work with Zipkin Server
++++++++++++++++++++++++++++++++
URL : https://zipkin.io/pages/quickstart.html
URL : http://localhost:9411/
+++++++++++++++++++++++++++
Steps to develop GREET-API
++++++++++++++++++++++++++++
1) Create Spring Boot application with below dependencies
- eureka-discovery-client
- starter-web
- devtools
- actuator
- sleuth
- zipkin
- admin-client
-----------------------------------
application.yml-----------------------------------------
server:
port: 9090
spring:
application:
name: GREET-API
boot:
admin:
client:
url: http://localhost:8080/
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8761/eureka
management:
endpoints:
web:
exposure:
include: '*'
-----------------------------------------------------------------------------------
---------------------------
5) Run the application and check in Eureka Dashboard (It should display in eureka
dashboard)
6) Check Admin Server Dashboard (It should display) (we can access application
details from here)
Ex: Beans, loggers, heap dump, thred dump, metrics, mappings etc...
- web-starter
- devtools
- eureka-discovery-client
- fegin-client
- admin-client
- zipkin-client
- sleuth
- actuator
@FeignClient(name = "GREET-API")
public interface GreetApiClient {
@GetMapping("/greet")
public String invokeGreetApi();
Note: In Rest Controller we should have logic to access another REST API (GREET-
API)
-> Using FeginClient we can make rest call to another service using name of the
service (no need of url)
-> FeginClient will get service URL from service-registry based on service-name
@RestController
public class WelcomeRestController {
@Autowired
private GreetApiClient greetClient;
@GetMapping("/welcome")
public String welcomeMsg() {
server:
port: 9091
spring:
application:
name: WELCOME-API
boot:
admin:
client:
url: http://localhost:1111/
management:
endpoints:
web:
exposure:
include: '*'
6) Run WELCOME-API project (it should register in Eureka and Admin server)
++++++++++++++++++++++++++++++++++++++++++++++++++++++
-> We are running Service Registry project with Eureka Server on 8761 port number
-> Eureka Discovery Client applications are auto-registering with Eureka Server
when port is 8761
-> If we change Eureka Server port number then we have to register Eureka Client
application with Eureka Server using below property in application.yml file
eureka:
client:
serviceUrl:
defaultZone: http://localhost:9090/eureka
Note: We should configure this property in eureka client application yml file
++++++++++++++++++++++++++++++++++++++++++++++++++++++
GREET API URL : DESKTOP-BDG00U7:GREET-API:9090/
==================
API Gateway
==================
-> API Gateway will act as mediator between client requests & backend apis
-> API Gateway will provide single entrypoint to access our backend apis
1) Filters
2) Routing
-> Filters are used to execute some logic before request processing and after
request processing
-> Routing is used to tell which request should go to which REST API
++++++++++++++++++++++++++++++++++++++++
Working with Spring Cloud API Gateway
++++++++++++++++++++++++++++++++++++++++
-> web-stater
-> eureka-client
-> cloud-gateway
-> devtools
-----------------------------application.yml file---------------------------------
spring:
cloud:
gateway:
discovery.locator:
enabled: true
lowerCaseServiceId: true
routes:
- id: welcome-api
uri: lb://WELCOME-API
predicates:
- Path=/welcome
- id: greet-api
uri: lb://GREET-API
predicates:
- Path=/greet
application:
name: CLOUD-API-GATEWAY
server:
port: 3333
-----------------------------------------------------------------------------------
-------------------------
In API gateway we will have 3 types of logics
1) Route
2) Predicate
3) Filters
-> Routing is used to defined which request should be processed by which REST API
in backend. Routes will be configured using Predicate
-> Predicate : This is a Java 8 Function Predicate. The input type is a Spring
Framework ServerWebExchange. This lets you match on anything from the HTTP request,
such as headers or parameters.
-> Filters are used to manipulate incoming request and outgoing response of our
application
Note: Using Filters we can implement security also for our application.
-----------------------------------------------------------------------------------
---------------------------
@Component
public class MyPreFilter implements GlobalFilter {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain
chain) {
keySet.forEach(key -> {
List<String> values = headers.get(key);
System.out.println(key +" :: "+values);
});
return chain.filter(exchange);
}
}
++++++++++++++++++++++++++++++++++++++++++++++++++++++
-> We can validate client given token in the request using Filter for security
purpose
-> Filters are used to manipulate request & response of our application
-> Any cross-cutting logics like security, logging, moniroing can be implemented
using Filters
====================
Sleuth & Zipkin
===================
-> As part of application execution one Rest API can communicate with another REST
API
-> When we send request from UI, it will process by Multiple REST APIs with
Interservice communication
*** How we can understand which rest api is taking more time to process our request
? ***
-> If we add Sleuth dependency in REST API then it will add span-id and trace-id
for log messages
-> If one request is processing multiple REST API then Sleuth will use same span-id
for REST APIs to generate log message
-> By using span-id and trace-id we can understand which REST api has taken more
time process request
-> To monitor span-id and trace-id details we will use ZipKin server
-> Zipkin server is providing user interface (UI) to monitor all the details
Note: The REST APIs which are having sleuth dependency should register with Zipkin
server
======================================
Steps to work with Sleuth and Zipkin
======================================
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-sleuth</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-sleuth-zipkin</artifactId>
</dependency>
4) Run spring boot applications and send a request to rest controller method
5) Verify boot application logs display in console (span-id and trace-id will be
attached to logs)
( URL : http://localhost:9411 )
++++++++++++++++++++++++++++++++++++++++++++++++++++++
=====================
Cloud Config Server
====================
=> If we want to make any changes to properties then we have to re-package our
application
=> To externalize properties from the application we can use Cloud Config Server
==================
Config Server App
===================
1) Create Git Repository and keep ymls files required for projects
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
</dependency>
@SpringBootApplication
@EnableConfigServer
public class Application {
spring:
cloud:
config:
server:
git:
uri: https://github.com/ashokitschool/configuration_properties
clone-on-start: true
management:
security:
enabled: false
=================================
Config Server Client Development
=================================
a) web-starter
b) config-client
c) dev-tools
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
@Value("${msg}")
private String msg;
@GetMapping("/")
public String getWelcomeMsg() {
return msg;
}
}
server:
port: 9090
spring:
config:
import: optional:configserver:http://localhost:8080
application:
name: greet
===================================================================================
===============
=================================
Circuit Breaker
=================================
-> Fault-tolerance system means when main logic is failed to execute then we should
execute fallback logic to process client request
===========
Usecase
===========
=> Get data from redis, if redis logic is failing then we should get data from
database
Note: If redis logic is failing for 3 requests continuosly then execute db logic
for 30 mins. After 30 mins re-try for redis logic execution if it is working then
execute redis logic only. If 3 re-try executions failed with redis then execute db
logic for next 30 mins.
<artifactId>spring-cloud-services-starter-circuit-breaker</artifactId>
</dependency>
-----------------------------------------------------------------------------------
-------------
@RestController
public class DataRestController {
@GetMapping("/data")
@HystrixCommand(
fallbackMethod = "getDataFromDB",
commandProperties = {
@HystrixProperty(name="circuitBreaker.requestVolumeThreshold", value="3"),
@HystrixProperty(name="circuitBreaker.sleepWindowInMilliseconds",
value="10000"),
@HystrixProperty(name="circuitBreaker.enabled",
value="true")
}
)
public String getDataFromRedis() {
System.out.println("**getDataFromRedis() method called**");
if (new Random().nextInt(10) <= 10) {
throw new RuntimeException("Redis Server Is Down");
}
// logic to access data from redis
return "data accessed from redis (main logic) ....";
}