#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 ожидают успешной доставки сообщений, а затем соответствующим образом обрабатывают ошибки, обычно путем сбоя задействованных процессов.