Какие гарантии дает «монитор» erlang?

#erlang #message-passing

#erlang #передача сообщений

Вопрос:

Читая руководство пользователя ERTS, я нашел этот раздел:

Единственная гарантия упорядочения сигналов заключается в следующем. Если объект отправляет несколько сигналов одному и тому же объекту назначения, порядок будет сохранен. То есть, если A отправляет сигнал S1 на B, а затем отправляет сигнал S2 на B, S1 гарантированно не прибудет после S2.

Я также сталкивался с этим, проводя дальнейшие исследования в Google:

Справочное руководство Erlang, 13.5:

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

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

  A,B are processes on two different nodes.
 Assume A does not crash and B was a valid node at some point.
 A and B monitor each other.
 A sends messages M1,M2,M3 to B
  

В приведенном выше сценарии возможно ли, что B получает M1, M3 (M2 отбрасывается)
без какого-либо тайм-аута «ВНИЗ» / «ВЫХОД» / сердцебиения, получаемого в A?

Комментарии:

1. Действительно зависит от того, что представляют A и B. В случае локального процесса это невозможно: все сообщения будут получены B (хотя B может аварийно завершиться перед обработкой M2 или M3). В случае удаленного процесса это маловероятно, но да, это будет означать отключение между узлами.

2. @Soupd’Campbells У вас есть ссылка на документацию, которая подтверждала бы это? В частности, является ли это «гарантированным», а не просто результатом того, как оно реализовано?

3. Я обновил вопрос более конкретным сценарием.

Ответ №1:

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

Ваш пример может произойти:

  • A отправляет M1 и M2
  • B получает M1
  • Узел, на котором находится B, отключается
  • Узел, на котором находится B, появляется снова
  • A отправляет M3 в B
  • B получает M3

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

Обновленный сценарий:

В обновленном сценарии, при условии, что я прочитал его правильно, 'DOWN' в какой-то момент A получит сообщение о стиле, и аналогично, он получит сообщение, сообщающее вам, что узел снова запущен, если вы отслеживаете узел.

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

Комментарии:

1. Есть ли способ, при котором сообщение теряется без получения отправителем сообщения «ВНИЗ», если отправитель отслеживает получателя? (при условии, что отправитель не выходит из строя)

2. Я обновил вопрос, чтобы лучше отразить мой конкретный сценарий

3. Вы всегда можете получить либо сообщение «ВНИЗ», либо сообщение в стиле NodeDown. Однако нет гарантии, какие сообщения попадают на другой конец. И может потребоваться некоторое время, прежде чем он поймет, что ссылка на узел отключена.

4. Я «могу» всегда получать сообщение DOWN / etc — но всегда ли я буду получать такое сообщение в сценарии, описанном в (обновленном) вопросе?

Ответ №2:

Читая список рассылки erlang и академический faq, кажется, что реализация ERTS предоставляет несколько гарантий, однако я не смог определить, гарантированы ли они также на уровне языка / спецификации.

Если вы предполагаете, что он TCP «надежный», то текущая реализация гарантирует, что
данные A, B являются процессами на разных узлах (и хостах), а A отслеживает B, A отправляет в B, предполагая, что A не сбой, любые сбои доставки сообщений * между двумя узлами или сбои хоста / узла / процесса наB приведет к получению сообщения «DOWN» (или «EXIT» в случае ссылок). [ См. 1 и 2 ]

* Из того, что я прочитал в потоке рассылки, это свойство почти полностью основано на том факте, что используется TCP, поэтому «сбой доставки сообщений» означает любую ситуацию, когда TCP решает, что произошел сбой / соединение должно быть закрыто.

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

Комментарии:

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