Самоорганизующиеся приложения - PullRequest
18 голосов
/ 06 февраля 2012

У меня есть следующие требования к приложению, которое многие люди будут использовать в офисе - без серверного компонента. Все экземпляры клиентских приложений должны как-то договариваться между собой, чтобы решить, какой клиент возьмет на себя роль сервера. И клиенты должны общаться между собой по IP.

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

Я думаю, что у меня не работает связь с приложением По сути, когда приложение запускается, оно объявляет себя через UDP (либо на заранее определенный IP-адрес, который все слушает, либо через широковещательную передачу UDP). С этого момента общение происходит аналогичным образом.

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

Я создал прототип в c #, который связывается и пытается реплицировать данные, но часть согласования (особенно в сочетании с ошибкой клиента).

Первоначально я думал, что это то, что сделал ZeroConf (он же Bonjour). Но это только объявляет о доступных сетевых услугах.

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

  • Есть ли шаблон, который уже реализует то, что я описал выше?
  • Если да, есть ли для этого доступная библиотека .NET (или даже нативная)?
  • Каковы хорошие способы согласования роли сервера среди клиентов?

Ответы [ 3 ]

6 голосов
/ 06 февраля 2012

Выбор сервера из группы машин, независимо от того, являются ли эти машины клиентами или нет, является чрезвычайно нетривиальной проблемой.Это называется выборами лидера.Основная работа, которую вы должны читать, - это «1001 * Парламент неполного рабочего дня» Лесли Лампорта , в котором описывается протокол Paxos.Google использовал Paxos для разработки системы под названием Chubby , которая служит цели, которую вы описываете.

При этом вам, вероятно, следует взглянуть на систему, подобную Apache ZooKeeper , которая представляет собой реализацию распределенного выбора лидера с открытым исходным кодом (хотя и Java) и, в более широком смысле, управление распределенной блокировкой, которое было тщательно протестировано при большой нагрузке.Платформа распределенного хранения и обработки данных Hadoop и, в частности, распределенная база данных HBase , работающая на Hadoop, активно используют ZooKeeper для определения того, кто отвечает за группу.сервера.Таким образом, любой из них может потерпеть неудачу, а другие сами решают, кто займет эту работу.

Как я упоминал ранее, выборы лидера чреваты ошибкой.Это очень трудно понять правильно.Я реализовал paxos "для удовольствия" полдюжины раз в C #, и во всех моих реализациях есть ошибки.

4 голосов
/ 06 февраля 2012

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

Это, конечно, не новая идея.То, что вы хотите, это добавить некоторые дополнительные разговоры во время начального соединения «здесь я».Когда новый клиент выкрикивает «здесь я» остальной части локальной сети, если есть сервер, сервер должен сказать «Добро пожаловать, я сервер», и новое клиентское приложение теперь знает, какой клиент действует каксервер.Все остальные клиенты, вероятно, также должны сказать «привет».Если сервера нет, новый клиент должен сначала повторить «привет» (в конце концов, это UDP; нужно ожидать, что некоторые сообщения не будут получены), и если никто не отвечает, этот новый клиент является единственным насеть и является «сервером» по умолчанию.Если есть другие, но никто не претендует на роль сервера, клиенты могут «обсудить между собой», чтобы определить новый сервер.

В дополнение к этому, серверная копия должна периодически (возможно, каждые 3-5 секунд).) кричать "я все еще здесь" всем;это называется «сердцебиение» и является очень распространенной альтернативой двухстороннему методу проверки «ping».

Если приложение сервера (или любая копия, действительно) закрывается нормально, оно должно выкрикнутьиз "прощай всем, выясни, кто следующий сервер".Затем оставшиеся клиенты могут обсудить между собой.Если клиент, выступающий в роли сервера, выходит из строя, клиенты пропускают «сердцебиение» на сервере, спрашивают «кто сервер», и, если никто не отвечает, клиенты будут обсуждать между собой.

Теперь клиенты обсуждают средисами по себе »могут быть такими же простыми или сложными, как вам нравится.Самым простым было бы то, чтобы любой клиент сказал «ОК, я теперь сервер», чтобы стать сервером.Возможно, вам придется включить какое-то время в сообщение, чтобы, если другой компьютер сказал это одновременно, клиенты могли сказать: «Хорошо, клиент 15 сказал это первым, поэтому мы пойдем с ним».Клиенты могут «голосовать»;пусть каждый клиент говорит со всеми остальными, чтобы определить номинальную задержку между этим клиентом и всеми остальными, и этот клиент будет «голосовать» за соединение с минимальной задержкой (ни один клиент не может голосовать за себя, если он не обнаружит, что он единственный).Большинство голосов побеждает.

Или сервер может в рамках своего сообщения «пульса» сказать «если я выйду из строя, мой преемник - клиент Х»;и если пропущено сердцебиение, а последующие сообщения от клиентов «вы все еще здесь, сервер» не отвечают, клиенты могут сказать: «Король мертв! Да здравствует King Client X!».

Поймите, что по необходимости, этот уровень управления в системе, состоящей из всех клиентов, при выборе «авторитетного» клиента, который станет сервером, значительно увеличит сложность взаимодействия с клиентом.Кроме того, в то время как использование вами протокола UDP обеспечивает быструю связь, сообщения UDP конфликтуют ВСЕ ВРЕМЯ;если вы разговариваете, когда разговаривает другой человек, ваши сообщения сталкиваются.Таким образом, я бы рекомендовал использовать TCP вместо UDP для большинства коммуникаций в этом программном обеспечении, в которых необходимо, чтобы конкретный клиент был услышан.Это любой прямой опрос клиента («вы все еще там, сервер?»), Какой бы процесс вы ни использовали, чтобы клиенты решали, кто новый сервер и т. Д. И т. Д.

3 голосов
/ 06 февраля 2012

Зачем вам вообще нужно договариваться о роли сервера? Подумай об этом на секунду. Если каждый «клиент» может обрабатывать «серверные» обязанности для работы, инициированной на клиенте, то все в определенной степени обрабатывают и клиента, и сервер. Тогда единственной проблемой является согласование репликации постоянного состояния между клиентами и обработка параллелизма, когда два клиента обрабатывают один и тот же бит состояния (с моей точки зрения, самой сложной частью было бы оповещение об изменении состояния других клиентов, когда один клиент "сохраняет" данные и наличие других клиентов, работающих над состоянием, открывают метод для разрешения столкновений - это может не быть проблемой, если всегда побеждает последний, но это редко).

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

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

...