Поделиться через


Ограничение распространения сообщений

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

Число прыжков

Понятие PeerHopCount аналогично понятию "срок жизни", используемому в протоколе IP. Значение PeerHopCount привязывается к экземпляру сообщения. Оно указывает, сколько раз следует перенаправить сообщение, прежде чем отбросить его. Каждый раз, когда клиент однорангового канала получает сообщение, он проверяет, указано ли значение PeerHopCount для этого сообщения. Если оно указано, клиент уменьшает значение числа прыжков на единицу, прежде чем перенаправить сообщение на соседние узлы. Если клиент получает сообщение с нулевым числом прыжков, он обрабатывает сообщение, но не перенаправляет его соседям.

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

Фильтр распространения сообщений

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

PeerMessagePropagationFilter - базовый абстрактный класс с единственной функцией ShouldMessagePropagate. Первый аргумент при вызове метода передает полную копию сообщения. Никакие изменения, внесенные в сообщение, не влияют на фактическое сообщение. Последний аргумент при вызове метода указывает источник сообщения (PeerMessageOrigination.Local или PeerMessageOrigination.Remote). Конкретные реализации этого метода должны возвращать константу из перечисления PeerMessagePropagation, указывающую, что сообщение необходимо перенаправить локальному приложению (Local), удаленным клиентам (Remote), и тому и другим (LocalAndRemote) или ни тому ни другим (None). Этот фильтр можно применить, обратившись к соответствующему объекту PeerNode и указав экземпляр производного класса фильтра распространения в свойстве PeerNode.MessagePropagationFilter. Прежде чем открыть одноранговый канал, убедитесь, что фильтр подключен.

Обращение к одному из узлов сетки

Можно обратиться к одному из узлов сетки, настроив локальный фильтр или прямое подключение.

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

Для длительных передач больших объемов данных предпочтительно использовать прямые подключения. Можно отправить по сетке информацию о подключении, а затем настроить прямое подключение для отправки и приема сообщений.

Выбор способа ограничения распределения сообщений

Если необходимо ограничить распределение сообщений, следует продумать следующие вопросы:

  • Кто необходимо получить сообщение? Только на соседний узел? На узел в другой части сетки? На половину узлов сетки?

  • Как часто будет отправляться это сообщение?

  • Какую пропускную способность будет использовать это сообщение?

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

  • Кто?

    • Отдельный узел: локальный фильтр или прямое подключение.

    • Соседи в определенной близости: PeerHopCount.

    • Сложное подмножество сетки: MessagePropagationFilter.

  • Как часто

    • Очень часто: прямое подключение, PeerHopCount, MessagePropagationFilter.

    • Иногда: локальный фильтр.

  • Использование пропускной способности

    • Высокий уровень: прямое подключение, менее рекомендуется использовать MessagePropagationFilter или локальный фильтр.

    • Низкий: Любое прямое подключение, вероятно, не требуется.

См. также