Ответ
Взаимодействие через очереди сообщений (Message Queues) — это распространенный паттерн асинхронной коммуникации в микросервисной архитектуре. Сервис-отправитель (producer) публикует событие в очередь, а сервис-получатель (consumer) подписывается на очередь и обрабатывает события в своем темпе. Это обеспечивает слабую связность, надежность и масштабируемость.
Пример сценария «Создание заказа» с использованием Spring Boot и RabbitMQ:
1. Сервис заказов (Producer) публикует событие OrderCreated:
// Event-объект (DTO)
public class OrderCreatedEvent {
private String orderId;
private BigDecimal amount;
private String userId;
// getters, setters, constructor
}
@Service
public class OrderService {
@Autowired
private RabbitTemplate rabbitTemplate;
public Order createOrder(OrderRequest request) {
// 1. Сохраняем заказ в БД
Order order = saveOrderToDatabase(request);
// 2. Публикуем асинхронное событие в обменник RabbitMQ
OrderCreatedEvent event = new OrderCreatedEvent(order.getId(), order.getAmount(), order.getUserId());
rabbitTemplate.convertAndSend("order.events.exchange", // Имя обменника
"order.created", // Routing key
event);
System.out.println("Event 'OrderCreated' published for order: " + order.getId());
// 3. Немедленно возвращаем ответ клиенту, не дожидаясь обработки платежа
return order;
}
}
2. Сервис платежей (Consumer) обрабатывает событие:
@Service
public class PaymentService {
// Слушатель очереди, привязанной к обменнику с routing key "order.created"
@RabbitListener(queues = "${queue.payment.process}")
public void handleOrderCreatedEvent(OrderCreatedEvent event) {
System.out.println("Processing payment for order: " + event.getOrderId());
// Бизнес-логика обработки платежа
boolean paymentSuccess = processPayment(event.getUserId(), event.getAmount());
if (paymentSuccess) {
// Можно отправить новое событие, например, 'PaymentCompleted'
System.out.println("Payment successful for order: " + event.getOrderId());
} else {
// Обработка неудачи, возможно, отправка в очередь повторных попыток (retry queue)
System.out.println("Payment failed for order: " + event.getOrderId());
}
}
}
3. Конфигурация очереди (application.yml):
spring:
rabbitmq:
host: localhost
port: 5672
username: guest
password: guest
queue:
payment:
process: payment.process.queue # Имя очереди для обработки платежей
Ключевые преимущества такого подхода:
- Асинхронность: Сервис заказов не блокируется, ожидая ответа от платежного сервиса.
- Устойчивость к сбоям: Если сервис платежей временно недоступен, сообщения будут накапливаться в очереди и обработаются после его восстановления.
- Масштабируемость: Можно запустить несколько инстансов сервиса платежей для параллельной обработки сообщений из одной очереди.