Ответ
В микросервисной архитектуре, над которой я работал, сервисы взаимодействуют в основном двумя способами: синхронно по HTTP и асинхронно через брокер сообщений.
1. Синхронное взаимодействие (REST/gRPC):
Используется, когда сервису нужен немедленный ответ. Например, сервис заказов (Order Service) запрашивает у сервиса каталога (Catalog Service) актуальную цену товара.
// Пример на Java с Spring Boot и Feign Client
@FeignClient(name = "catalog-service")
public interface CatalogServiceClient {
@GetMapping("/api/products/{id}")
Product getProduct(@PathVariable("id") Long productId);
}
// Использование в Order Service
Product product = catalogServiceClient.getProduct(orderItem.getProductId());
Недостатки: Создает жесткую связь и может привести к каскадным сбоям.
2. Асинхронное взаимодействие (через брокер, например, Kafka или RabbitMQ):
Используется для декoupling и обработки событий. Например, при создании заказа Order Service публикует событие OrderCreated, а Notification Service и Inventory Service подписываются на него.
// Order Service (Publisher)
kafkaTemplate.send("order-events", new OrderCreatedEvent(orderId, userId));
// Notification Service (Consumer)
@KafkaListener(topics = "order-events", groupId = "notification-group")
public void handleOrderEvent(OrderCreatedEvent event) {
// Отправляем email пользователю
emailService.sendOrderConfirmation(event.getUserId(), event.getOrderId());
}
С точки зрения тестирования (QA):
- Для синхронных API мы пишем интеграционные тесты, мокая внешние зависимости с помощью WireMock.
- Для асинхронных сценариев мы используем тесты, которые публикуют сообщение в тестовый топик Kafka и затем проверяют, что потребитель корректно обработал его и выполнил нужные действия (например, обновил базу данных).
- Критически важна трассировка запросов (Distributed Tracing), например, через Jaeger, чтобы отслеживать путь запроса по всем сервисам.