Я разделю это на пункты, надеюсь, будет иметь смысл.Я мог бы перефразировать немного из того, что я написал в Руководство Автостопщика по параллелизму .Возможно, вы захотите прочитать его, чтобы получить подробные сведения об обосновании способа передачи сообщений в Erlang.
1.Передача сообщений
Передача сообщений в Erlang осуществляется через асинхронные сообщения, отправляемые в почтовые ящики (своего рода очередь для хранения данных).Абсолютно нет предположений относительно того, было ли сообщение получено или нет, или даже что оно было отправлено действительному процессу.Это потому, что можно предположить [на уровне языка], что кто-то может захотеть обработать сообщение, возможно, всего за 4 дня, и даже не признает его существование, пока оно не достигнет определенного состояния.
AСлучайным примером этого может быть представление о длительном процессе, который обрабатывает данные в течение 4 часов.Должно ли оно действительно подтвердить, что получило сообщение, если не может его обработать?Может быть, должно, а может и нет.Это действительно зависит от вашего приложения.Таким образом, никаких предположений не делается.Вы можете иметь половину своих сообщений асинхронными и только одно, которое не является.
Эрланг ожидает, что вы отправите подтверждающее сообщение (и ждете его с таймаутом), если вам когда-нибудь понадобится.Правила, связанные с тайм-аутом и форматом ответа, оставляются на усмотрение программиста - Эрланг не может предположить, что вам нужно подтверждение при получении сообщения, когда задача выполнена, соответствует она или нет (сообщениеможет совпадать через 4 часа при горячей загрузке новой версии кода и т. д.
Для краткости , если сообщение не прочитано, не получено или не прерванокто-то тянет за вилку, пока она находится в пути, не имеет значения, если вы этого не хотите.Если вы хотите, чтобы это имело значение, вам нужно спроектировать логику между процессами.
Бремя реализации протокола сообщений высокого уровня между процессами Erlang возлагается на программиста.
2.Протоколы сообщений
Как вы сказали, эти сообщения хранятся во временной памяти: если процесс умирает, все сообщения, которые он еще не прочитал, теряются.Если вы хотите больше, есть разные стратегии.Вот некоторые из них:
- Прочитайте сообщение как можно быстрее и, при необходимости, запишите его на диск, отправьте подтверждение обратно и обработайте его позже.Сравните это с программным обеспечением очереди, таким как RabbitMQ и ActiveMQ, с постоянными очередями.
- Используйте группы процессов для дублирования сообщений в группе процессов на нескольких узлах.На этом этапе вы можете ввести транзакционную семантику.Этот используется для базы данных mnesia для фиксации транзакции;
- Не думайте, что что-то сработало, пока не получите либо подтверждение того, что все прошло нормально, либо сообщение об ошибке
- Комбинация процессагруппы и сообщения об ошибках.Если первый процесс не может обработать задачу (потому что узел выходит из строя), ВМ автоматически отправляет уведомление аварийному процессу, который обрабатывает его.Этот метод иногда используется с полными приложениями для обработки аппаратных сбоев.
В зависимости от поставленной задачи, вы можете использовать один или несколько из них.Их все можно реализовать в Erlang, и во многих случаях модули уже написаны для того, чтобы сделать тяжелую работу за вас.
Так что это может ответить на ваш вопрос. Поскольку вы сами реализуете протоколы, вы сами выбираете, будут ли сообщения отправляться более одного раза или нет.
3.Что такое отказоустойчивость
Выбор одной из вышеуказанных стратегий зависит от того, что для вас значит отказоустойчивость .В некоторых случаях люди имеют в виду, что «никакие данные никогда не теряются, никакие задачи никогда не заканчиваются».Другие люди используют отказоустойчивость, чтобы сказать «пользователь никогда не видит сбой».В случае систем Erlang обычно подразумевается сохранение работоспособности системы: вполне возможно, что один пользователь отбрасывает телефонный звонок, а не все отбрасывает его.
Здесь идея состоит в том, чтобыэто терпит неудачу, но остальные работают.Чтобы достичь этого, есть несколько вещей, которые ВМ дает вам:
- Вы можете знать, когда процесс умирает и почему он это сделал
- Вы можете заставить процессы, которые зависят друг от друга,умрите вместе, если один из них выйдет из строя
- Вы можете запустить регистратор, который автоматически регистрирует каждое необученное исключение для вас, и даже может определять ваши собственные
- Узлы можно отслеживать так,вы знаете, когда они вышли из строя (или отключились)
- Вы можете перезапустить сбойные процессы (или группы сбойных процессов)
- Перезапускать целые приложения на разных узлах в случае сбоя одного
- И еще много чего еще с OTP framework
С этими инструментами и несколькими модулями стандартной библиотеки, которые обрабатывают различные сценарии для вас, вы можете реализовать в значительной степени то, что вы хотите, поверх асинхронного Эрлангасемантика, хотя обычно стоит иметь возможность использовать определение отказоустойчивости Эрланга.
4.Несколько замечаний
Мое личное мнение заключается в том, что довольно сложно иметь больше предположений, чем то, что существует в Erlang, если вы не хотите использовать чисто транзакционную семантику.Одна из проблем, с которой у вас всегда будут проблемы, связана с отключением узлов.Вы никогда не узнаете, вышли ли они из строя из-за сбоя сервера или из-за сбоя в сети.
В случае сбоя сервера простое повторное выполнение задач достаточно просто.Однако при разделении сети вы должны убедиться, что некоторые важные операции не выполняются дважды, но и не теряются.
Обычно это сводится к теореме CAP , которая в основном дает вам 3 вариантаиз которых вы должны выбрать два:
- Последовательность
- Допуск раздела
- Доступность
В зависимости от того, где вы позиционируете себя,потребуются разные подходы.Теорема CAP обычно используется для описания баз данных, но я считаю, что подобные вопросы следует задавать всякий раз, когда вам требуется определенный уровень отказоустойчивости при обработке данных.