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é



Message-Oriented Middleware (MOM)

1. What is Message-Oriented Middleware (MOM)?

Message-Oriented Middleware (MOM) is a software layer that facilitates communication between distributed systems by sending messages between them. It decouples the sender and receiver, allowing them to communicate asynchronously. Here are some key features:

  • Decoupling : The sender and receiver do not need to know each other's existence or state.
  • Asynchronous Communication : Messages can be sent and received at different times.
  • Reliability : Messages can be queued and stored until they are processed.
  • Scalability : The system can easily scale by adding more consumers or producers.

2. Synchronous vs. Asynchronous Communication

  • Synchronous Communication :

    • The sender waits for the receiver to process the message and send a response.
    • This can lead to blocking operations, which can reduce system performance and increase latency.
    • Example: HTTP requests in RESTful services.
  • Asynchronous Communication :

    • The sender sends a message and continues its processing without waiting for a response.
    • This improves system performance and responsiveness.
    • Example: Sending messages to a message broker (like RabbitMQ or Kafka) and processing them later.
graph TD Producer1[Producer 1] -->|Sends Message| Queue1[Queue 1] Producer2[Producer 2] -->|Sends Message| Queue1 Queue1 -->|Delivers Message| Consumer1[Consumer 1] Queue1 -->|Delivers Message| Consumer2[Consumer 2] subgraph Broker Exchange[Exchange] -->|Routes Messages| Queue1 Exchange -->|Routes Messages| Queue2[Queue 2] end Producer3[Producer 3] -->|Sends Message| Exchange Queue2 -->|Delivers Message| Consumer3[Consumer 3] Consumer3 -->|Acknowledges| Queue2 classDef highlight fill:#f9f,stroke:#333,stroke-width:2px; class Queue1,Queue2 highlight;
RabbitMQ is a message broker that facilitates communication between different systems, applications, or services by enabling them to exchange messages asynchronously.
It implements the Advanced Message Queuing Protocol (AMQP) and supports other protocols like MQTT and STOMP
  1. Producers:

    • Producer 1, Producer 2, and Producer 3 send messages to RabbitMQ.
    • Producers do not directly communicate with consumers; they rely on RabbitMQ to handle the routing.
  2. Exchange:

    • RabbitMQ's Exchange determines how messages are routed to the appropriate queue(s) based on routing rules.
    • Different exchange types (e.g., direct, topic, fanout) allow for various routing patterns.
  3. Queues:

    • Messages are stored in Queue 1 and Queue 2 until consumers are ready to process them.
    • Queues act as buffers between producers and consumers.
  4. Consumers:

    • Consumer 1 and Consumer 2 consume messages from Queue 1, enabling load balancing.
    • Consumer 3 consumes messages from Queue 2 and sends an acknowledgment to RabbitMQ once a message is processed.
  5. Acknowledgments:

    • Consumers send acknowledgments to RabbitMQ to confirm successful message processing.
    • If a consumer fails, RabbitMQ re-queues the message for another consumer.

3. Why Use MOM?

  • Loose Coupling : Systems can evolve independently.
  • Scalability : New services can be added or existing ones can be modified without affecting others.
  • Flexibility : Supports different protocols and message formats.
  • Resilience : Ensures messages are not lost even if the receiver is down.

4. How to Implement a Project

We will create a simple Spring Cloud project to illustrate these concepts. We'll use RabbitMQ as our message broker.

Project Structure

  • Service A (Producer)
  • Service B (Consumer)

Setting Up RabbitMQ

  1. Install Erlang OTP:

    • RabbitMQ requires Erlang to run.
    • Download the latest Erlang/OTP installer for Windows from the Erlang website.
    • Install it by following the on-screen instructions.
    • Set ERLANG_HOME:
      • Add the Erlang installation path (e.g., C:\Program Files\erl-XX.X) to the ERLANG_HOME environment variable.
  2. Install RabbitMQ:

    • Download RabbitMQ from the RabbitMQ website.
    • Choose the appropriate version for your system and install it.

What is Erlang?

functional programming language and runtime system designed for building highly concurrent, distributed, and fault-tolerant applications.
It was originally developed by Ericsson in the 1980s for use in telecommunications systems but has since been used in a variety of domains requiring robust and scalable solutions.

-module(hello).
-export([start/0, say_hello/1]).

say_hello(Name) ->
    io:format("Hello, ~p!~n", [Name]).

start() ->
    spawn(fun() -> say_hello("Erlang") end).

Install Erlang

go to https://www.erlang.org/downloads install it
add the installation folder to:
ERLANG_HOME:C:\Program Files\Erlang OTP

Install rabbitmq

go to https://www.rabbitmq.com/docs/install-windows-manual
Extract the software
run CMD as administrator
go to innstalation folder of rabbitmq:
cd C:\Users\user\Desktop\jee\rabbitmq-server-windows-4.0.3\rabbitmq_server-4.0.3\sbin
run rabbitmq:
 
 rabbitmq-plugins enable rabbitmq_management
 rabbitmq-service install
 rabbitmq-service start

 
 
 
go to http://localhost:15672/ username :guest
password:guest

1. Connections

  • Definition: A Connection is the TCP connection between a client (e.g., a producer or consumer) and the RabbitMQ server.
  • Purpose: It is the physical link that allows clients to send and receive messages from RabbitMQ. Each connection can have multiple channels.

2. Channels

  • Definition: A Channel is a virtual connection within a Connection.
  • Purpose: It allows multiple communication streams over a single connection, making it more efficient to send and receive messages.

3. Exchanges

  • Definition: An Exchange is responsible for routing messages to queues based on certain rules (e.g., routing keys).
  • Purpose: It determines how to deliver messages to one or more queues based on routing logic.

4. Queues

  • Definition: A Queue is a buffer where messages are stored until they are consumed by a consumer.
  • Purpose: It holds messages for future processing. Each message in a queue is consumed by a single consumer (unless shared).
graph TD %% Connections A[Producer] -->|Creates Connection| B[Connection] %% Channels within Connection B -->|Uses Channel| C[Channel] %% Exchange routing C -->|Routes Message to Exchange| D[Exchange] %% Queues and Consumers D -->|Routes to Queue| E[Queue] E -->|Delivers Message| F[Consumer] %% Streams (for large data processing) E -->|Persistent Storage| G[Stream] %% Connections and Components Relationship B --> C F -->|Processes Message| E

Create Spring Boot Applications

Service A (Producer)

Create a Spring Boot Application


Use Spring Initializr (https://start.spring.io/) to create a Spring Boot application named service-a with the following dependencies:
Spring Web
Spring for RabbitMQ

Configure Application Properties

In src/main/resources/application.properties, add the following RabbitMQ configuration:

spring.rabbitmq.host=localhost
spring.rabbitmq.port=5672

Create a Message Producer

Create a REST controller to send messages. Create a new class MessageController:

import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class MessageController {

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @PostMapping("/send")
    public String sendMessage(@RequestBody String message) {
        rabbitTemplate.convertAndSend("myQueue", message);
        return "Message sent: " + message;
    }
}
Explanation:

The @RestController annotation indicates that this class will handle HTTP requests.
The RabbitTemplate is used to send messages to the RabbitMQ broker. We inject it using @Autowired.
The sendMessage method listens for POST requests on /send, sends the received message to the queue named myQueue, and returns a confirmation response.

Create a RabbitMQ Configuration Class

Create a configuration class RabbitConfig to set up the RabbitMQ queue and exchange:

import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.core.TopicExchange;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class RabbitConfig {

    @Bean
    public Queue myQueue() {
        return new Queue("myQueue", false);
    }

    @Bean
    public TopicExchange exchange() {
        return new TopicExchange("myExchange");
    }

    @Bean
    public Binding binding(Queue myQueue, TopicExchange exchange) {
        return BindingBuilder.bind(myQueue).to(exchange).with("myQueue");
    }
}
Explanation:

The @Configuration annotation indicates that this class contains bean definitions.
The myQueue method creates a new queue named myQueue.
The exchange method defines a topic exchange named myExchange.
The binding method binds the queue to the exchange with a routing key, allowing messages sent to the exchange to reach the queue.

Service B (Consumer)

Create Another Spring Boot Application

Create a Spring Boot application named service-b with the same dependencies (Spring Web, Spring for RabbitMQ).

Configure Application Properties

In src/main/resources/application.properties, add the RabbitMQ configuration:

spring.rabbitmq.host=localhost
spring.rabbitmq.port=5672

Create a Message Listener

Create a new class MessageListener to listen for messages from the queue:

import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Service;

@Service
public class MessageListener {

    @RabbitListener(queues = "myQueue")
    public void receiveMessage(String message) {
        System.out.println("Received message: " + message);
    }
}
Explanation:

The @Service annotation indicates that this class is a Spring service.
The @RabbitListener annotation marks the receiveMessage method as a listener for messages on the myQueue queue.
When a message is received, the method prints it to the console.
 

Running the Applications

Start service-b first, as it will listen for incoming messages.
Start service-a next. Use a tool like Postman or curl to send a POST request to http://localhost:8080/send with a message body. For example:

curl -X POST http://localhost:8080/send -d "Hello, RabbitMQ!"
Check the Console of service-b: You should see the received message printed in the console.

4. Conclusion

In this project, we have created a simple producer-consumer setup using RabbitMQ and Spring Cloud:

Service A sends messages to a RabbitMQ queue.
Service B listens for those messages and processes them asynchronously.