Silverlight и push-уведомления - PullRequest
20 голосов
/ 13 марта 2009

Я создаю пользовательский интерфейс Silverlight 2 для удаленного прибора. На разных площадках взаимодействуют два одновременно работающих пользователя (оператор на приборе и удаленный ученый) и любое количество пользователей-наблюдателей, не взаимодействующих с ним, просто наблюдающих. Однако всякий раз, когда один из двух активных пользователей что-то меняет, эти изменения должны быть немедленно отражены в пользовательском интерфейсе всех пользователей, например, панорамирование или масштабирование изображения, аннотирование или выделение части изображения, добавление элементов в коллекцию, отображаемую в списке. В клиенте я использую наблюдаемые коллекции, которые легко отражают изменения, сделанные этим пользователем, но труднее видеть изменения, сделанные другим пользователем. Я могу опросить изменения от каждого клиента, но что-то вроде push-уведомлений было бы лучше. Я много гуглил по примерам, но не нашел ничего, что мне нужно. При взаимодействии Silverlight со службами WCF возникают всевозможные проблемы безопасности, что означает, что многие потенциальные примеры просто не работают. У меня практически не осталось времени на этот проект, и мне нужна срочная помощь. У кого-нибудь есть предложение подходящего простого примера, который иллюстрирует, как это сделать? Я опытный разработчик, но мне приходилось учить себя службам Silverlight и WCF, и в моем районе нет никого, кто бы что-нибудь знал об этом. Даже несмотря на то, что я проделал немалую работу над ASP.NET, я не гуру веб / Javascript. Спасибо.

Ответы [ 8 ]

10 голосов
/ 13 марта 2009

Push-уведомление поддерживается в Silverlight 2 с использованием новой поддержки WCF PollingDuplexHttpBinding. Вместе с Silverlight SDK установлено две сборки ( одна для приложения Silverlight, другая для сервера WCF ).

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

В последней версии образца (часть 4) показано, как синхронизировать push-обновления между клиентами Silverlight и WPF с использованием двух конечных точек сервера следующим образом:

using System;
using System.ServiceModel;
using System.ServiceModel.Description;

namespace StockServer
{
    public class StockServiceHost : ServiceHost
    {
        public StockServiceHost(object singletonInstance, params Uri[] baseAddresses)
            : base(singletonInstance, baseAddresses)
        {
        }

        public StockServiceHost(Type serviceType, params Uri[] baseAddresses)
            : base(serviceType, baseAddresses)
        {
        }

        protected override void InitializeRuntime()
        {
            this.AddServiceEndpoint(
                typeof(IPolicyProvider),
                new WebHttpBinding(),
                new Uri("http://localhost:10201/")).Behaviors.Add(new WebHttpBehavior());

            this.AddServiceEndpoint(
                typeof(IStockService),
                new PollingDuplexHttpBinding(),
                new Uri("http://localhost:10201/SilverlightStockService"));

            this.AddServiceEndpoint(
                typeof(IStockService),
                new WSDualHttpBinding(WSDualHttpSecurityMode.None),
                new Uri("http://localhost:10201/WpfStockService"));

            base.InitializeRuntime();
        }
    }
}

Клиенты WPF подключаются к конечной точке WSDualHttpBinding, а клиенты Silverlight подключаются к конечной точке PollingDuplexHttpBinding той же службы WCF. В приложении также показано, как обрабатывать требования политики доступа клиента Silverlight.

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

Вы можете увидеть скриншот демо-приложения , запущенного здесь .

6 голосов
/ 13 марта 2009

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

Мы берем три компонента и объединяем их вместе, чтобы реализовать эту возможность:

  1. Шаблон кометы (HTTP-совместимый способ отправки push-уведомлений на сервере - дополнительную информацию можно найти в Википедии)
  2. Темы обмена сообщениями JMS (публикации / очереди подписчиков)
  3. Сервлет Adobe BlazeDS

Последний элемент реализует шаблон Comet, поддерживает маршалинг объектов AMF (двоичный формат сериализации Adobe для объектов ActionScript3) и соединяется с очередью или темой JMS. При соединении с темой несколько клиентов Flex, работающих в браузере, могут быть проксированы как подписчики на тему JMS. Поэтому, если какой-либо клиент публикует сообщение (или серверный код публикуется в теме), всем подписчикам клиента будет отправлено сообщение через BlazeDS и реализацию Comet Pattern.

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

Поддерживает ли WCF шаблон Comet и двунаправленный обмен сообщениями? Особенно там, где соответствует HTTP и порт 80 или порт 443 для SSL. Похоже, вы уже изучили это и не нашли ничего для двунаправленного обмена сообщениями. Поэтому вам, возможно, придется закатать рукава и заняться кодированием.

Несколько замечаний по поводу отправки сервера в веб-приложение:

BlazeDS поддерживает два основных режима реализации шаблона Comet (на самом деле есть третий вариант опроса, но я его игнорирую):

  1. долго-опрос
  2. Потоковое HTTP

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

Что касается брокера сообщений, который может обеспечить возможность публикации / приостановки, вы можете рассмотреть возможность использования ActiveMQ JMS. Это с открытым исходным кодом и бесплатно с активной поддержкой сообщества (вы также можете купить поддержку). Кроме того, вы можете использовать NMS для интеграции в качестве клиента .NET.

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

Еще одна вещь, которую следует учитывать в сценариях с большим объемом трафика (сотни или тысячи клиентов, таких как веб-сайт в Интернете), вам необходимо иметь подход к масштабируемому шаблону кометы.

В мире Flex / Java сервлет BlazeDS (с открытым исходным кодом) был модифицирован для работы с асинхронной моделью. В Java слушатель сокетов может быть построен для использования каналов NIO и потоковых потоков Java Concurrency Executor. Веб-сервер Tomcat имеет приемник NIO и поддержку асинхронных событий Servlet 3.0. В частности, BlazeDS был модифицирован для работы с веб-сервером Jetty. Суть в том, что масштабируемость этого асинхронного подхода означает, что отдельный физический веб-сервер может быть расширен для поддержки примерно до 20 000 одновременных клиентских соединений в стиле Comet.

Прошло много времени с тех пор, как я серьезно занимался программированием на .NET, но привык к тому, что возможности io были очень похожи на Java 1.1, за исключением возможности асинхронного обработчика результатов. Это, однако, не то же самое, что создание асинхронных слушателей сокетов через каналы Java NIO. Реализация канала NIO может поддерживать от сотен до тысяч соединений сокетов с относительно небольшим пулом потоков. Но C # и .NET прошли через два или три значительных оборота - возможно, были добавлены новые возможности ввода-вывода, сравнимые с каналами NIO.

3 голосов
/ 02 сентября 2009

Я просто хотел уточнить, что PollingDuplexHttpBinding не реализует «истинные» push-уведомления, поскольку раскрывает его имя (опрос). Из документации msdn :

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

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

Если вы хотите реализовать настоящие push-уведомления с помощью Silverlight, я считаю, что вам нужно работать с сокетами, и я рекомендую прочитать некоторые сообщения в блоге Дэна Уолина на эту тему.

2 голосов
/ 30 июня 2009

РЕДАКТИРОВАТЬ: на самом деле работает нормально. Меня сильно укусила скрытая переменная в закрытии: (

Я использовал PollingDuplex для SL2 и думаю, что он еще не готов к производству.

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

Аналогичным образом, если я убью клиента, а затем создам нового, новый клиент какое-то время получит push-обновления от предыдущего клиента.

Кто-нибудь сталкивался с такими же проблемами или они исправлены в SL3?

На самом деле я запустил еще несколько демонстрационных кодов и понял, что по какой-то причине вы должны указать InstanceContextMode и InstanceMode, чтобы служба основывалась на сеансах, а не на одиночном (насколько я могу судить). В простом демонстрационном коде, который я вытащил, есть явные проблемы с производительностью.

К сожалению, такое поведение не было задокументировано.

2 голосов
/ 19 мая 2009

С другой стороны,

Если вам нужен собственный Silverlight API без прокси, мостов или веб-серверов, вы можете использовать Nirvana из my-Channels в качестве промежуточного программного обеспечения для обмена сообщениями. Проверьте Нирвану от моих каналов и их демонстрационный сайт. (извините, я новый пользователь и не могу отправить ссылки):

Alex

1 голос
/ 24 марта 2009

Моя организация нашла, что принудительная реализация Silverlight 2.0 / WCF немного "не готова к прайм-тайм", по крайней мере, для того, для чего мы планировали ее использовать.

В итоге мы выбрали XMPP / Jabber, потому что это более хорошо сформированный зверь, и вы можете довольно легко реализовать его в Silverlight, просто вытащив некоторые ресурсы из Интернета.

Я верю, что Silverlight 3.0 будет реализовывать более новую / более правильно сформированную реализацию push, насколько я могу судить по общедоступной информации.

0 голосов
/ 05 июня 2009

Одно гораздо более простое и мощное решение на сайте http://www.udaparts.com/document/Tutorial/slpush.htm

0 голосов
/ 13 марта 2009

PollingDuplexHttpBinding, вероятно, самый элегантный способ сделать это.

Еще одна менее сложная альтернатива - использовать TCP-сокет от клиента Silverlight. Когда одному из клиентов Silverlight необходимо отправить обновление, вы можете отправить ему TCP-сообщение, содержащее имя службы WCF, которую он должен вызвать, или некоторую другую легковесную информацию.

Я использую этот подход для приложения, и он хорошо работает.

...