Commit 1e4b3470 authored by mohammad.salama's avatar mohammad.salama

Added Circuit Breaker for API Gateway (Cloud Gateway Service) with Monitoring...

Added Circuit Breaker for API Gateway (Cloud Gateway Service) with Monitoring using Prometheus and Grafana
parent 58768210
......@@ -27,6 +27,15 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-circuitbreaker-reactor-resilience4j</artifactId>
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-prometheus</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
......@@ -51,26 +60,6 @@
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- <dependency>-->
<!-- <groupId>org.slf4j</groupId>-->
<!-- <artifactId>slf4j-api</artifactId>-->
<!-- <version>2.0.9</version>-->
<!-- </dependency>-->
<!-- <dependency>-->
<!-- <groupId>ch.qos.logback</groupId>-->
<!-- <artifactId>logback-classic</artifactId>-->
<!-- <version>1.4.11</version>-->
<!-- </dependency>-->
<!-- <dependency>-->
<!-- <groupId>ch.qos.logback</groupId>-->
<!-- <artifactId>logback-core</artifactId>-->
<!-- <version>1.4.11</version>-->
<!-- </dependency>-->
<!-- <dependency>-->
<!-- <groupId>com.google.code.gson</groupId>-->
<!-- <artifactId>gson</artifactId>-->
<!-- <version>2.8.9</version>-->
<!-- </dependency>-->
</dependencies>
</dependencyManagement>
......
package org.example;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/")
public class FallbackMethod {
@RequestMapping("user-fallback")
public String getCatalogFallback(){
//it can be an empty list of books or last cash result
return "User Service Service is temporary unavailable, Please Try Again Later";
}
@RequestMapping("database-fallback")
public String getMovieFallback(){
//it can be an empty list of books or last cash result
return "Database Service is temporary unavailable, Please Try Again Later";
}
@RequestMapping("weather-fallback")
public String getRatingFallback(){
//it can be an empty list of books or last cash result
return "Weather Service is temporary unavailable, Please Try Again Later";
}
}
......@@ -12,14 +12,32 @@ spring:
predicates:
- Path=/users-db/**
- Path=/flights-db/**
filters:
- name: CircuitBreaker
args:
name: databaseCircuitBreaker
fallbackUri: forward:/database-fallback
- id: UserService
uri: lb://user-service
predicates:
- Path=/users/**
filters:
- name: CircuitBreaker
args:
name: userCircuitBreaker
fallbackUri: forward:/user-fallback
- id: WeatherService
uri: lb://weather-service
predicates:
- Path=/weather/**
filters:
- name: CircuitBreaker
args:
name: weatherCircuitBreaker
fallbackUri: forward:/weather-fallback
eureka:
client:
......@@ -28,6 +46,28 @@ eureka:
service-url:
default-zone: http://localhost:8761/eureka/
# instance:
# hostname: localhost
# preferIpAddress: true
\ No newline at end of file
management:
health:
circuitbreakers:
enabled: true
endpoints:
web:
exposure:
include: health,prometheus
endpoint:
health:
show-details: always
resilience4j:
circuitbreaker:
instances:
userCircuitBreaker:
registerHealthIndicator: true
eventConsumerBufferSize: 10
failureRateThreshold: 50
minimumNumberOfCalls: 5
automaticTransitionFromOpenToHalfOpenEnabled: true
waitDurationInOpenState: 10s
permittedNumberOfCallsInHalfOpenState: 3
slidingWindowSize: 10
slidingWindowType: COUNT_BASED
\ No newline at end of file
......@@ -12,14 +12,32 @@ spring:
predicates:
- Path=/users-db/**
- Path=/flights-db/**
filters:
- name: CircuitBreaker
args:
name: databaseCircuitBreaker
fallbackUri: forward:/database-fallback
- id: UserService
uri: lb://user-service
predicates:
- Path=/users/**
filters:
- name: CircuitBreaker
args:
name: userCircuitBreaker
fallbackUri: forward:/user-fallback
- id: WeatherService
uri: lb://weather-service
predicates:
- Path=/weather/**
filters:
- name: CircuitBreaker
args:
name: weatherCircuitBreaker
fallbackUri: forward:/weather-fallback
eureka:
client:
......@@ -28,6 +46,28 @@ eureka:
service-url:
default-zone: http://localhost:8761/eureka/
# instance:
# hostname: localhost
# preferIpAddress: true
\ No newline at end of file
management:
health:
circuitbreakers:
enabled: true
endpoints:
web:
exposure:
include: health,prometheus
endpoint:
health:
show-details: always
resilience4j:
circuitbreaker:
instances:
userCircuitBreaker:
registerHealthIndicator: true
eventConsumerBufferSize: 10
failureRateThreshold: 50
minimumNumberOfCalls: 5
automaticTransitionFromOpenToHalfOpenEnabled: true
waitDurationInOpenState: 10s
permittedNumberOfCallsInHalfOpenState: 3
slidingWindowSize: 10
slidingWindowType: COUNT_BASED
\ No newline at end of file
# Mini-Catalog Microservices Application
## Application Services
### Spring Boot APP
- Weather Service
- User Service
- DataBase Service
### Spring Cloud APP
- Service Discovery (DiscAndReg)
- Cloud Gateway
## Monitoring with Prometheus and Grafana
### Requirements
[Docker](https://docs.docker.com/install/) and [Docker Compose](https://docs.docker.com/compose/install/) installed.
### Step 1
Use docker-compose to start Grafana and Prometheus servers.
- In the root folder
```sh
docker-compose -f docker-compose.yml up
```
### Step 2
Check the Prometheus server.
- Open http://localhost:9091
- Access status -> Targets, both endpoints must be "UP"
### Step 3
Configure the Grafana.
- Open http://localhost:3000
- **Configure integration with Prometheus**
- Access configuration
- Add data source
- Select Prometheus
- Use url "http://prometheus:9090" and access with value "Browser"
- **Configure dashboard**
- Access "home"
- Import dashboard
- Upload dashboard.json from /docker
version: '3'
services:
prometheus:
image: prom/prometheus
container_name: prometheus
volumes:
- ./docker/prometheus-desktop.yml:/etc/prometheus/prometheus.yml
ports:
- "9091:9090"
networks:
- net
grafana:
image: grafana/grafana
container_name: grafana
env_file:
- ./docker/grafana.env
ports:
- "3000:3000"
networks:
- net
networks:
net:
\ No newline at end of file
This diff is collapsed.
# [server]
# GF_SERVER_DOMAIN=localhost
# GF_SERVER_HTTP_PORT=3000
# GF_SERVER_PROTOCOL=http
\ No newline at end of file
global:
scrape_interval: 15s # By default, scrape targets every 15 seconds.
# Attach these labels to any time series or alerts when communicating with
# external systems (federation, remote storage, Alertmanager).
external_labels:
monitor: 'resilience4j-monitor'
# A scrape configuration containing exactly one endpoint to scrape:
# Here it's Prometheus itself.
scrape_configs:
# The job name is added as a label `job=<job_name>` to any timeseries scraped from this config.
- job_name: 'prometheus'
# Override the global default and scrape targets from this job every 5 seconds.
scrape_interval: 5s
static_configs:
- targets: ['localhost:9090']
- job_name: 'Cloud-Gateway'
# Override the global default and scrape targets from this job every 5 seconds.
scrape_interval: 5s
metrics_path: /actuator/prometheus
static_configs:
# Use the service name (see docker-compose.yml) instead of localhost
- targets: ['host.docker.internal:9090']
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment