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

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

Ответ

Асинхронное взаимодействие означает, что сервис-отправитель не ожидает немедленного ответа от получателя. Это достигается через посредника — брокера сообщений, что повышает отказоустойчивость и масштабируемость системы.

Основные подходы:

  1. Очереди сообщений (Message Queues)

    • Принцип: Один отправитель (producer) отправляет сообщение в очередь, а один получатель (consumer) его забирает и обрабатывает (модель point-to-point).
    • Применение: Для задач, которые должен выполнить ровно один сервис (например, обработка заказа).
    • Технологии: RabbitMQ, Amazon SQS.
  2. Издатель-подписчик (Publish/Subscribe)

    • Принцип: Один отправитель (publisher) публикует сообщение в тему (topic), а все подписанные на эту тему сервисы (subscribers) получают копию сообщения.
    • Применение: Для оповещения нескольких систем о событии (например, "пользователь зарегистрировался").
    • Технологии: Apache Kafka, RabbitMQ (с использованием fanout exchange), Google Pub/Sub.

Пример с RabbitMQ (библиотека pika в Python):

# producer.py - Сервис, отправляющий заказ
import pika

connection = pika.BlockingConnection(pika.ConnectionParameters('localhost'))
channel = connection.channel()
channel.queue_declare(queue='order_processing')

message = '{"order_id": 123, "item": "Laptop"}'
channel.basic_publish(exchange='', routing_key='order_processing', body=message)
print(f" [x] Sent '{message}'")
connection.close()

# consumer.py - Сервис, обрабатывающий заказ
import pika

def callback(ch, method, properties, body):
    print(f" [x] Received {body.decode()}")
    # Здесь логика обработки заказа
    ch.basic_ack(delivery_tag=method.delivery_tag) # Подтверждение обработки

connection = pika.BlockingConnection(pika.ConnectionParameters('localhost'))
channel = connection.channel()
channel.queue_declare(queue='order_processing')
channel.basic_consume(queue='order_processing', on_message_callback=callback)

print(' [*] Waiting for messages. To exit press CTRL+C')
channel.start_consuming()

Преимущества асинхронного подхода:

  • Слабая связанность (Loose Coupling): Сервисы не знают друг о друге, только о брокере.
  • Отказоустойчивость: Если сервис-получатель недоступен, сообщение останется в очереди и будет обработано позже.
  • Масштабируемость: Можно легко добавлять новые экземпляры сервисов-получателей для параллельной обработки сообщений из очереди.