Найти в Дзене

Синхронное и асинхронное взаимодействие "на пальцах"

Это выдержка из публикации за моим авторством на Хабре. Вы можете посмотреть ее полную версию в моем блоге: https://habr.com/ru/users/dmitryshelamov/

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

Итак, представим что у нас есть два микросервиса (А и B). Будем считать, что коммуникация между ними осуществляется через API (application programming interface) и они ничего не знают о внутренней реализации друг друга, как и предписывает микросервисный подход. Формат передаваемых между ними данных заранее оговорен.

Задача перед нами стоит следующая: нам нужно организовать передачу данных от одного приложения к другому и, желательно, с минимальными задержками.

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

Если же ответ на запрос так и не был получен (например, B рвет соединение до отправки ответа или A отваливается по таймауту), сервис А может повторить свой запрос к B.

С одной стороны, такая модель взаимодействия дает определенность статуса доставки данных для каждого запроса, когда отправитель точно знает, были ли получены данные получателем и какие дальнейшие действия ему необходимо делать в зависимости от ответа.
С другой стороны, плата за это – ожидание. После отправки запроса сервис
A (или поток, в котором выполняется запрос) блокируется до того момента, пока не получит ответ или не сочтет запрос неудавшимся согласно своей внутренней логике, после чего примет дальнейшие действия.

Проблема не только в том, что ожидание и простой имеют место быть, – задержки в сетевом взаимодействии неизбежны. Основная проблема заключается в непредсказуемости этой задержки.

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

Все, что остается
А при такой модели взаимодействия – это просто ждать. Может быть наносекунду, а может быть час. И эта цифра вполне реальна в том случае, если B в процессе обработки данных выполняет какие-либо тяжеловесные операции, вроде обработки видео.

Часики-то тикают!
Часики-то тикают!

Возможно, вам проблема не показалась существенной – одна железка ждет пока другая ответит, велика ли потеря?

Чтобы сделать эту проблему более личной, представим, что сервис А – это приложение, запущенное на вашем телефоне, и пока оно ожидает ответ от B, вы видите на экране анимацию загрузки. Вы не можете продолжить пользоваться приложением до тех пор, пока сервис B не ответит, и вынуждены ждать. Неизвестное количество времени. При том, что ваше время гораздо ценнее, чем время работы куска кода.

Подобные шероховатости решаются следующим образом – вы разделяете участников взаимодействия на два “лагеря”: одни не могут работать быстрее, как бы вы их ни оптимизировали (обработка видео), а другие не могут ждать дольше определенного времени (интерфейс приложения на вашем телефоне).

Затем вы заменяете cинхронное взаимодействие между ними (когда одна часть вынуждена ждать другую, чтобы удостовериться, что данные были доставлены и обработаны сервисом-получателем) на асинхронное, то есть модель работы по принципу отправил и забыл – в этом случае сервис A продолжит свою работу, не дожидаясь ответа от B.

Ставьте лайк, если вам было интересно и подписывайтесь на мой канал! В будущем планирую развивать этот блог и очень надеюсь на вашу поддержку! Всем добра:)

Наука
7 млн интересуются