Какие основные способы взаимодействия сервисов в микросервисной архитектуре?

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

Ответ

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

1. Синхронное взаимодействие (RPC - Remote Procedure Call)

Сервис-клиент ожидает ответа от сервиса-сервера.

  • REST/HTTP API (наиболее распространён): Использует стандартные HTTP-методы (GET, POST, PUT, DELETE).
    # Пример вызова REST API из Python-сервиса
    import requests
    response = requests.get(
        'http://orders-service/api/v1/orders/123',
        timeout=5  # Важно: всегда устанавливать таймаут!
    )
    if response.status_code == 200:
        order_data = response.json()
  • gRPC (высокая производительность): Использует бинарный протокол HTTP/2 и Protocol Buffers (protobuf) для сериализации. Идеален для внутренней связи в high-load системах.

2. Асинхронное взаимодействие (через брокер сообщений)

Сервисы обмениваются событиями/сообщениями, не блокируя друг друга.

  • Публикация/Подписка (Pub/Sub): Сервис-издатель отправляет событие в канал (topic), а все подписанные сервисы получают его копию.

    # Пример публикации события в Apache Kafka
    from kafka import KafkaProducer
    import json
    
    producer = KafkaProducer(
        bootstrap_servers=['kafka-broker:9092'],
        value_serializer=lambda v: json.dumps(v).encode('utf-8')
    )
    producer.send('order_created', 
                  value={'order_id': 123, 'user_id': 456, 'status': 'pending'})
    producer.flush()

    Популярные брокеры: Apache Kafka, RabbitMQ, NATS.

Ключевые принципы и инструменты:

  • Слабая связанность: Сервисы взаимодействуют только через контракты (API-схемы, форматы сообщений), не зная внутренней реализации друг друга.
  • Отказоустойчивость: Для синхронных вызовов обязательны паттерны Retry, Circuit Breaker (например, через Hystrix или Resilience4j) и таймауты.
  • Обнаружение сервисов: Использование Service Discovery (Consul, Eureka, Kubernetes Services) для динамического поиска адресов сервисов.
  • Тестирование: Использование WireMock для мокирования HTTP-сервисов и Testcontainers для поднятия реальных брокеров сообщений в тестах.