Различия между приложениями, управляемыми сообщениями, между простыми вызовами методов

Я кое-что читал, нашел несколько библиотек, которые действительно смешались с моими мыслями, такие как Akka, Quasar, Reactor и Disruptor, Akka и Quasar реализуют шаблон Actor, а Disruptor - это библиотека обмена сообщениями между потоками, а Reactor основан на, Итак, каковы преимущества, варианты использования для использования управляемой сообщениями архитектуры по сравнению с простыми вызовами методов?

Учитывая прослушиватель очереди RabbitMQ, я получаю сообщение от метода, решаю, какой тип является сообщением RabbitMQ (NewOrder,Payment,...).

С библиотекой, управляемой сообщениями, я мог бы это сделать.

Псевдокод:

actor.tell('decider-mailbox',message)

Который в основном говорит: "Я помещаю это сообщение здесь, когда вы, ребята, можете с этим справиться, делайте это") и так далее, пока оно не будет сохранено. И актер снова готов получить еще одно сообщение

Но с прямым вызовом метода, как messageHandler.handle(message)не будет лучше и менее отвлеченным?

3 ответа

Решение

Модель актеров очень похожа на людей, работающих вместе; он основан на передаче сообщений, но это намного больше, и я бы сказал, что не все модели передачи сообщений одинаковы, например, Quasar фактически поддерживает не только Erlang-подобные актеры, но и Go-подобные каналы, которые проще но не предоставляйте отказоустойчивую модель (и волокна BTW, которые похожи на потоки, но гораздо более легкие, которые вы можете использовать даже без какой-либо передачи сообщений).

Методы / функции следуют строгой, нестабильной дисциплине "возврат-вызов" (поэтому запрос-ответ) и обычно не предполагают параллелизма (по крайней мере, в императивных и не чистых функциональных языках).

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

Обратите внимание, что RPC - это действительно передача сообщений, но со строгой коммуникационной дисциплиной запрос-ответ.

Это означает, что в зависимости от ситуации один или другой может подойти вам лучше: методы / функции лучше, когда вы находитесь в дисциплине обратного вызова и / или вы просто делаете свой последовательный код более модульным. Передача сообщений лучше, когда вам нужна сеть потенциально параллельных, автономных "агентов", которые взаимодействуют, но не обязательно в дисциплине запрос-ответ.

Что касается модели актеров, я думаю, что вы можете лучше понять ее, например , прочитав первую часть этого поста в блоге (обратите внимание: я являюсь основным автором поста и являюсь частью Parallel Universe - и Quasar - Команда разработчиков):

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

Актерский дизайн приносит много преимуществ:

  • Адаптивное поведение: взаимодействие только через очередь сообщений делает участников слабо связанными и позволяет им:
    • Изоляция сбоев: почтовые ящики отделяют очереди сообщений, что позволяет перезапустить субъект без прерывания работы службы.
    • Управляйте эволюцией: они позволяют замену актеров без прерывания обслуживания.
    • Регулирование параллелизма: очень частый прием сообщений и устранение переполнения или, наоборот, увеличение размера почтового ящика может максимизировать параллелизм за счет надежности или использования памяти соответственно.
    • Регулирование нагрузки: уменьшение частоты приема звонков и использование небольших почтовых ящиков уменьшает параллелизм и увеличивает задержки, оказывая обратное давление через границы действующей системы.
  • Максимальная емкость параллелизма:
    • Актеры чрезвычайно легки как по потреблению памяти, так и по накладным расходам на управление, так что возможно порождать даже миллионы в одной коробке.
    • Поскольку актеры не делят государство, они могут безопасно работать параллельно.
  • Низкая сложность:
    • Каждый субъект может реализовывать поведение с состоянием, изменяя свое частное состояние, не беспокоясь о параллельной модификации.
    • Актеры могут упростить свою логику перехода состояний, выборочно получая сообщения из почтового ящика в логическом порядке, а не в порядке поступления.

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

В некотором смысле, это просто вопрос определения абстракций. Некоторые говорят, что изначально объектно-ориентированное программирование должно было основываться на передаче сообщений, а вызов метода для объекта имел бы семантику отправки ему сообщения (с асинхронным неблокирующим поведением, аналогичным действующему).

Способ, которым мы реализовали ОО на большинстве популярных языков, таков, что он стал тем, чем он является сегодня - "синхронный порядок блокировки" для объекта, контролируемый и запускаемый из того же контекста выполнения (потока / процесса), что и вызывающая сторона. Это хорошо, потому что это легко понять, но у него есть свои ограничения при проектировании параллельных систем.

Теоретически, вы можете создать язык с синтаксисом, подобным Java, но дать ему другую семантику - сделать object.method (arg) внутренне чем-то похожим на actor.tell (msg). Есть много идиом, которые пытаются скрыть асинхронный вызов и передачу сообщений за простыми вызовами методов, но, как всегда, это зависит от варианта использования.

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

Другие вопросы по тегам