WCF дуплексная связь в кластерной среде - PullRequest
3 голосов
/ 30 июля 2009

Итак, я посмотрел примеры примеров, которые люди создавали для Duplex Communications, а именно, когда они размещались в IIS и подключались через Silverlight. Есть множество примеров этого ( эта статья MSDN великолепна ), но все используют ту же самую парадигму:

Пользователь A подключается к серверу A, он помещает его в список в памяти для получения будущих обновлений.
Пользователь B подключается к серверу A, он уведомляет всех пользователей в списке, что кто-то «вошел в систему».

... но что происходит, когда

Пользователь C подключается к серверу C, список в памяти для сервера C не содержит пользователя A или B.

Проблема в том, что я пытаюсь реализовать это в кластерной (веб-ферме) среде. Это усложняет ситуацию, потому что я не могу проверить, какая машина завершит передачу вызова wcf, поэтому передача любого сообщения всем другим пользователям затруднена.

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

Менее эффективное решение состоит в том, чтобы служба постоянно что-то опрашивала (файл на файловом сервере или таблица в БД) в поисках изменений. Когда изменения будут внесены, отправьте их клиентам. Это похоже на очень уродливого ребенка, хотя.

Что я пропустил?

ОБНОВЛЕНИЕ - Система маршрутизации невозможна для моих нужд. Моя хостинговая компания не позволяет мне напрямую подключаться к конкретной машине в ферме по IP. Я могу подключиться только к общему интерфейсу балансировщика нагрузки, поэтому не могу гарантировать, что мои пользователи попадут на один и тот же сервер.

Пока что мы дошли до опроса таблицы в БД в поисках изменений. Все еще кажется уродливым ребенком.

Ответы [ 8 ]

2 голосов
/ 28 августа 2009

Предполагая, что вы имеете нулевой контроль над своей средой, помимо того, что вы можете установить на каждом сервере (то есть без MSMQ, без ESB и т. Д.), Тогда я рассмотрю использование WCF для связи между серверами. Простая проблема заключается в том, что у вас есть список в памяти, который необходимо синхронизировать между двумя серверами, и всякий раз, когда содержимое списка меняется, пользователи обоих серверов должны быть уведомлены.

С помощью внутренней службы WCF, которую размещают и используют как серверы, вы можете использовать простой обмен сообщениями "забыл и забыл", чтобы синхронизировать списки. Представьте себе следующий сценарий:

  1. «Пользователь А» входит на сервер А
    1. Добавить пользователя A в список онлайн-пользователей
    2. Отправить сообщение на сервер B, чтобы уведомить его о добавленном «пользователе A»
      1. Заставляет Сервер B добавлять пользователя A в свой список пользователей в сети
      2. Заставляет Сервер B уведомлять всех пользователей о входе пользователя в систему
    3. Уведомить всех пользователей на сервере A о входе пользователя в систему
  2. «Пользователь B» входит на сервер B
    1. Добавить пользователя B в список пользователей онлайн
    2. Запустить сообщение на сервере A, чтобы уведомить его о добавлении пользователя B
      1. Заставляет Сервер A добавить пользователя B в свой список пользователей в сети
      2. Заставляет Сервер A уведомлять всех пользователей о входе пользователя в систему
    3. Уведомить всех пользователей на сервере B о входе пользователя в систему
  3. «Пользователь А» выходит из сервера А
    1. Удалить пользователя A из списка онлайн-пользователей
    2. Запустить сообщение на сервере B, чтобы уведомить его об удаленном «пользователе A»
      1. Заставляет Сервер B удалить «Пользователя A» из своего списка онлайн-пользователей
      2. Заставляет Сервер B уведомлять всех пользователей о выходе из системы
    3. Уведомить всех пользователей на сервере А о выходе пользователя из системы
  4. Периодически сервер A и сервер B синхронизируют свои списки друг с другом. (Может быть реализован стиль Ping-Pong ... один сервер отправляет свой список другому серверу, другой сервер объединяет и объединяет список обратно)

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

1 голос
/ 28 августа 2009

Похоже, вам нужно использовать одноранговую сеть (netPeerTcpBinding). Я не уверен, поддерживает ли это среда вашего хостинга.

http://msdn.microsoft.com/en-us/library/cc297274.aspx

1 голос
/ 27 августа 2009

Использует ли ваш поставщик решений MS SQL для сервера базы данных? Если у вас есть полные права на базу данных MS SQL, вы можете реализовать триггеры T-SQL. Вы можете написать триггер, который выполняет код, когда происходит операция CRUD базы данных. В текущей версии MS SQL вы даже можете выполнить управляемый (C # / VB #) код.

Это решение было бы очень сложным, но возможным. Я бы использовал центральный MS SQL для вашего кластера и написал бы триггерный код T-SQL. Когда записи, которые вас интересуют, изменены / etc, я бы заставил сервер SQL отправлять специальные сообщения веб-запроса HTTP на другие серверы в кластере (при условии, что сервер в кластере может произвольно общаться с другими / всеми серверами кластера), чтобы они знают о любых изменениях. Затем каждый сервер может использовать глобальный кэш приложения для трансляции изменений каждого сеанса на сервере.

Это мое необычное предложение.

-Джефф

1 голос
/ 25 августа 2009

Использовать Memcached или MSMQ.

С Memcached вы бы использовали его как единую точку правды для всех предметов, которые должны быть переданы. Итак, когда вы получаете логин клиента, вы сбрасываете некоторые простые данные в Memcached. Он уведомляет другой сервер и обновляет список другого сервера. Затем, когда вы публикуете информацию, запрос Memcached.

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

1 голос
/ 22 августа 2009

Могут ли серверы напрямую взаимодействовать друг с другом? Если это так, вы можете настроить частные конечные точки, к которым могут подключаться только другие серверы в ферме. Затем, когда сервер C получает сообщение, он отправляет сообщение на сервер A, информируя его об этом факте, и затем сервер A может пересылать его своим клиентам.

1 голос
/ 11 августа 2009

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

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

0 голосов
/ 28 августа 2009

скоростной проект от MS может быть более быстрым решением для вас, чем серверная часть базы данных; это слой кеша в памяти со всеми причудливыми элементами кластеризации / отработки отказа ... вы можете вставить его между WEB и слоем БД; его API довольно прост и совместим с остальными .NET.

0 голосов
/ 30 июля 2009

Вы можете настроить свою веб-ферму с помощью «Sticky IP».

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

EDIT

Вероятно, проще всего реализовать систему опроса, в которой клиент silverlight спрашивает у веб-сервера «есть ли что-то новое для меня», этот запрос будет содержать время последнего запроса клиента. Список новых вещей будет храниться в таблице базы данных. Так что нет проблем, какой веб-сервер вы попали.

Кроме того, необходимо следить за ограничениями в Silverlight WCF, если я правильно понимаю, что он не реализует все WCF.

РЕДАКТИРОВАТЬ 2

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

РЕДАКТИРОВАТЬ 3

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

  • использовать служебную шину Azure, каждый клиент обращается к конечной точке в облаке, которая преобразуется в прямую связь.
  • Отбросьте с помощью silverlight, используйте клиент, который может предоставить конечную точку службы WCF. Когда клиент запускается, он регистрирует конечную точку на сервере. Каждый клиент может затем спросить сервер, который находится в сети, и отправить сообщение непосредственно клиенту.
...