Re[3]: Message broker for REST API
От: maxkar  
Дата: 07.07.21 19:57
Оценка: 6 (1)
Здравствуйте, gandjustas, Вы писали:

G>В том и дело, что я хочу функцию надежной доставки возложить на этот брокер, а не городить его в каждом приложении.

А не получится "не городить". Всегда есть проблема надежно доставить сообщение от отправителя для брокера. В момент генерации сообщения может не оказаться сети. Узел брокера может внезапно умереть. На машину с отправителем сразу после коммита в базу данных (или другое persistence storage) может случайно упасть метеорит и докатывать сообщение в брокер придется уже кому-то другому. Именно это и есть основная проблема — надежно доставить от первой точки до существующего решения. А дальше распространение сообщения по цепочке — уже вопрос удобства реализации.

G>Тем более я сильно сомневаюсь в квалификации среднего программиста, что он может без ошибок сделать надежную доставку.

Значит нужно выбирать одно из решений, которое позволяет упросить кодирование. И/или учить разработчиков его использовать, следить на ревью кода и т.д. Если "из коробки" — это распределенные транзакции. Понадобится соответствующая поддержка от драйвера базы (или инфраструктуры) и от драйвера брокера. Очевидно, что если брать готовую библиотеку, в ней вряд ли будет rest. Да и для вас нет никакой разницы от того, что у нее внутри.

Можно городить свой удобный велосипед. Под чутким руководством средние программисты такое пишут, проверял. Велосипед в моем стиле работает через основную базу (туда временно пишутся недоставленные сообщения). Библиотека отправки сообщений требует открытую транзакцию, посылает сообщения после коммита. Имеет задачу/поток по периодической докатке сообщений в брокера.

Причем вся эта магия с брокером работает только для ситуаций, когда можно отправить сообщение и забыть про него. К сожалению, во многих случаях нужно надежно продолбиться к конкретному сервису, получить от него ответ и обработать. Там брокер не особо поможет (хотя да, можно и вокруг брокера нагородить...). А вот возможность запрашивать pending операции и повторять их — полезно. Так что обработка повторных отправок входит в обязательный набор навыков разработчика REST.

M>>Но вот что меня еще больше волнует, так это как этот пункт сочетается с предыдущим? Этот пункт (4) утверждает, что оркестратор может терять сообщения. Зачем тогда все сложности с попыткой гарантированной доставки в пункте 3?

G>Это вообще нормальная практика, что сообщение выбрасывается из очереди если не удалось его доставить за N попыток.
Это нормальная практика для ситуаций, когда нужно стримить котиков по интернет (ничего не имею против котиков). Ограничение числа попыток автоматически обозначает, что сообщения могут теряться. Поэтому разговор может идти только о количестве девяток (или просто значащих цифр) в надежности доставки отдельно сообщения.

В кровавом энтерпрайзе с реальными деньгами такое "отправили и фиг с ним" редко проходит. Как минимум — нужно отправлять такие сообщения в dead letters и потом вручную разбираться.

Плюс есть большая проблема с N. Точнее, с интервалом между первой и последней попытками отправки сообщения. Если это меньше часа — есть хороший шанс потерять сообщения, когда ляжет инфраструктура (сеть, kubernetes, маршрутизация, что там еще любят техопсы). Ляжет cloud provider в отдельной зоне. В потребителе сообщений будет баг, при котором определенные типы сообщений не могут быть обработаны (это, кстати, классный сценарий слить много сообщений в /dev/null до того, как проблема будет обнаружена). А если интервал большой, то какая разница, сколько именно раз повторится сообщение? Опять же, в типичном скучном бизнес-приложении есть большие запасы по нагрузке. В норме (стабильный операционный режим) у вас недоставленных сообщений будет вообще 0. Поэтому банальные мониторинги на очередь повторов/количество запущенных повторов/количество повторов отдельного сообщения дадут повод расставить сигналы (alerts) и в случае срабатывания неторопясь разобраться, почему же до получателся все еще не доходит.

Нет, есть сценарии где недоставленные сообщения — это нормальный и ожидаемый режим работы. Но таких мало относительно общей массы.

M>>Это очень сложно в ситуации с "зависимыми entities"

G>Вообще без разницы честно говоря.
А зачем вы тогда ниже жалуетесь, что все решения — сложные?

M>>Если вам все же очень хочется их решить — можно сделать два простеньких сервиса. Один будет предоставлять REST для отправки сообщений в message bus. Второй будет слушать сообщения и маршрутизировать их в web hook (aka вызов rest).

G>А почему нет одного сервера, который это делает?
G>Я понимаю что наколхозить такой сервер можно из подручных средств. Но вот готового решения, кроме тяжелых и дорогих, не видел.
Как раз по причинам, описанным выше. Нужно надежно доставлять сообщения от отправителя до брокера или следующего сервиса. Если эта проблема решена, дальше по цепочке "синхронных" вызовов как раз не обязательно делать надежную доставку (первый сервис все равно крутить будет до победного конца). Клиенту/отправителю во многих случаях нужен ответ а не просто отправка сообщений.

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

Есть и еще один момент. Типичный REST API все-таки предполагает не самую тривиальную обработку. Т.е. разные ответы, гонки состояний, разные форматы выдачи, чтение и запись данных. У вас в ваших требованиях все проще. Сообщения нужно получать, отвечать не обязательно. Там просто смысла нет никакого городить полноценный REST. Взяли брокер, написали ему слушатель (или RPC для брокера) и все. А вот когда функциональности не хватит — можно будет реализовывать что-то более сложное.

Кстати, касательно темы Rest vs Kafka. Там основная причина выбора шины сообщений — это наличие нескольких потребителей сообщения и очень слабая связность между отправителем и получателем. Отправителей не волнует, есть ли вообще получатели. Rest создает излишнюю связность — отправитель будет вынужден знать своих получателей (и их набор может меняться), а это исходя из условиях задачи не нужно. Если бы это были не получатели, а "критичные для работы зависимости", rest мог бы быть лучшим решением. И да, в обоих решениях в отправителе там нужно городить надежную доставку.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.