Cloud computing

Introduction

Architecture de Spring Cloud

Eureka Config Serve Zuul Consul Hystrix Resilience4J

Spring Boot (BackEnd) TPs

Creation,Dépendance,Configuration Exemple Video RestController

Produit Rest API

Entity et repository Ajouter Afficher Liste Produit Détails,Supprimer,Vider Modifier

Angular (FrontEnd)

Angular Rappel CLient CRUD

Spring Security

User Auth

CRUD

Vente CRUD

To be Continued...

Middlewares Orientés Messages

Communication Synchrone vs. Asynchrone API JMS : Java Message Service JMS avec ActiveMQ et HornetQ KAFKA

Spring Batch

Spring Batch

Stream Processing

Kafka Streams

Architectures Serverless

Architectures Serverless Résumé



Resilience4J for fault tolerance,

<

In a Spring Cloud application utilizing consul for service discovery and Resilience4J for fault tolerance, various components play distinct roles to enhance the architecture's resilience, scalability, and maintainability. Here’s a breakdown of each element and its role in the project:

Consul

  • Role : Acts as a service registry.
  • Function :
    • Service Discovery : It maintains a registry of all available microservices, allowing other services to discover and communicate with them without hardcoding URLs.
    • Registration : Microservices register themselves with the Consul upon startup, providing their metadata (like service name, URL, and health status).
    • Health Monitoring : The server periodically checks the health of registered services and deregisters them if they become unresponsive or fail.

Service A

  • Role : A microservice that can handle requests and respond with data.
  • Function :
    • Service Endpoint : Exposes an endpoint (/serviceA ) that can be accessed by other services (like Service B).
    • Self-Discovery : Registers with the Consul to be discoverable by Service B and other clients.

Service B

  • Role : A microservice that interacts with Service A.
  • Function :
    • Service Endpoint : Exposes an endpoint (/serviceB ) which calls Service A and returns its response.
    • Dependency Management : Utilizes a RestTemplate to make HTTP requests to Service A, allowing it to retrieve and display data from Service A.
    • Circuit Breaker : Uses Resilience4J’s Circuit Breaker to handle potential failures in calls to Service A, preventing cascading failures if Service A is down.

Resilience4J

  • Role : A library for fault tolerance.
  • Function :
    • Circuit Breaker : Prevents cascading failures by stopping requests to a failing service after a certain number of failures. When the circuit breaker opens, subsequent requests to the failing service are quickly failed until it recovers.
    • Rate Limiter : (If implemented) Controls the rate of requests sent to a service, preventing overload.
    • Bulkhead : (If implemented) Isolates different parts of the application to ensure that if one part fails, the others can still operate.
    • Retry Mechanism : (If implemented) Automatically retries failed requests to recover from transient errors.

RestTemplate

  • Role : A synchronous client to make HTTP requests.
  • Function :
    • Service Communication : Used by Service B and Service C to call other microservices. It abstracts the complexities of making HTTP calls, handling serialization/deserialization of requests and responses.
    • Load Balancing : With the @LoadBalanced annotation, it allows calls to other services by their registered names (e.g., http://service-a/serviceA ), automatically resolving their actual IP addresses through the Consul .
graph TD A[ClientA] -->|Call via Consul| B[Service B] A -->|Invoke /invoke| C[Service A Client RestTemplate] subgraph Resilience4J Mechanisms direction TB D[Retry] --> E[Rate Limiter] E --> F[Time Limiter] F --> G[Circuit Breaker] end C -->|Handles Mechanisms| D C -->|Call Service B with Circuit Breaker| B B -->|Return Response| A classDef resilience fill:#f9f,stroke:#333,stroke-width:2px; class D,E,F,G resilience;
  1. Client (Service A) :

    • Le client (Service A) effectue un appel via consul discovery pour trouver Service B.
  2. Service B :

    • Le service appelé (Service B) répond à la requête envoyée par Service A.
  3. Service A Client (RestTemplate) :

    • Cette partie du Service A est responsable de l'appel HTTP à Service B. Elle est protégée par les mécanismes de résilience suivants :
      • Retry : En cas d'échec, l'appel est réessayé plusieurs fois.
      • Rate Limiter : Limite le nombre d'appels à Service B dans une période donnée.
      • Time Limiter : Si le service prend trop de temps pour répondre, l'appel est interrompu.
      • Circuit Breaker : Si Service B échoue plusieurs fois, le circuit est ouvert pour éviter d'inonder Service B de requêtes.
  4. Mécanismes de Résilience :

    • Ces mécanismes assurent la résilience de l'application face aux pannes ou aux délais de réponse longs.

Objectif du Projet

  • Eureka or Consul pour la découverte de services.
  • Resilience4J pour gérer la résilience des appels interservices à l'aide des mécanismes suivants :
    • Circuit Breaker : Protège contre les appels à un service défaillant.
    • Retry : Réessaie automatiquement un appel en cas d'échec.
    • Rate Limiter : Limite le nombre d'appels à un service par unité de temps.
    • Time Limiter : Ajoute une limite de temps pour les appels aux services externes.

atructure de l'Application

  • Consul or Consul : Service de découverte des microservices.
  • Service A : Service client qui appelle un autre service (Service B).
  • Service B : Service appelé (par Service A).

Créer Client A

Définir un projet Spring Boot

<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-consul-discovery</artifactId>
		</dependency>
	
		  <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>
Configuration du application.properties :

# Spring application name
spring.application.name=clienta

# Spring Cloud Consul configuration
spring.cloud.consul.host=localhost
spring.cloud.consul.port=8500
spring.cloud.consul.discovery.enabled=true


# Management endpoints exposure
management.endpoints.web.exposure.include=health,info,refresh

# Server port configuration
server.port=8080

Controller

package com.example.clienta;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class ClientAController {
    
    @GetMapping("/greet")
    public String greet() {
        return "Hello from Client A!";
    }
}
ClientAApplication

@SpringBootApplication
public class ClientAApplication {

	public static void main(String[] args) {
		SpringApplication.run(ClientAApplication.class, args);
	}

}

Lance Consul

Créer le Service B (Service Externe)

Créez un projet Spring Boot .

	<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-consul-discovery</artifactId>
		</dependency>
  <dependency>
            <groupId>io.github.resilience4j</groupId>
            <artifactId>resilience4j-spring-boot2</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>
        
        
        
  <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>

Configurer application.properties

# Spring Application Configuration
server.port=8083
spring.application.name=client-b

# Spring Cloud Consul Configuration
spring.cloud.consul.host=localhost
spring.cloud.consul.port=8500
spring.cloud.consul.discovery.prefer-ip-address=true

# Management Endpoints
management.endpoints.web.exposure.include=*
management.endpoint.health.show-details=always
management.health.circuitbreakers.enabled=true

# Resilience4j Circuit Breaker Configuration for serviceB
resilience4j.circuitbreaker.instances.serviceA.baseConfig=default


# Resilience4j Retry Configuration for serviceB
resilience4j.retry.instances.serviceA.maxAttempts=3
resilience4j.retry.instances.serviceA.waitDuration=2s

# Resilience4j Rate Limiter Configuration for serviceB
# Limit the number of calls to 3 per 5 seconds
resilience4j.ratelimiter.instances.serviceA.limitForPeriod=3
resilience4j.ratelimiter.instances.serviceA.limitRefreshPeriod=10s

# Resilience4j Time Limiter Configuration for serviceB
resilience4j.timelimiter.instances.serviceA.timeoutDuration=2s
# Resilience4j Rate Limiter Configuration for serviceB


Créer un contrôleur pour le Service B : Exposez une API REST pour simuler un service.
package com.example.clientb;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import io.github.resilience4j.circuitbreaker.annotation.CircuitBreaker;
import io.github.resilience4j.ratelimiter.RateLimiterRegistry;
import io.github.resilience4j.ratelimiter.annotation.RateLimiter;
import io.github.resilience4j.retry.annotation.Retry;
import io.github.resilience4j.timelimiter.annotation.TimeLimiter;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import io.github.resilience4j.ratelimiter.annotation.RateLimiter;
import io.github.resilience4j.ratelimiter.RateLimiterRegistry;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.stereotype.Controller;
import java.util.concurrent.CompletableFuture;
import java.util.List;

@RestController
public class ClientBController {

    @Autowired
    private DiscoveryClient discoveryClient;

    private final RestTemplate restTemplate = new RestTemplate();


  

    @GetMapping("/call-a")
    @CircuitBreaker(name = "serviceA", fallbackMethod = "callifNoReponse")
    @Retry(name = "serviceA", fallbackMethod = "callifNoReponse")
    @RateLimiter(name = "serviceA",fallbackMethod = "callifNoReponse")
    @TimeLimiter(name = "serviceA", fallbackMethod = "callifNoReponse")
    public CompletableFuture callClientA() {
        return CompletableFuture.supplyAsync(() -> {
        List<ServiceInstance> instances = discoveryClient.getInstances("clienta");
        if (instances != null && !instances.isEmpty()) {
            String clientAUrl = instances.get(0).getUri().toString() + "/greet";
            return restTemplate.getForObject(clientAUrl, String.class);
        }
        return "Client A not available";
        });
    }

    
 // Fallback method with Throwable parameter
    public CompletableFuture<String> callifNoReponse(Throwable throwable) {
        // Handle the fallback logic here (e.g., return a default message)
        return CompletableFuture.completedFuture("Fallback response: " + throwable.getMessage());
    }
}

ClientBApplication


package com.example.clientb;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;

import io.github.resilience4j.circuitbreaker.CircuitBreakerRegistry;

@SpringBootApplication
public class ClientBApplication {

	public static void main(String[] args) {
		SpringApplication.run(ClientBApplication.class, args);
	}

	
	 @Bean
	    public RestTemplate restTemplate() {
	        return new RestTemplate();
	    }

	    @Bean
	    public CircuitBreakerRegistry circuitBreakerRegistry() {
	        return CircuitBreakerRegistry.ofDefaults();
	    }
	    
}

CompletableFuture

  1. Asynchronous Execution:
    It enables tasks to run in the background without blocking the main thread.

  2. Non-Blocking API:
    You can attach callbacks to process results or handle errors when the computation completes, without waiting.

  3. Chaining Tasks:
    You can define dependent tasks that execute after the completion of the initial task, forming a chain of computations.

  4. Exception Handling:
    Provides mechanisms to handle exceptions gracefully during the computation process.

  5. Combination of Futures:
    Allows combining multiple asynchronous tasks to execute either sequentially or concurrently.

  • @CircuitBreaker : Si Service B échoue, cette annotation active le fallback.
  • @Retry : Réessaie l'appel en cas d'échec (max 3 tentatives).
  • @RateLimiter : Limite le nombre d'appels (5 appels toutes les 10 secondes).
  • @TimeLimiter : Limite la durée de l'appel à 2 secondes.
Démarrez le Service A. Il sera accessible sur http://localhost:8082/call-a et appellera le Service B.
  1. Démarrer tous les services :

    • Démarrez le Service B (localhost:8081).
    • Démarrez le Service A (localhost:8082).
pour tester RateLimeter :Run http://localhost:8082/call-a 5 fois
Pour tester circuitbreaker arreter le service ClientA puis run http://localhost:8082/call-a