Являются ли сообщения Erlang / OTP надежными? Можно ли дублировать сообщения? - PullRequest
36 голосов
/ 03 июля 2010

Длинная версия:

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

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

Будут ли все производители автоматически ретранслировать сообщения, которые не были подтверждены при смерти пользовательских процессов?Если нет, то как это можно считать отказоустойчивым?И если да, то что мешает повторной передаче и, следовательно, повторной обработке сообщения, которое было обработано - но не полностью подтверждено -

(я признаю, что эти проблемы не являются уникальными для erlang; аналогичные проблемы возникнутв любой системе распределенной обработки. Но, похоже, энтузиасты erlang утверждают, что платформа делает все это "простым" ..?)

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

Краткая версия:

Являются ли распределенные процессы erlang предметом дублированных сообщений?Если да, то является ли защита от дублирования (то есть идемпотентности) ответственностью приложения, или erlang / OTP как-то помогает нам в этом?

Ответы [ 3 ]

109 голосов
/ 05 июля 2010

Я разделю это на пункты, надеюсь, будет иметь смысл.Я мог бы перефразировать немного из того, что я написал в Руководство Автостопщика по параллелизму .Возможно, вы захотите прочитать его, чтобы получить подробные сведения об обосновании способа передачи сообщений в Erlang.


1.Передача сообщений

Передача сообщений в Erlang осуществляется через асинхронные сообщения, отправляемые в почтовые ящики (своего рода очередь для хранения данных).Абсолютно нет предположений относительно того, было ли сообщение получено или нет, или даже что оно было отправлено действительному процессу.Это потому, что можно предположить [на уровне языка], что кто-то может захотеть обработать сообщение, возможно, всего за 4 дня, и даже не признает его существование, пока оно не достигнет определенного состояния.

AСлучайным примером этого может быть представление о длительном процессе, который обрабатывает данные в течение 4 часов.Должно ли оно действительно подтвердить, что получило сообщение, если не может его обработать?Может быть, должно, а может и нет.Это действительно зависит от вашего приложения.Таким образом, никаких предположений не делается.Вы можете иметь половину своих сообщений асинхронными и только одно, которое не является.

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

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

Бремя реализации протокола сообщений высокого уровня между процессами Erlang возлагается на программиста.


2.Протоколы сообщений

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

  • Прочитайте сообщение как можно быстрее и, при необходимости, запишите его на диск, отправьте подтверждение обратно и обработайте его позже.Сравните это с программным обеспечением очереди, таким как RabbitMQ и ActiveMQ, с постоянными очередями.
  • Используйте группы процессов для дублирования сообщений в группе процессов на нескольких узлах.На этом этапе вы можете ввести транзакционную семантику.Этот используется для базы данных mnesia для фиксации транзакции;
  • Не думайте, что что-то сработало, пока не получите либо подтверждение того, что все прошло нормально, либо сообщение об ошибке
  • Комбинация процессагруппы и сообщения об ошибках.Если первый процесс не может обработать задачу (потому что узел выходит из строя), ВМ автоматически отправляет уведомление аварийному процессу, который обрабатывает его.Этот метод иногда используется с полными приложениями для обработки аппаратных сбоев.

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

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


3.Что такое отказоустойчивость

Выбор одной из вышеуказанных стратегий зависит от того, что для вас значит отказоустойчивость .В некоторых случаях люди имеют в виду, что «никакие данные никогда не теряются, никакие задачи никогда не заканчиваются».Другие люди используют отказоустойчивость, чтобы сказать «пользователь никогда не видит сбой».В случае систем Erlang обычно подразумевается сохранение работоспособности системы: вполне возможно, что один пользователь отбрасывает телефонный звонок, а не все отбрасывает его.

Здесь идея состоит в том, чтобыэто терпит неудачу, но остальные работают.Чтобы достичь этого, есть несколько вещей, которые ВМ дает вам:

  • Вы можете знать, когда процесс умирает и почему он это сделал
  • Вы можете заставить процессы, которые зависят друг от друга,умрите вместе, если один из них выйдет из строя
  • Вы можете запустить регистратор, который автоматически регистрирует каждое необученное исключение для вас, и даже может определять ваши собственные
  • Узлы можно отслеживать так,вы знаете, когда они вышли из строя (или отключились)
  • Вы можете перезапустить сбойные процессы (или группы сбойных процессов)
  • Перезапускать целые приложения на разных узлах в случае сбоя одного
  • И еще много чего еще с OTP framework

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


4.Несколько замечаний

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

В случае сбоя сервера простое повторное выполнение задач достаточно просто.Однако при разделении сети вы должны убедиться, что некоторые важные операции не выполняются дважды, но и не теряются.

Обычно это сводится к теореме CAP , которая в основном дает вам 3 вариантаиз которых вы должны выбрать два:

  1. Последовательность
  2. Допуск раздела
  3. Доступность

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

4 голосов
/ 05 июля 2010

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

  1. Когда процесс умирает, этот процесс будет перезапущен.
  2. В большинстве случаев выиграл сбой процессане сбрасывает все ваше приложение
  3. Когда сообщение отправлено, оно будет получено при условии, что получатель существует.

Насколько я знаю, сообщения в erlang не подлежат дублированию.Если вы отправляете сообщение, а процесс его получает, сообщение исчезает из очереди.Однако, если вы отправляете сообщение, и процесс получает это сообщение, но при обработке его происходит сбой, то это сообщение пропадает и не обрабатывается.Этот факт следует учитывать при разработке вашей системы.OTP помогает вам справиться со всем этим, используя процессы для изоляции критического кода инфраструктуры (например, supervisors, gen_servers, ...) от кода приложения, который может быть подвержен сбоям.

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

Тот факт, что система отказоустойчива, не означает, что ваш алгоритм.

1 голос
/ 15 января 2011

Я думаю, что ответ никак не связан с Эрлангом.Он заключается в семантике взаимодействия клиент-сервер, когда вы можете выбрать реализацию «по крайней мере один раз», «максимум один раз» или «ровно один раз» в свой протокол клиент-сервер.Все эти семантики вызовов могут быть реализованы путем объединения уникальных тегов, повторных попыток и регистрации клиентских запросов как на клиенте, так и на сервере перед его отправкой или выполнением, чтобы сервер мог получить их после сбоя.Помимо дубликатов, вы можете потерять, осиротеть или задержать сообщения.

...