Как могут общаться между собой сервисы?

«Как могут общаться между собой сервисы?» — вопрос из категории Архитектура, который задают на 24% собеседований AQA / Automation. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

В моей практике сервисы общаются через несколько основных механизмов, выбор которых зависит от требований к задержке, связности и надежности.

Основные паттерны взаимодействия:

Способ Протокол/Технология Когда использовать Пример сценария для QA
Синхронный запрос-ответ REST/HTTP, gRPC, GraphQL Когда нужен немедленный результат. Тестирование API эндпоинтов (Postman, автотесты). Проверка корректности кодов ответа, схемы JSON, времени отклика.
Асинхронное обмен сообщениями Kafka, RabbitMQ (AMQP), AWS SQS/SNS Для декoupling, фоновых задач, событийной архитектуры. Тестирование того, что событие опубликовано, доставлено и обработано. Проверка идемпотентности потребителей.
Совместная база данных Любая СУБД (антипаттерн для МСА) Стараться избегать. Иногда для быстрого прототипа. Тестирование целостности данных и отсутствия прямых SQL-запросов между сервисами.

Практический пример тестирования взаимодействия: Допустим, у нас есть сервис оплаты, который по REST вызывает платёжный шлюз, а затем через Kafka отправляет событие PaymentProcessed.

  1. Тест REST-вызова: Мокаем внешний платёжный шлюз с помощью WireMock, чтобы симулировать успешные и ошибочные ответы.
  2. Тест Kafka-события: В интеграционном тесте проверяем, что после успешной оплаты в конкретный топик Kafka было отправлено сообщение с ожидаемой структурой. Для этого можно использовать embedded Kafka в тестах.
    // Псевдокод интеграционного теста с Kafka
    @Test
    void shouldPublishPaymentProcessedEvent() {
    // 1. Вызываем API оплаты
    post("/api/payments", paymentRequest);
    // 2. Читаем сообщение из тестового топика Kafka
    ConsumerRecord<String, PaymentEvent> record = kafkaConsumer.poll(Duration.ofSeconds(5)).get(0);
    // 3. Assert
    assertThat(record.value().getStatus()).isEqualTo("SUCCESS");
    }

    Ключевые нефункциональные аспекты для проверки: таймауты, retry-логика, обработка недоступности сервиса (circuit breaker).