
par Zelkulon07 mars 20251 min de lecture
Comment RabbitMQ découple les microservices, livre les messages de manière fiable et Spring AMQP rend l'intégration simple comme bonjour.
Le problème avec la communication synchrone

Concepts : Exchange, Queue, Binding

- Exchange : reçoit les messages et décide dans quelle queue ils vont
- Queue : stocke les messages jusqu'à ce qu'un consumer les récupère
- Binding : relie l'exchange à la queue (via la routing key)
- Routing Key : clé de chaîne pour le routage (ex. order.created)
Configuration : Exchanges & Queues
@Configuration
public class RabbitMQConfig {
public static final String ORDER_EXCHANGE = "order.exchange";
public static final String ORDER_CREATED_QUEUE = "order.created.queue";
public static final String ORDER_CREATED_KEY = "order.created";
@Bean
public TopicExchange orderExchange() {
return new TopicExchange(ORDER_EXCHANGE, true, false);
}
@Bean
public Queue orderCreatedQueue() {
return QueueBuilder.durable(ORDER_CREATED_QUEUE)
.withArgument("x-dead-letter-exchange", "")
.withArgument("x-dead-letter-routing-key", "dead.letter.queue")
.build();
}
@Bean
public MessageConverter jsonMessageConverter() {
return new Jackson2JsonMessageConverter();
}
}Producer : Envoi de messages
@Service
@RequiredArgsConstructor
public class OrderEventPublisher {
private final RabbitTemplate rabbitTemplate;
public void publishOrderCreated(Order order) {
var event = new OrderCreatedEvent(
order.getId(), order.getCustomerId(),
order.getTotalAmount(), Instant.now()
);
rabbitTemplate.convertAndSend(
RabbitMQConfig.ORDER_EXCHANGE,
RabbitMQConfig.ORDER_CREATED_KEY,
event
);
}
}
// Important : envoyer l'événement seulement APRÈS le commit DB !
@Transactional
public OrderResponse placeOrder(OrderRequest request) {
Order saved = orderRepository.save(buildOrder(request));
TransactionSynchronizationManager.registerSynchronization(
new TransactionSynchronizationAdapter() {
@Override public void afterCommit() {
eventPublisher.publishOrderCreated(saved);
}
}
);
return toResponse(saved);
}Consumer : Réception de messages
@Component
@RequiredArgsConstructor
public class OrderCreatedListener {
@RabbitListener(queues = RabbitMQConfig.ORDER_CREATED_QUEUE)
public void handleOrderCreated(
OrderCreatedEvent event,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag
) {
try {
paymentService.processPayment(event);
channel.basicAck(deliveryTag, false); // Succès
} catch (PaymentException e) {
// Non retryable → Dead Letter Queue
channel.basicNack(deliveryTag, false, false);
} catch (Exception e) {
// Retry → retour dans la queue
channel.basicNack(deliveryTag, false, true);
}
}
}Conclusion
- Découplage : les services ne se connaissent pas
- Tolérance aux pannes : les messages survivent aux interruptions de service
- Dead Letter Queue : pas de perte de données en cas d'erreur de traitement
- Scalabilité : plusieurs instances de consumer traitent en parallèle
- Sécurité transactionnelle : envoyer l'événement après le commit DB