Содержание

Синхронная и асинхронная коммуникация в сервисах | Блог Кирилла Грищука

Замечание
Одна из самых сложных в понимании тем это синхронный и асинхронный процесс коммуникации в приложении.

Введение

Эта тема все еще вызывает трудности, поэтому решил подготовить собственную статью с пояснениями.

Поговорим о двух парадигмах для связи асинхронная и синхронная.

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

Практический пример

Обсудим в чем принципиальные отличия этих подходов.

Представим, что у вас есть вопрос и вам срочно нужно получить ответ на него от друга.

В синхронной модели вы позвоните ему, получите ответ, завершите звонок. Ответ получен сразу или не получен вовсе (например ваш друг не берет трубку).

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

Подробно поговорим о характеристиках

Синхронный вызов

Плюсы:

  • Ответ известен сразу
  • Самый простой и распространенный, большинство обработчиков и контроллеров работают так
  • Идеально для малых нагрузок
  • Консистентность возможна, но требуются механизмы для управления транзакциями, например 2PC. Разберем следующие случаи коммуникаций.
    • Получатель смог все обработать, а отправитель упал - все плохо
      • Появляются мертвые записи и объекты без привязки
    • Отправитель ждет ответа, а получатель упал - все хорошо - запрос отвалится по ожиданию обработки.
    • Полная консистеность возможна, возможно видеть самые последние изменения.

Минусы:

  • Блокировка до ответа
    • Ожидание ввода/вывода. Железо простаивает, в момент ожидания ответа, не обрабатывая другие вопросы, но применимо не ко всем языкам и технологиям, реализации могут парковать потоки или отдавать в пул.
    • Возможна утечка ресурсов при неправильно подобранных таймаутах и политиках повторных запросов, каскадный отказ системы по таймаутам.
  • Снижение отказоустойчивости
    • Плохой паттерн для работы под нагрузкой, в прямых вызовах отсутствует журналирование, ведение лога сообщение и при критичных проблемах, восстановление потребует время + необработанные запросы будут потеряны
    • Например когда второй сервис отвечает долго и у нас таймаут и ретраи и мы еще больше грузим систему, возможен каскадный резонанс всей системы

Асинхронный

Плюсы:

  • Высокая отказоустойчивость
    • Отказ одного компонента ведет к наполнению очередей обработки, а не каскадному резонансу
    • Возможнотсть обработать запросы повторно при ошибках
  • Самый распространенный способ отмасштабировать систему и размазать нагрузку
    • Шлем ивенты
    • Добавляем обработчики

Минусы:

  • Результат недоступен сразу, а появлется с задержкой -> проблема актуальности данных
  • Реализуется сложнее, требуется промежуточное хранилище, еще одна система для хранения данных
  • Делает систему eventually consistent
    • Состояние актуальное, но через какое-то время
    • Есть паттерны для цепочек транзакций между сервисами например SAGA, но от проблем отката никто не застрахован
  • Гарантии доставки ограничены
    • Невозможно реализовать доставку ровно 1 раз
    • Все популярные системы дают гарантии at most 1, at least 1
    • Требуется паттерн (Transaction outbox) для гарантии записи
    • Сложность реализации идемпотентных операций

Дополнительные источники для изучения: