Руководство по Microsoft® .NET Service Bus для разработчиков

advertisement
Руководство по Microsoft®
Service Bus для разработчиков
.NET
Технология ПО + сервисы становится реальностью на
платформе Windows
Аарон Сконнард, Pluralsight
Май 2009
Все приведенные здесь сведения и фрагменты кода касаются CTP-версии .NET Services, вышедшей в
марте 2009 года.
Содержание
Аннотация ........................................................................................................................................3
Краткий обзор .NET Service Bus ........................................................................................................3
Шаблон Enterprise Service Bus ................................................................................................................ 4
Переход к Сервисной шине Интернета ................................................................................................. 6
Введение в .NET Service Bus.................................................................................................................. 10
Ваше первое решение для .NET Service Bus........................................................................................ 11
Присваивание имен и поиск .......................................................................................................... 20
Система имен ........................................................................................................................................ 20
Реестр сервиса ....................................................................................................................................... 22
Обмен сообщениями ..................................................................................................................... 27
Сервис ретрансляции ............................................................................................................................ 27
Слушатели и присваивание имен ........................................................................................................ 28
Порты, необходимые сервису ретрансляции ..................................................................................... 29
WCF-привязки ретрансляции ............................................................................................................... 29
NetOnewayRelayBinding ........................................................................................................................ 32
NetEventRelayBinding ............................................................................................................................ 36
NetTcpRelayBinding ................................................................................................................................ 39
HTTP-привязки ретрансляции .............................................................................................................. 45
Управление доступом .................................................................................................................... 50
Аутентификация и авторизация ........................................................................................................... 50
Модель программирования WCF для управления доступом ........................................................... 52
Аутентификация в стиле Веб (REST) ..................................................................................................... 54
Очереди и маршрутизаторы .......................................................................................................... 55
Понимание очередей и маршрутизаторов ......................................................................................... 55
Программирование очередей ............................................................................................................. 58
Программирование маршрутизаторов ............................................................................................... 63
Рекомендации ............................................................................................................................... 69
Заключение .................................................................................................................................... 71
Дополнительные ресурсы .............................................................................................................. 71
Пакеты документов по Microsoft® .NET Services................................................................................. 72
Ресурсы .NET Service Bus ....................................................................................................................... 72
Об авторе ....................................................................................................................................... 72
Благодарности................................................................................................................................ 72
Аннотация
При переходе приложений на платформу обработки данных в облаке, предлагаемую Windows®
Azure, возникнет необходимость в объединении существующих локальных программных ресурсов
с новыми выполняющимися в облаке ресурсами. Эту стратегию сегодня называют программное
обеспечение + сервисы (software + services). Если существует возможность установления
двусторонней связи, такой тип интеграции может быть осуществлен через стандартные
протоколы. Тогда как организация передачи данных от локальных приложений к сервисам в
облаке обычно не составляет никакого труда, обратное куда как намного сложнее из-за того, что
локальное программное обеспечение, как правило, выполняется за многочисленными
межсетевыми экранами или NAT-устройствами. Microsoft® .NET Service Bus адресована решению
именно этих проблем, упрощая создание безопасных двунаправленных каналов связи между
локальным ПО и сервисами в облаке.
Краткий обзор .NET Service Bus
Microsoft® .NET Services1 – это набор высокомасштабируемых ориентированных на разработчика
сервисов, выполняющихся в центрах обработки данных Microsoft как часть платформы Azure™
Services Platform. Microsoft .NET Services предоставляет разработчикам основные стандартные
блоки и инфраструктуру сервисов для приложений в облаке и работающих с облаком. Во многом
аналогично тому, как .NET Framework обеспечивает основные стандартные блоки для разработки
локального ПО, Microsoft® .NET Services предлагает основные стандартные блоки для приложений
в облаке.
Microsoft® .NET Service Bus – один из основных предлагаемых сервисов, входящих в состав
Microsoft® .NET Services. Сегодня его дополняют два других сервиса: Microsoft® .NET Access Control
Service и Microsoft® .NET Workflow Service. .NET Service Bus полагается на Access Control Service в
управлении доступом к решениями через модель безопасности на базе утверждений. .NET
Workflow Service позволяет описывать рабочие процессы в облаке, моделирующие
взаимодействия с сервисами через .NET Service Bus. Совместно эти сервисы обеспечивают
1
Microsoft® .NET Services – новое, боле подходящее имя исходной инициативы BizTalk Services.
полноценную среду разработки, необходимую большинству приложений в облаке. Они
предоставляют разработчику возможность сосредоточить внимание исключительно на бизнестребованиях, таким образом, упрощая разработку для облака.1
Данный документ посвящен возможностям решения некоторых наиболее распространенных в
современном мире проблем подключения к Интернету с помощью .NET Service Bus. Во-первых,
мы обсудим мотивацию применения .NET Service Bus, реализуемый им архитектурный шаблон и
ключевые аспекты архитектуры, обязательные для понимания. Затем, после быстрого обзора
вашего первого приложения .NET Service Bus, углубимся в изучение каждой отдельно взятой
области архитектуры .NET Service, исследуем различные предлагаемые ею варианты обмена
сообщениями и обсудим, как они интегрируются с .NET Access Control Service. И, наконец, в конце
данного документа будут предложены рекомендации по наилучшему использованию .NET Service
Bus в ваших приложениях.
Шаблон Enterprise Service Bus
Название .NET Service Bus было дано не просто так. Имя «шина сервисов» выбрано, чтобы
подчеркнуть определенные характеристики базовой архитектуры. На самом деле, эти
архитектурные характеристики довольно широко распространены сегодня благодаря
воплощениям в различных продуктах архитектурного шаблона Enterprise Service Bus (ESB) 2 .
Шаблон ESB определяет модель интеграции прикладных систем предприятия через общую среду
обмена сообщениями или «шину» (рис. 1).
Шаблон ESB обычно требует интегрированного механизма идентификации и управления
доступом, общего механизма присваивания имен сервисам, доступного для просмотра реестра
сервиса и общей среды обмена сообщениями, обеспечивающей различные варианты связи. Эта
модель представляет уровень преобразования логических адресов в физические между
различными сервисами шины и между составными приложениями и сервисами, используемыми
ими. Шаблон ESB помогает преодолеть различия между сервисами с точки зрения управления
идентификацией, соглашений о присваивании имен, форматов сообщений и протоколов связи.
Как только сервис попадает в шину, все остальные сущности, входящие в нее, могут связываться с
ним, даже несмотря на то, что в обычных условиях взаимодействие между ними напрямую было
бы невозможным.
1
Более подробно Microsoft® .NET Services, .NET Access Control Service и .NET Workflow Service рассматриваются в
сопутствующих документах серии «Пакеты документов по Microsoft .NET Services», ссылки на которые можно найти в
конце данного документа.
2 Сервисная шина предприятия (прим переводчика).
Service Orchestration
Federated Identity and Access Control
Взаимодействие сервисов
Интегрированные идентификация и управление
доступом
Naming
Присваивание имен
Service Registry
Реестр сервиса
Messaging Fabric
Среда обмена сообщениями
Point Of Sale
Пункт продажи
POS Integration
Интеграция POS
Product Catalog
Каталог продуктов
Web Store
Веб-магазин
Returns
Прибыль
Supply Chain
Канал поставок
Inventory
Товары
Order Entry
Регистрация заказа
Purchasing
Закупка
Planning
Планирование
CRM
Система управления взаимоотношениями с
клиентами
Customers
Покупатели
Leads
Руководство
Campaigns
Компании
Trends
Тенденции
Рис. 1: Шаблон Enterprise Service Bus
Популярность шаблона ESB растет, потому что он упрощает управление соединениями множества
сервисов. Один из аспектов, обеспечивающих это – включение архитектур публикации/подписки,
что обеспечивает даже еще более слабое связывание в рамках предприятия. Когда используется
архитектура публикации/подписки, клиентам больше нет необходимости связываться с сервисами
напрямую, требуется просто подключение к шине, и узлы могут добавляться или удаляться со
временем по желанию. Такой тип архитектуры также обеспечивает распространение событий.
Может существовать множество подписчиков на какой-то один тип сообщения, и также может
быть множество издателей этого типа событий, таким образом, реализуется многоадресная
рассылка N-к-N.
Большинство сред ESB расширены уровнем взаимодействия сервисов, который обеспечивает
механизм последовательности операций процесса для управления взаимодействиями
сообщений, образующими бизнес-процесс или «рабочий процесс».
Сейчас доступно множество различных продуктов и технологий для реализации ESB, включая
Active Directory, UDDI, BizTalk Server, MSMQ и WCF. Также существует довольно обширный ряд
эквивалентных предложений на других платформах. В большинстве окружений ESB среда обмена
сообщениями просто размещается в Ethernet и TCP/IP. Затем эта исходная база расширяется
различными серверными продуктами и технологиями обмена сообщениями, обеспечивающими
различные семантики обмена сообщениями.
Для реализации семантики надежного асинхронного обмена сообщениями может использоваться
MSMQ или BizTalk Server, если необходимо применить модель интеграции «звезда». Также
технологии обмена сообщениями между равноправными участниками сети могли бы быть
реализованы посредством WCF или более отвечающей принципам RESTful модели, построенной,
преимущественно, средствами протокола HTTP. Среда обмена сообщениями ESB может
поддерживать все эти варианты обмена сообщениями и абстрагироваться от их отличий.
Шаблон ESB доказал свою значимость для управления локальными приложениями, однако, по
мере того, как все большее количество программных ресурсов переходят к схеме работы с
облаком, появляются все новые и новые проблемы, которые необходимо решать.
Переход к Сервисной шине Интернета
Microsoft активно работает над реализацией возможности использования шаблона ESB в рамках
Интернета. Если подумать, что подразумевается под этим, можно понять, что понадобятся все те
же архитектурные компоненты ESB: идентификация и управление доступом, присваивание имен,
реестр сервиса и общая среда обмена сообщениями. Основное отличие в области действия: в
данном случае различные компоненты ESB должны проектироваться для работы в облаке, в
Интернете, с обеспечением высокой масштабируемости и интегрируемости. Вот что
подразумевали под реализацией Internet Service Bus (рис. 2) в Microsoft ранее.1
1
Эта терминология применялась в документации BizTalk Services, но более не является официальным наименованием,
используемым Microsoft.
Service Orchestration
Federated Identity and Access Control
Взаимодействие сервисов
Интегрированные идентификация и управление
доступом
Naming
Присваивание имен
Service Registry
Реестр сервиса
Messaging Fabric
Среда обмена сообщениями
Your Services
Ваши сервисы
Clients
Клиенты
Desktop, RIA, & Web
Настольные, RIA & Веб
On-Premise ESB
Локальная ESB
ESB
ESB
rd
MS/3 Party Services
Сервисы MS/сторонних производителей
Рис. 2: Internet Service Bus
Internet Service Bus сделала бы возможным интегрировать вашу локальную ESB 1 с вашими
сервисами, выполняющимися в облаке, с различными сервисами сторонних производителей или
Microsoft (такими как предлагаются в рамках платформы Azure Service Platform) и с различными
настольными, RIA 2 и веб-приложениями, которые могут выполняться во внешних
местоположениях вне межсетевого экрана предприятия. Чтобы претворить это в жизнь, данная
реализация должна предоставлять интегрированные решения, основанные на открытых
Интернет-стандартах, и надежную среду обмена сообщениями, обеспечивающую возможность
двусторонней связи в Интернете.
Организация двусторонней связи в Интернете не такая простая задача в виду некоторых реалий
сегодняшнего дня. Первая проблема – нехватка IPv4-адресов. В настоящий момент они
применяются так широко, что теперь очень сложно получить открытый IPv4-адрес. Вместо них
большинство Интернет-провайдеров, корпоративных сетей и беспроводных сетей используют
1
2
Enterprise service bus – Сервисная шина предприятия (прим. переводчика).
RIA = Rich Internet Application (насыщенное )
динамическое распределение IP-адресов и преобразование сетевых адресов (network address
translation, NAT). Такие IP-адреса являются частными для этих сетей и недоступными для
открытого доступа извне.
Другая проблема связана с безопасностью. В большинстве сред предприятий локальное
программное обеспечение практически полностью отгорожено от внешнего мира множеством
уровней межсетевых экранов и другими защитными сетевыми устройствами. Это необходимо,
поскольку Интернету присущи масштабные угрозы безопасности.1 Большинство сетевых сред
допускают наличие множества исходящих портов в своих межсетевых экранах, но жестко
ограничивают допустимое количество входящих портов.2 Часто порты 80 (HTTP) и 443 (HTTPS)
являются единственными санкционированными входящими портами, что представляет большую
проблему для различных типов двусторонней связи.
Представим ситуацию: торговый агент находится в командировке и использует ваше приложение
в беспроводной сети в случайной гостинице в некоторой точке земного шара (рис. 3). В подобных
сценариях бывает очень сложно установить связь с компьютерами, располагающимися за
множеством различных сетевых уровней.
Sender
Отправитель
Laptop on a hotel wireless network somewhere in Портативный компьютер в беспроводной сети в
the world
некоторой точке мира
Network Address Translation
Преобразование сетевых адресов
Network Firewall
Межсетевой экран сети
Machine Firewall
Межсетевой экран компьютера
Receiver
Получатель
Рис. 3: Проблемы установления подключений в Интернете
Часто компании решают эти проблемы установления подключения, открывая входящие порты
межсетевых экранов (что доставляет немало хлопот системным администраторам) или используя
различных обходные приемы, такие как динамическая DNS, сопоставление портов NAT или
1
Никто не будет оспаривать то, что Интернет наводнен злоумышленниками. Сегодня, если у вас есть что-то ценное, вы
обязательно должны предусмотреть защиту. Поэтому большинство корпоративных сред защищают себя множеством
уровней межсетевых экранов.
2 Для установления связи с приложением, располагающимся за межсетевым экраном, необходим входящий порт.
технологию UPnP. Все эти методы неустойчивы, трудно управляемы и восприимчивы к угрозам
безопасности. С ростом числа приложений, для которых требуется такой тип двусторонней связи,
все сильнее ощущается необходимость в новых методах ее обеспечения, особенно в связи с тем,
что упомянутые приемы зачастую абсолютно ни на что не годятся.
Несмотря на эти трудности, некоторые наиболее популярные на сегодняшний день приложения
являются по сути своей двунаправленными. Например, приложения для обмена мгновенными
сообщениями, сетевые игры для нескольких участников и приложения совместного
использования файлов равноправными участниками сети, использующие такие протоколы, как
BitTorrent, составляющие большую долю всего Интернет-трафика сегодня. В этих приложениях для
преодоления межсетевых экранов и NAT-устройств, а также установления прямых соединений
между равноправными участниками сети, когда это возможно, используется низкоуровневая
логика работы с сетью. Обычно это выполняется через центральный сервис ретрансляции,
который обеспечивает логику установления подключения (рис. 4).
Relay Service
rendezvous address
Outbound connect
Outbound connect (bidirectional socket)
Msg
Sender
Receiver
Firewall
Dynamic IP
Сервис ретрансляции
адрес встречи
Исходящее соединение
Исходящее соединение (двунаправленный
сокет)
Сообщение
Отправитель
Получатель
Межсетевой экран
Динамический IP
Рис. 4: Сервис ретрансляции
Получатель подключается к сервису ретрансляции через исходящий порт и создает
двунаправленный сокет для обмена данными, связанный с конкретным адресом встречи. После
этого отправитель может обмениваться данными с получателем путем отправки сообщений на
сервис ретрансляции, указывая этот адрес встречи. В свою очередь, сервис ретрансляции
«ретранслирует» эти сообщения получателю через существующий двунаправленный сокет. Для
этого отправителю не надо устанавливать прямое соединение с получателем. И получателю нет
необходимости открывать входящие порты в межсетевом экране. По такой схеме сегодня
работает большинство приложений для обмена мгновенными сообщениями.
Таким образом, «сервисная шина» для успешной работы в Интернете должна обеспечивать среду
обмена сообщения, способную решать эти проблемы с подключением посредством сервиса
ретрансляции в облаке.
Введение в .NET Service Bus
Microsoft® .NET Service Bus является конкретной реализацией шаблона сервисной шины,
спроектированной для работы в Интернете в рамках высокомасштабируемых центров обработки
данных Microsoft. .NET Service Bus обеспечивает интегрированный механизм идентификации и
управления доступом (посредством .NET Access Control Service), интегрированную систему
присваивания имен, динамический реестр сервиса и надежную среду обмена сообщениями,
способную преодолевать проблемы с подключением, описанные в предыдущем разделе. Кроме
того, в сочетании с .NET Service Bus может использоваться .NET Workflow Service для обеспечения
уровня взаимодействия сервисами, как показано на рис. 2.
Основной компоненты среды обмена сообщениями .NET Service Bus – централизованный (но со
строгой балансировкой нагрузки) сервис ретрансляции, поддерживающий множество различных
транспортных протоколов и стандартов веб-сервисов, включая SOAP, WS-* и даже REST. Сервис
ретрансляции обеспечивает разные варианты подключения и может даже способствовать в
установлении прямых соединений между равноправными участниками сети, когда это возможно.
.NET Service Bus спроектирован независимым от платформы, т.е. подходит для всех
разработчиков, но оптимизирован для .NET-разработчиков, использующих Windows
Communication Foundation (WCF), с точки зрения, как производительности, так и удобства
использования. .NET Service Bus предоставляет полный доступ к своему сервису ретрансляции
через интерфейсы SOAP и REST, аналогично сервисам .NET Access Control Service и .NET Workflow
Service. Это обеспечивает возможность интеграции с этими сервисами Azure любой среды
программирования, поддерживающей SOAP или REST.
На сайте Microsoft .NET Services (см. «Дополнительные ресурсы») можно скачать несколько
ориентированных на разные среды программирования SDK для интегрирования с этими
сервисами. Сегодня предлагаются Java SDK, Ruby SDK и, конечно же, Microsoft® .NET Services SDK.
Если вы .NET-разработчик, уверенно себя чувствующий с WCF, .NET Services SDK сделает работу с
.NET Service Bus такой же привычной. .NET Services SDK устанавливает набор новых WCF-привязок
«ретрансляции» (и соответствующие компоненты каналов), которые обеспечивают интеграцию с
.NET Service Bus в фоновом режиме. Благодаря им программирование для .NET Service Bus ничем
не отличается от работы с традиционными клиентами и сервисами WCF.
Ваше первое решение для .NET Service Bus
Чтобы начать работу с .NET Service Bus, необходимо сначала зарегистрироваться на портале Azure
Services Platform для получения учетной записи .NET Services (см. «Дополнительные ресурсы»).
При этом ваш Windows Live ID (WLID) будет ассоциирован с учетной записью Azure Services.
Получив учетную запись, вы можете регистрироваться на портале .NET Services, используя свой
WLID, после чего можно выбирать опцию «Create a New Solution» (Создать новое решение). Новое
решение должно обладать уникальным среди всех решений .NET Services.1 На рис. 5 показано, как
выглядит портал .NET Services после создания нескольких решений.
Каждое решение выступает в роли контейнера для набора конечных точек .NET Service Bus. Имя
решения является именем пользователя для решения. В процессе подготовки вы получите также
пароль решения, который можно изменять впоследствии. Эти учетные данные потом
используются в .NET-коде.
На этой странице представлены ссылки для начала работы, переходя по которым, можно
подробнее узнать о том, как начать использовать каждый из сервисов .NET Services, или можно
щелкнуть имя одного из решений для работы с ним. По щелчку имени решения вы переходите на
страницу управления решением, которая позволяет управлять учетными данными решения и
различными аспектами каждого отдельного сервиса .NET Services. На рис. 6 показан пример такой
страницы для решения «pluralsight».
Рис. 5: Создание нового решения .NET Services
1
Процедура начала работы с новым решением подробно описана в документе «Введение в Microsoft .NET Services для
разработчиков». Что касается CTP-версии, вышедшей в марте 2009 года, в ней для создания нового решения .NET
Services больше не требуется маркер приглашения.
Рис. 6: Управление решением .NET Services
По щелчку ссылки .NET Service Bus выполняется переход на страницу, описывающую ваше
решение .NET Service Bus. Здесь дается краткая справка по тому, какой формат URI должен
использоваться, а также ссылка на канал ATOM, выступающий в роли реестра сервиса данного
решения (рис. 7).
Рис. 7: Начало работы с решением .NET Service Bus
Как показано на этой веб-странице, базовый URI для всех конечных точек решения «pluralsight» http://pluralsight.servicebus.windows.net/. Этот базовый URI можно дополнять справа по
собственному желанию. Перейдя по базовому URI решения, вы получите канал Atom,
представляющий реестр решения. На данный момент он будет пуст, поскольку в решении еще не
зарегистрировано ни одной конечной точки (рис. 8).
Рис. 8: Пустой канал Atom для решения ‘pluralsight’
Теперь можно приступать к написанию кода для регистрации конечных точек в созданном
решении .NET Service Bus. Но перед этим необходимо загрузить и установить Microsoft® .NET
Services SDK. После того, как Microsoft® .NET Services SDK установлен, вы абсолютно готовы к
использованию .NET Service Bus в своих приложениях.
Рассмотрим небольшой пример настройки простого WCF-приложения для использования .NET
Service Bus. Начнем со следующего простого контракта и реализации WCF-сервиса:
[ServiceContract]
public interface IHelloServiceBus
{
[OperationContract]
string SayHello(string name);
}
public class HelloServiceBus : IHelloServiceBus
{
public string SayHello(string name)
{
string greeting = string.Format("Hello {0}!", name);
Console.WriteLine("Returning: {0}", greeting);
return greeting;
}
}
Разместим этот сервис в следующем консольном приложении, которое
конфигурационные данные сервиса из конфигурационного файла приложения:
считывает
class Program
{
static void Main(string[] args)
{
Console.WriteLine("**** Receiver ****");
ServiceHost host = new ServiceHost(typeof(HelloServiceBus));
host.Open();
Console.WriteLine("Press [Enter] to exit");
Console.ReadLine();
host.Close();
}
}
И начнем со следующего описания конечной точки в конфигурационном файле приложения.
Обратите внимание, как конечная точка использует NetTcpBinding и локальный адрес
net.tcp://localhost:8080/helloservicebus:
<configuration>
<system.serviceModel>
<services>
<service name="HelloServiceBus">
<endpoint address="net.tcp://localhost:8080/helloservicebus"
binding="netTcpBinding"
contract="IHelloServiceBus" />
</service>
</services>
</system.serviceModel>
</configuration>
Далее можем написать клиентское приложение, вызывающее этот сервис. Следующий фрагмент
кода показывает, как сделать это, используя то же описание контракта IHelloServiceBus. Также
здесь предполагается, что данные конечной точки («DirectEndpoint») будут считываться из
конфигурационного файла приложения клиента.
class Program
{
static void Main(string[] args)
{
Console.WriteLine("**** Sender ****");
Console.WriteLine("Press <Enter> to start sending messages.");
Console.ReadLine();
ChannelFactory<IHelloServiceBus> channelFactory =
new ChannelFactory<IHelloServiceBus>("DirectEndpoint");
IHelloServiceBus channel = channelFactory.CreateChannel();
string response = channel.SayHello(".NET Service Bus");
Console.WriteLine(response);
channelFactory.Close();
}
}
Наконец, чтобы обеспечить возможность связи с сервисом через предоставляемую им конечную
точку TCP, в конфигурационном файле приложения клиента должно присутствовать
эквивалентное описание конечной точки:
<configuration>
<system.serviceModel>
<client>
<endpoint address="net.tcp://localhost:8080/helloservicebus"
binding="netTcpBinding"
contract="IHelloService"
name="DirectEndpoint" />
</client>
</system.serviceModel>
</configuration>
Если выполнить эти два приложения, в обоих окнах консоли будет выведено «Hello .NET Service
Bus!». В данном случае, между клиентским и сервисным приложениями устанавливается прямое
TCP-соединение.
Теперь рассмотрим, как сделать .NET Service Bus ретранслятором между клиентским и сервисным
приложениями. Во-первых, понадобиться реконфигурировать приложение сервиса на
прослушивание .NET Service Bus и затем клиента на отправку сообщений через .NET Service Bus.
Чтобы изменить настройку сервиса на прослушивание .NET Service Bus, можно просто заменить
привязку NetTcpBinding на привязку NetTcpRelayBinding. При этом также понадобится указать
действительный адрес встречи .NET Service Bus для конечной точки. Поскольку решению
присвоено имя «pluralsight», для конечной точки «helloservicebus» можно использовать адрес
sb://pluralsight.servicebus.windows.net/helloservicebus.
Однако я должен доказать сервису ретрансляции, что имею право слушать адресное пространство
данного решения. Сегодня для этого необходимо предоставить учетные данные своего решения
.NET Access Control Service. .NET Access Control Service, в свою очередь, выпустит маркер, которому
будет доверять .NET Service Bus. Учетные данные решения можно задать в коде или в
конфигурационном файле. Воспользуемся вторым подходом и определим имя пользователя и
пароль в элементе <transportClientEndpointBehavior>. Ниже представлена полная конфигурация
сервиса:
<configuration>
<system.serviceModel>
<services>
<service name="HelloServiceBus">
<endpoint address=
"sb://pluralsight.servicebus.windows.net/helloservicebus"
behaviorConfiguration="default"
binding="netTcpRelayBinding"
contract="IHelloServiceBus" />
</service>
</services>
<behaviors>
<endpointBehaviors>
<behavior name="default">
<transportClientEndpointBehavior credentialType="UserNamePassword">
<clientCredentials>
<userNamePassword
userName="[solution-name]" password="[solution-password]" />
</clientCredentials>
</transportClientEndpointBehavior>
</behavior>
</endpointBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
При запуске с этой конфигурацией приложение WCF-сервиса сначала отправит учетные данные
клиента на .NET Access Control Service и запросит маркер доступа для прослушивания .NET Service
Bus. Затем оно установит TCP-подключение с сервисом ретрансляции и предоставит полученный
маркер доступа. Если сервису разрешено прослушивать этот адрес (т.е. маркер содержит
необходимое утверждение), сервис ретрансляции создаст слушателя для ретрансляции
сообщений на наш локальный WCF-сервис.
Аналогичным образом меняем конфигурацию клиентского приложения. Прежде всего, для
конечной точки задаем NetTcpRelayBinding и тот же адрес встречи, на прослушивание которого
настроен наш сервис. Также необходимо задать учетные данные клиента. Как и сервис, клиенты
тоже должны подтверждать свое право на отправку сообщений на определенный адрес .NET
Service Bus, запрашивая маркер у .NET Access Control Service. Ниже представлена полная
конфигурация клиента:
<configuration>
<system.serviceModel>
<client>
<endpoint address=
"sb://pluralsight.servicebus.windows.net/helloservicebus"
binding="netTcpRelayBinding"
contract="IHelloServiceBus"
behaviorConfiguration="default"
name="RelayEndpoint" />
</client>
<behaviors>
<endpointBehaviors>
<behavior name="default">
<transportClientEndpointBehavior credentialType="UserNamePassword">
<clientCredentials>
<userNamePassword
userName="[solution-name]" password="[solution-password]" />
</clientCredentials>
</transportClientEndpointBehavior>
</behavior>
</endpointBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
После внесения всех этих изменений можно выполнить приложение сервиса и затем клиентское
приложение. Результат будет аналогичен предыдущему, но обеспечивается он ретрансляцией
связи через .NET Service Bus (рис. 9), что позволило обойти различные препятствия в сети.
Рис. 9: Пример HelloServiceBus в действии
Теперь, познакомившись с различными концепциями .NET Service Bus и тем, как начать работу с
простым решением, можно углубляться в детали. В следующих разделах будут рассмотрены
ключевые области архитектуры .NET Service Bus, их свойства и возможности.
Присваивание имен и поиск
Понимание схемы присваивания имен сервисам в .NET Service Bus чрезвычайно важно. Перед тем,
как обратиться к изучению подхода, используемого в .NET Service Bus, рассмотрим принцип
работы Domain Naming System (DNS)1.
DNS разработана для преобразования доменных имен в IP-адреса. Первое, что происходит при
переходе пользователя на веб-сайт, – поиск в DNS с целью установить, в какой IP-адрес
разрешается удобное для пользователя имя домена. Поскольку DNS использует открытые IPадреса, она не может применяться для идентификации хостов, располагающихся за устройствами
NAT, без помощи такого многоуровневого сервиса как Dynamic DNS. Сегодня обычно один IPадрес определяет всю сеть хостов, располагающихся за одним устройством NAT. Таким образом,
модель DNS далеко не идеальна для именования и идентификации конечных точек в сервисориентированном мире.
В отличие от DNS, система присваивания имен .NET Service Bus оптимизирована для именования
конечных точек сервиса без использования имен хостов. Систему имен можно рассматривать как
глобальный лес интегрированных деревьев имен, спроецированных на независимые от хостов
URI. Каждое решение проецируется в дерево имен, следовательно, имя каждого решения должно
быть глобально уникальным. Деревья имен интегрированы, потому что владелец каждого
решения управляет именами своего решения. Имена организованы в «деревья» из-за
иерархической природы пространства имен (имена в рамках имени, которое находится в рамках
другого имени). Существует естественное проецирование этих имен в URI, но результирующие URI
абсолютно не зависят от хостов: может существовать множество сервисов, выполняющихся на
разных хостах, но имеющих одно имя решения. Эти особенности системы имен .NET Service Bus
обеспечивают более детальный подход на уровне конечных точек, который прекрасно дополняет
DNS.
Система имен
Корень системы имен .NET Service Bus разрешается традиционными методиками DNS. Затем для
проведения различий между доменами управления в рамках системы имен используется
независимый от хоста критерий, в частности, имя решения. После этого вся ответственность за
управление иерархическим пространством имен соответствующих решений ложится на
владельцев решений, как показано на рис. 10.2
1
Доменная система имен (прим. переводчика).
Тот факт, что вы можете определять иерархии имен в рамках своих решений, позволяет делегировать управление
определенными поддеревьями различным группам или командам в рамках организации.
2
Root
Solution
Name
Корень
Решение
Имя
Рис. 10: Система имен .NET Service Bus
Проецирование имен .NET Service Bus в URI выполняется по следующей схеме:
[схема]://[имя-решения].servicebus.windows.net/[имя]/[имя]/...
.NET Service Bus поддерживает две схемы URI: «sb» и «http». Для всех конечных точек на базе HTTP
используется схема «http». Схема «sb» предусмотрена для всех остальных случаев, в которых
используется каналы связи на базе TCP. Часть имя-решения имени хоста определяет уникальное
дерево имен в рамках глобального пространства имен .NET Service Bus, полностью управляемое
владельцем решения.
Например, все имена в рамках решения «pluralsight» должны начинаться либо с
sb://pluralsight.servicebus.windows.net/, либо с http://pluralsight.servicebus.windows.net/, в
зависимости от используемого протокола. Все, что следует после базового URL, является частью
определяемого пользователем пространства имен. Строя иерархии имен, можно создавать
неограниченное число имен в рамках одного решения. Предположим, у нас есть офисы в Бостоне
(Boston), Солт-Лейк-Сити (Salt Lake City) и Лос-Анджелесе (Los Angeles), и каждый из них должен
опубликовать несколько конечных точек. Каждому офису можно задать уникальное имя и
предоставить контроль над определением имен в рамках этой иерархии1:
sb://pluralsight.servicebus.windows.net/boston/
sb://pluralsight.servicebus.windows.net/saltlakecity/
sb://pluralsight.servicebus.windows.net/losangeles/
Затем, предположим, каждому из офисов необходимо предоставить конечную точку для сервиса
регистрации на учебные курсы (своего для каждого города). Они могли бы сделать это, добавляя
«training» (учебный курс) в конце своих URI:
1
Если бы эти имена обозначали конечные точки HTTP, использовалась бы схема «http», а не «sb».
sb://pluralsight.servicebus.windows.net/boston/training
sb://pluralsight.servicebus.windows.net/saltlakecity/training
sb://pluralsight.servicebus.windows.net/losangeles/training
И если Бостонскому офису, который является штаб-квартирой, необходимо предоставить сервис
обработки платежей, можно просто создать другое имя конечной точки, используя «payment»
(платеж) в своем пространстве имен:
sb://pluralsight.servicebus.windows.net/boston/training/payment
Нет никакой необходимости размещать эти разные конечные точки сервисов на одном сервере, в
одной сети или даже географически в одном месте. Определение физического местоположения
конечной точки во время ответа – это работа .NET Service Bus и, в частности, сервиса
ретрансляции.
.NET Service Bus не предоставляет API для взаимодействия с системой имен напрямую, поэтому
доступ к системе имен осуществляется через функциональность реестра сервиса.
Реестр сервиса
.NET Service Bus предоставляет реестр сервиса для публикации и поиска ссылок на конечные точки
сервиса в рамках решения. Ссылки на конечные точки могут публиковаться либо как простые URI,
либо как конечные ссылки WS-Addressing. Теперь, чтобы получить конечные ссылки решения,
необходимо перейти на базовый адрес решения и извлечь канал Atom, содержащий эти
сведения.1
Реестр сервиса предоставляет конечные ссылки решения через связанное дерево каналов Atom
1.0. Переход к реестру сервиса выполняется просто путем навигации по системе имен через HTTP
с возможностью просмотра любого уровня структуры имен решения. При переходе к базовому
HTTP-адресу решения вы получите корневой канал Atom 1.0, описывающий первый уровень
вложенных имен. При переходе к одному из вложенных имен, будет получен другой канал Atom
1.0, описывающий второй уровень имен, вложенных в имя контейнера. И так по всей иерархии,
вплоть до имен конечного уровня дерева имен.
Существует два способа публикации конечных ссылок в реестре. Самый простой подход –
предоставить .NET Service Bus возможность сделать все за вас при регистрации слушателей на
сервисе ретрансляции. Если требуется сделать открыто доступной определенную конечную точку
.NET Service Endpoint, необходимо ассоциировать поведение ServiceRegistrySettings с конечной
точкой WCF, задавая ее свойству DiscoveryMode значение DiscoveryType.Public. следующий
фрагмент кода демонстрирует, как сделать это в хост-приложении WCF:
1
Это можно сделать программно, просто сформировав HTTP-запрос GET к базовому адресу решения.
class Program
{
static void Main(string[] args)
{
Console.WriteLine("**** Receiver ****");
ServiceHost host = new ServiceHost(typeof(HelloServiceBus));
host.Open();
ServiceRegistrySettings settings = new ServiceRegistrySettings();
settings.DiscoveryMode = DiscoveryType.Public;
foreach(ServiceEndpoint se in host.Description.Endpoints)
se.Behaviors.Add(settings);
Console.WriteLine("Press [Enter] to exit");
Console.ReadLine();
host.Close();
}
}
Когда определено такое поведение, сервис ретрансляции автоматически заполняет реестр
сервиса данными о необходимых конечных точках. Например, если повторно выполнить
приложение сервиса HelloServiceBus, показанного ранее, и затем перейти к базовому HTTP-адресу
этого решения, мы увидим сформированное в Internet Explorer представление канала Atom 1.0 с
единственной конечной ссылкой (рис. 11).
Если такое поведение конечной точки не определено, конечные точки .NET Service Bus не будут
видимыми через канал Atom по умолчанию (DiscoveryType.Private является настройкой по
умолчанию).1
Рис. 9: Переход к реестру сервиса решения
1
Фактически, поведение по умолчанию изменилось в CTP-версии, вышедшей в марте 2009 года. До этой версии все
конечные точки .NET Service Bus были видимыми по умолчанию. Однако, теперь все конечные точки .NET Service Bus по
умолчанию закрытые. Чтобы сделать их видимыми, необходимо явно задать для них DiscoveryType.Public.
Рассмотрим более интересный пример. Предположим, мы изменили настройку показанного
ранее приложения сервиса HelloServiceBus следующей конфигурацией конечных точек:
<configuration>
<system.serviceModel>
<services>
<service name="HelloServiceBus">
<endpoint address=
"sb://pluralsight.servicebus.windows.net/boston/training"
behaviorConfiguration="default"
binding="netTcpRelayBinding"
contract="IHelloServiceBus" />
<endpoint address=
"sb://pluralsight.servicebus.windows.net/boston/payment"
behaviorConfiguration="default"
binding="netTcpRelayBinding"
contract="IHelloServiceBus" />
<endpoint address=
"sb://pluralsight.servicebus.windows.net/saltlakecity/training"
behaviorConfiguration="default"
binding="netTcpRelayBinding"
contract="IHelloServiceBus" />
<endpoint address=
"sb://pluralsight.servicebus.windows.net/losangeles/training"
behaviorConfiguration="default"
binding="netTcpRelayBinding"
contract="IHelloServiceBus" />
</service>
</services>
...
</system.serviceModel>
</configuration>
Теперь, если выполнить приложение и перейти к базовому HTTP-адресу решения, можно будет
увидеть корневой канал Atom 1.0, такой как представлен на рис. 12. Обратите внимание, что он
включает только первый уровень имен описанных нами конечных точек, т.е. «boston»,
«losangeles» и «saltlakecity».
Рис. 10: Корневой канал Atom 1.0
Теперь, если щелкнуть «boston», будет сформирован запрос на получение другого канала Atom
1.0, описывающего имена уровня иерархии «boston». На рис. 13 показано, как выглядит
вложенный канал для «boston». Если бы мы перешли к каналам «losangeles» или «saltlakecity», мы
бы увидели в них только «training».
Другой способ публикации конечных ссылок в реестр сервиса – программное взаимодействие с
реестром сервиса через Atom Publishing Protocol (APP) 1 или WS-Transfer. Можно просто
формировать HTTP-запросы PUT с записью Atom 1.0 к любому имени дерева имен решения, и это
обеспечит добавление конечных ссылок. Удаление конечных ссылок реализуется путем
формирования HTTP-запроса DELETE к имени, которое требуется удалить. При использовании
этого подхода имена в системе имен создаются и удаляются автоматически при создании или
удалении записей реестра сервиса.2
1
Протокол публикации Atom (прим. переводчика).
Для такого взаимодействия с реестром сервиса понадобится маркер доступа (полученный от .NET Access Control
Service). Microsoft еще не предоставил полной документации по использованию APP или WS-Transfer для
взаимодействия с реестром сервиса. Ее публикация ожидается в одной из следующих версий.
2
Рис. 11: Вложенный канал Atom 1.0
Обмен сообщениями
В сердце .NET Service Bus находится масштабируемый сервис ретрансляции общего назначения
(рис. 4), обеспечивающий множество различных расширенных возможностей обмена
сообщениями для гибкой связи через Интернет.
Сервис ретрансляции
Сервис ретрансляции упрощает построение решений с возможностью обмена информацией через
межсетевые экраны и NAT-устройства, используя множество различных шаблонов обмена
сообщениями. Сервис ретрансляции поддерживает традиционный однонаправленный обмен
сообщениями, синхронный обмен сообщениями и обмен сообщениями между равноправными
участниками сети. Он также поддерживает распространение событий в Интернет для реализации
сценариев публикации/подписки и двунаправленную связь через сокеты для повышения
эффективности передачи информации из точки в точку. И также в CTP-версии, вышедшей в 2009
году, сервис ретрансляции поддерживает буферизованную (асинхронную) связь для обеспечения
сценариев работы в сети и в автономном режиме, а также «гибкие» передачи, при которых
скорость или полоса пропускания отправителей и получателей может не совпадать.
При использовании сервиса ретрансляции вы, по сути, делегируете задачу по «прослушиванию»
транспортного уровня сервису ретрансляции в облаке. В этом случае вашим сервисам больше нет
необходимости создавать локальных слушателей транспортного уровня; они полностью
полагаются на сервис ретрансляции в вопросах обработки указанных транспортных аспектов
связи. Сервис ретрансляции просто пересылает входящие сообщения на ваш локальный сервис.
Отношение между вашими сервисами и сервисом ретрансляции аналогично отношению между
приложениями Windows, построенными на HTTP.SYS. Приложения, использующие HTTP.SYS сами
не создают слушателей транспорта HTTP: они просто регистрируют адрес с помощью драйвера
HTTP.SYS и просят его пересылать все сообщения, поступающие на зарегистрированный адрес. Это
обеспечивает централизацию транспортной логики HTTP и сокращает контактную зону, что
хорошо с точки зрения безопасности. Сервис ретрансляции выполняет аналогичную HTTP.SYS
функцию, но располагается в облаке, и чтобы он передавал сообщения, поступающие на
определенный адрес, ваши локальные сервисы регистрируются в нем.
Подключение между локальным сервисом и сервисом ретрансляции должно быть
инициировано.1 При использовании .NET это выполняется с помощью модели программирования
WCF и нового комплекта WCF-привязок «ретрансляции», который поставляется с .NET Services SDK.
Привязки ретрансляции в фоновом режиме проецируются на новые элементы привязки
транспорта, спроектированные для создания слушателей WCF, которые интегрируются с сервисом
ретрансляции. В большинстве режимов подключения для взаимодействия с сервисом
ретрансляции, поддерживающим двустороннюю связь, слушатель WCF создает безопасное
исходящее подключение через сокет. В ходе этого процесса он проходит аутентификацию, задает
имя, которое будет прослушиваться, и сообщает, какой тип слушателя должен быть установлен.
WCF-привязки ретрансляции обеспечивают различные варианты обмена сообщениями, которые
упрощают обход многих серьезных препятствий подключения к Интернету даже в самых
защищенных средах. Эти варианты подробно обсуждаются в следующих разделах.
Слушатели и присваивание имен
При выборе имен для слушателей необходимо следовать рекомендациям, данным в разделе
«Присваивание имен». Несмотря на то, что слушатели могут быть организованы по любому
критерию, подходящему для вашего решения, важно понимать, что определенное пространство
URI может слушать только один слушатель, кроме случаев использования привязок
NetEventRelayBinding, которые специально разработаны для определения множества слушателей
для одного URI.
Во всех других случаях попытка открытия второго слушателя для URI, который уже используется
другим слушателем, будет неудачной. Более того, не увенчается успехом попытка открытия
слушателя для URI, находящегося в области действия первого URI. Например, если первый
слушатель использует /foo/bar, попытка открыть /foo/bar/baz вторым слушателем даст сбой.
Множество слушателей могут использовать URI с общим базовым адресом, как в случае с /foo/bar
и /foo/baz, но если один URI является полным префиксом другого URI, возникнет ошибка.
Сервис ретрансляции выполняет маршрутизацию сообщений к слушателям, используя алгоритм
максимального совпадения префиксов (точное совпадение не обязательно), благодаря чему
1
Важно отметить, что CTP-версия не поддерживает сценарии активации IIS/WAS для размещения локальных сервисов.
целевой сервис может также напрямую инспектировать сегменты пути URI и строку запроса для
выполнения специальной обработки, что оказывается очень полезным для RESTful-сценариев.
Порты, необходимые сервису ретрансляции
Сервис ретрансляции требует открытия всего нескольких выходных портов, в частности, портов
808, 818, 819 и 828.1 Порт 808 используется для исходящих TCP-соединений, и порт 828 – для
исходящих TCP/SSL-соединений. Также порты 818 и 819 служат определенным расширенным
режимам подключения на базе TCP, которые будут обсуждаться позже. Важно отметить, что для
работы с сервисом ретрансляции нет необходимости в открытии каких-либо входных портов в
межсетевом экране или в сопоставлении портов с устройством NAT/маршрутизатор.
При работе в жестко управляемой сетевой среде, блокирующей все исходящие подключения
через сокеты, кроме используемых HTTP/HTTPS, можно применять специальный вариант связи на
базе HTTP, когда слушатель WCF фактически опрашивает сервис ретрансляции через HTTPсоединение. Такой подход обычно работает даже в наиболее защищенных сетевых средах.
С точки зрения безопасности, сервис ретрансляции выполняет функцию демилитаризованной
зоны (demilitarized zone, DMZ), полностью изолированной от локальной среды сервиса. DMZ
обеспечивает внешнюю обработку всего сетевого трафика, что позволяет отфильтровывать
нежелательный трафик в облаке до того, как он поступает в окружение сервиса. Более того,
сервис ретрансляции скрывает все сведения о местоположении локального слушателя в сети (в
сущности, делая его анонимным), сокращая, таким образом, потенциальную поверхность атаки
(по типу HTTP.SYS). Сервис ретрансляции интегрирован с .NET Access Control Service, что
обеспечивает возможности аутентификации и авторизации, предоставляя гибкие и легко
управляемые механизмы безопасности в облаке.
Могут возникнуть опасения, что сервис ретрансляции «пробивает брешь» в межсетевом экране. В
этом случае важно обратить внимание на средства защиты, предоставляемые им. Основное
назначение межсетевого экрана – блокирование доступа к сетевым ресурсам на уровне портов. С
этой точки зрения, сервис ретрансляции (в сочетании с функциями безопасности .NET Access
Control Service) аналогичен межсетевому экрану, только сервис ретрансляции разработан для
блокирования нежелательного доступа к ресурсам сервиса.
WCF-привязки ретрансляции
Основной моделью программирования для работы с .NET Service Bus на платформе .NET является
WCF. .NET Services SDK поставляется с набором новых привязок WCF, которые автоматизируют
интеграцию между вашими сервисами и клиентами WCF и сервисом ретрансляции. В
1
Microsoft подал заявку на широко известный номер порта .NET Service Bus в Комитет по цифровым адресам в
Интернете (Internet Assigned Numbers Authority, IANA), организацию, занимающуюся глобальной координацией
распределения IP-адресов и Интернет-протоколами. Как только IANA официально предоставит номера портов,
реализация .NET Service Bus будет обновлена соответствующим образом.
большинстве случаев потребуется лишь заменить используемую WCF-привязку одной из привязок
.NET Service Bus.
На рис. 14 представлен список всех WCF-привязок .NET Service Bus и соответствующих им
стандартных WCF-привязок. Для всех наиболее часто используемых WCF-привязок, таких как
BasicHttpBinding, WebHttpBinding, WSHttpBinding и NetTcpBinding, есть соответствующие привязки
.NET Service Bus с очень похожим именем (просто перед «Binding» добавляется «Relay»). Лишь
несколько привязок ретрансляции, NetOneWayRelayBinding и NetEventRelayBinding, не имеют
соответствующих привязок в .NET Framework.
Стандартная WCF-привязка
Эквивалентная
привязка
ретрансляции
BasicHttpBinding
BasicHttpRelayBinding
WebHttpBinding
WebHttpRelayBinding
WSHttpBinding
WSHttpRelayBinding
WS2007HttpBinding
WS2007HttpRelayBinding
WSHttpContextBinding
WSHttpRelayContextBinding
WS2007HttpFederationBinding WS2007HttpRelayFederationBinding
NetTcpBinding
NetTcpRelayBinding
NetTcpContextBinding
NetTcpRelayContextBinding
N/A
NetOnewayRelayBinding
N/A
NetEventRelayBinding
Рис. 12: WCF-привязки ретрансляции
По большей части, привязки ретрансляции аналогичны стандартным WCF-привязкам. Например,
они поддерживают различные версии WCF-сообщений (SOAP 1.1, SOAP 1.2 и None), различные
сценарии безопасности WS-*, надежный обмен сообщениями, потоковую передачу, обмен
метаданными, модель программирования для Веб (например, [WebGet] и [WebInvoke]) и многие
другие стандартные возможности WCF.
Тем, кто знаком с подноготной работы WCF, может быть интересно знать, как новые привязки
(представленные на рис. 14) проецируются на элементы привязки транспорта. На рис. 15 показаны
элементы привязки транспорта для каждой новой привязки ретрансляции. Все они соответствуют
четырем новым элементам привязки транспорта WCF: HttpRelayTransportBindingElement,
HttpsRelayTransportBindingElement,
TcpRelayTransportBindingElement
и
OnewayRelayTransportBindingElement.
Привязка ретрансляции
BasicHttpRelayBinding
WebHttpRelayBinding
WSHttpRelayBinding
WS2007HttpRelayBinding
WSHttpRelayContextBinding
WS2007HttpRelayFederationBinding
NetTcpRelayBinding
Элемент привязки транспорта
Http(s)RelayTransportBindingElement
Http(s)RelayTransportBindingElement
Http(s)RelayTransportBindingElement
Http(s)RelayTransportBindingElement
Http(s)RelayTransportBindingElement
Http(s)RelayTransportBindingElement
TcpRelayTransportBindingElement
NetTcpRelayContextBinding
TcpRelayTransportBindingElement
NetOnewayRelayBinding
OnewayRelayTransportBindingElement
NetEventRelayBinding
OnewayRelayTransportBindingElement
Рис. 13: Элементы привязки ретрансляции WCF
Эти новые примитивы WCF обеспечивают низкоуровневую интеграцию каналов с сервисом
ретрансляции. Если сравнить элементы привязки, используемые WSHttpBinding и
WSHttpRelayBinding, можно заметить, что данные наборы практически идентичны. Единственное
существенное различие между ними – элемент привязки транспорта, что иллюстрирует рис. 16.
WSHttpBinding использует стандартный HttpTransportBindingElement. На стороне клиента элемент
привязки сопоставляется с каналом клиента, использующим System.Net.WebRequest для связи по
протоколу HTTP. На стороне сервера он сопоставляется со слушателем, созданным на базе
System.Net.HttpListener для интеграции с HTTP.SYS.
Same binding elements
Аналогичные элементы привязки
Different Transport
Другой транспорт
Client Channel:
Канал клиента:
Listener:
Слушатель:
Рис. 14: Сравнение наборов привязок
С другой стороны, WSHttpRelayBinding сопоставляется с HttpRelayTransportBindingElement,
который, как это ни странно, использует тот же тип канала клиента. Таким образом, способ связи
клиентов WCF с сервисом ретрансляции тот же, но на стороне сервера используется другой
слушатель. Новый слушатель WCF «знает», как интегрироваться с сервисом ретрансляции и
обрабатывать «ретранслированные» сообщения. Обратите внимание, что все элементы привязки
над элементом привязки транспорта абсолютно аналогичны в обоих случаях. Это иллюстрирует то,
что сервис ретрансляции может замечательно сочетаться с различными протоколами WS-*.
Подобная иллюстрация для остальных привязок WCF будет выглядеть аналогично с той точки
зрения, что основное отличие будет в компонентах слушателя транспорта. В следующих разделах
более подробно рассматриваются основные WCF-привязки ретрансляции и продемонстрирована
работа с ними.
NetOnewayRelayBinding
NetOnewayRelayBinding является наиболее ограниченной из всех привязок ретрансляции, потому
что поддерживает только однонаправленный обмен сообщениями. Однако она лучше всего
обеспечивает слушателям входящий канал связи в сетевых средах с ограничениями, поскольку
поддерживает и TCP, и HTTP-соединения с сервисом ретрансляции, выступающим в роли
получателя.
По умолчанию NetOnewayRelayBinding использует SOAP 1.2 через TCP и двоичное кодирование
сообщений, хотя эти параметры связи могут быть настроены стандартными методами
конфигурации привязок.1 Сервисы, использующие эту привязку, должны всегда применять схему
протокола «sb».
Если WCF-сервис использует эту привязку, WCF-слушатель пытается установить исходящее
соединение с сервисом ретрансляции для создания двунаправленного сокета. В этом случае он
всегда создает безопасное TCP/SSL-соединение через исходящий порт 828. В процессе
подключения слушатель проходит аутентификацию (предоставляя маркер доступа, полученный от
.NET Access Control Service), задает имя, которое будет прослушивать на сервисе ретрансляции, и
сообщает сервису ретрансляции тип слушателя, который должен быть создан.
Если WCF-клиент использует эту привязку, он применяет компоненты канала NetTcpRelayBinding и
устанавливает с сервисом ретрансляции TCP-соединение через порт 808 (TCP) или 828 (TCP/SSL) в
зависимости от параметров привязки. В процессе подключения он должен пройти
аутентификацию на сервисе ретрансляции (опять же, предоставляя маркер доступа, полученный
от .NET Access Control Service). Как только клиент установил TCP-соединение, он может отправлять
на сервис ретрансляции односторонние сообщения для «ретрансляции» целевому сервису через
установленное получателем TCP-соединение (рис. 17).
Рис. 17 иллюстрирует некоторые заслуживающие внимание аспекты архитектуры .NET Service Bus.
Весь массив интерфейсных узлов отправителей и получателей, установивших соединения с
сервисом ретрансляции, сбалансирован по нагрузке, что в итоге обеспечивает необходимую
масштабируемость этого типа сервиса. При передаче сообщения интерфейсный узел отправителя
обменивается данными с серверной средой именования и маршрутизации, чтобы обеспечить
успешную ретрансляцию сообщения на другой интерфейсный узел, прикрепленный к получателю.
В конечном счете, такой подход обеспечивает масштабируемый канал связи между
отправителями и получателями.
1
В настоящее время NetOnewayRelayBinding поддерживает сообщения размером до 60 KB.
Если в качестве значения свойства привязки, определяющего режим безопасности, задано
значение Transport или TransportWithMessageCredential, канал будет требовать SSL-защиты. В этом
случае весь трафик, передаваемый с и на сервис ретрансляции, будет защищен с помощью SSL,
однако, сообщение будет проходить через сервис ретрансляции в незашифрованном виде.1 Для
обеспечения полной конфиденциальности придется использовать режим безопасности
«Message». В этом случае может кодироваться все передаваемое через сервис ретрансляции
сообщение, кроме данных идентификации получателя.
Backend Naming Routing Fabric
Серверная среда именования и маршрутизации
Frontend Nodes
Интерфейсные узлы
Route
Канал
Subscribe
Подписка
Service Bus
Сервисная шина
Msg
Сообщение
Sender
Отправитель
outbound connect one-way net.tcp
Исходящее соединение
outbound connect bidi socket
Receiver
Получатель
NAT
NAT
Firewall
Межсетевой экран
Dynamic IP
Динамический IP
Рис. 15: NetOnewayRelayBinding
NetOnewayRelayBinding требует, чтобы все операции сервисного контракта были обозначены как
однонаправленные операции (IsOneWay=true). В этом случае использование WCF-привязки
заключается не более чем в задании описаний конечной точки и предоставлении необходимых
учетных данных.
1
Несмотря на то, что сообщения являются видимыми, Microsoft заявляет, что сервис ретрансляции не просматривает
проходящие через него сообщения.
.NET Services SDK поставляется с простым примером, иллюстрирующим работу
NetOnewayRelayBinding. В нем описывается следующий однонаправленный сервисный контракт:
[ServiceContract(Name = "IOnewayContract",
Namespace = "http://samples.microsoft.com/ServiceModel/Relay/")]
public interface IOnewayContract
{
[OperationContract(IsOneWay = true)]
void Send(int count);
}
Реализация сервиса просто обеспечивает вывод предоставляемого счетчика в окно консоли.
Приложение сервиса с помощью NetOnewayRelayingBinding задает для сервиса единственную
конечную точку:1
<configuration>
<system.serviceModel>
<services>
<service name="Microsoft.ServiceBus.Samples.OnewayService">
<endpoint address=
"sb://pluralsight.servicebus.windows.net/oneway"
behaviorConfiguration="credentials"
binding="netOnewayRelayBinding"
contract="Microsoft.ServiceBus.Samples.IOnewayContract" />
</service>
</services>
...
</system.serviceModel>
</configuration>
В клиентском приложении задана эквивалентная конфигурация конечной точки (также на базе
NetOnewayRelayBinding), и оно передает на сервис ретрансляции через эту конечную точку 25
сообщений. При запуске решения приложение и клиента, и сервиса запросит ввести имя решения
и учетные данные. На рис. 18 представлена консоль приложения сервиса после выполнения
примера. Все 25 сообщений, отправленные клиентом, успешно прошли сервис ретрансляции и
поступили на локальный WCF-сервис.
1
Обратите внимание, что здесь для примера я использовал адрес одного из моих решений. SDK приглашает ввести имя
решения и динамически формирует адрес во время выполнения.
Рис. 16: Выполнение примера NetOnewayRelayBinding
При использовании NetOnewayRelayBinding получатель по умолчанию подключается к сервису
ретрансляции через TCP. При работе в защищенной сетевой среде, не допускающей установления
исходящих TCP-соединений вне HTTP, можно настроить NetOnewayRelayBinding на использование
более агрессивного режима подключения, который для извлечения ретранслированных
сообщений заставляет получателя устанавливать с сервисом ретрансляции HTTP-соединение
(вместо прямого TCP-соединения). Перечисление ConnectivityMode (Режим подключения)
определяет три доступных режима подключения. Как видите, TCP является режимом по
умолчанию.
ConnectivityMode
Tcp (по умолчанию)
Http
AutoDetect
Описание
Слушатели устанавливают с сервисом ретрансляции TCP-соединения через порт 828
(SSL).
Слушатели устанавливают HTTP-соединение с сервисом ретрансляции и опрашивают
для получения сообщений (что упрощает обход ограничений по применяемым TCPпортам).
При такой настройке выбор режимов Tcp или Http производится автоматически
путем определения доступного для текущей сетевой среды механизма
автоматического выбора; Tcp является предпочтительным режимом.
Рис. 17: Опции ConnectivityMode для одностороннего подключения
В режиме AutoDetect WCF автоматически определяет протокол, используемый для подключения
получателя, TCP или HTTP. Если в данной сети возможно применение TCP, используется этот
режим, поскольку он является предпочтительным. В противном случае, выполняется
автоматическое переключение в режим HTTP для обеспечения возможности связи через
межсетевой экран.
Режим одностороннего связи задается на уровне AppDomain (Домен приложений) через
статический класс ServiceBusEnvironment (Среда сервисной шины). 1 Этот класс предоставляет
свойство OnewayConnectivity (Одностороннее подключение), для которого может быть задано
одно из трех значений ConnectivityMode, описанных на рис. 19. Все односторонние подключения
(даже созданные конечными точками NetEventRelayBinding) используют этот параметр. Это
вполне логично, поскольку все однонаправленные подключения в рамках одного AppDomain
располагаются в одной сети и сталкиваются с одними и теми же препятствиями.
Следующий фрагмент кода иллюстрирует настройку простого приложения сервиса на
использование режима подключения HTTP с помощью статического класса ServiceBusEnvironment:
1
ServiceBusEnvironment – это статический класс, обеспечивающий доступ к общим параметрам среды. Он предоставляет
сведения о текущих именах хостов для конечных точек .NET Service Bus и .NET Access Control и глобальные настройки
подключения для всех активных в данном домене приложений конечных точек на базе NetOnewayRelayBinding и
NetEventRelayBinding.
...
ServiceBusEnvironment.SystemConnectivity.Mode = ConnectivityMode.Http;
ServiceHost host = new ServiceHost(typeof(OnewayService), address);
host.Open();
...
При повторном выполнении примера из SDK с применением данного фрагмента кода будут
получены те же результаты, что и ранее, но, вероятно, вы заметите небольшую задержку доставки
сообщений, обусловленную работой механизма опроса HTTP.
Этот подход годится только для однонаправленного обмена сообщениями. Чтобы использовать
такой агрессивный подход для двусторонней связи, можно создать специальную привязку WCF,
объединяющую два соединения NetOnewayRelayBinding в составной дуплексный канал,
использующий этот HTTP-режим в обоих направлениях.1
NetEventRelayBinding
NetEventRelayBinding очень близка NetOnewayRelayBinding с точки зрения реализации.
Стандартные настройки и опции безопасности этих привязок аналогичны. Кроме того, принципы
взаимодействия слушателей/клиентов с сервисом ретрансляции, по сути, такие же, как и для
NetOnewayRelayBinding (подробное описание можно найти в предыдущем разделе). К тому же,
класс NetEventRelayBinding наследуется от класса NetOnewayRelayBinding.
Основное отличие привязки NetEventRelayBinding в том, что она позволяет создавать множество
слушателей для одного адреса .NET Service Bus (рис. 20). Когда клиент отправляет сообщение на
такой адрес, .NET Service Bus рассылает его всем слушателям, в настоящее время подписанным на
данный адрес.
1
Это более специальная тема, выходящая за рамки рассмотрения данного документа. Больше информации по этому
сценарию и, возможно, пример можно будет найти в будущей версии .NET Services SDK.
Backend Naming Routing Fabric
Серверная среда именования и маршрутизации
Frontend Nodes
Интерфейсные узлы
Route
Канал
Subscribe
Подписка
Service Bus
Сервисная шина
Msg
Сообщение
Sender
Отправитель
outbound connect one-way net.tcp
исходящее однонаправленное соединение
outbound connect bidi socket
Receiver
Получатель
Рис. 18: NetEventRelayBinding
Данная привязка обеспечивает базу для реализации архитектур публикации/подписки, но не
предоставляет никаких гарантий доставки сообщений или порядка доставки. Это делает ее схожей
с многоадресной рассылкой UDP, но она не так подвержена ошибкам, поскольку сервис
ретрансляции использует для связи протокол TCP.
NetEventRelayBinding поддерживает те же опции ServiceBusEnvironment.SystemConnectivity, что и
NetOnewayRelayBinding. Значение свойства SystemConnectivity класса ServiceEnvironment
распространяется на все конечные точки, использующие любой из типов однонаправленных
привязок. Следовательно, для всех слушателей NetEventRelayBinding, размещающихся в
защищенной сетевой среде, которая блокирует исходящие TCP-соединения, может
использоваться агрессивный режим подключения HTTP.
В .NET Services SDK предлагается еще один пример, иллюстрирующий применение
NetEventRelayBinding для создания простого приложения чата. Он включает проект простого
консольного приложения, которое выступает в роли и отправителя, и получателя. Все экземпляры
чата регистрируют нового слушателя на сервисе ретрансляции по одному адресу. После этого в
приложении можно вводить сообщения чата, и оно будет отправлять их на один адрес сервиса
ретрансляции, а сервис ретрансляции будет рассылать это сообщение всем выполняющимся
приложениям чата, подписанным на этот адрес. Следующий фрагмент кода иллюстрирует
конфигурацию WCF для консольного приложения чата:1
<configuration>
<system.serviceModel>
<client>
<endpoint name="RelayEndpoint"
contract="Microsoft.ServiceBus.Samples.IMulticastContract"
binding="netEventRelayBinding"
bindingConfiguration="default"
address="sb://pluralsight.servicebus.windows.net/chat/" />
</client>
<services>
<service name="Microsoft.ServiceBus.Samples.MulticastService">
<endpoint name="RelayEndpoint"
contract="Microsoft.ServiceBus.Samples.IMulticastContract"
binding="netEventRelayBinding"
bindingConfiguration="default"
address="sb://pluralsight.servicebus.windows.net/chat/" />
</service>
</services>
</system.serviceModel>
</configuration>
Если запустить три экземпляра приложения чата и ввести несколько сообщений в одном из них,
эти сообщения появятся в окнах других чатов, как показано на рис. 21.
1
Обратите внимание, что здесь для примера я использовал адрес одного из моих решений. SDK приглашает ввести имя
«сеанса чата» и динамически формирует адрес распределения событий во время выполнения.
Рис. 19: Пример чата на базе NetEventRelayBinding
Обе привязки, NetOnewayRelayBinding и NetEventRelayBinding, обеспечивают гибкий
одноадресный и многоадресный однонаправленный обмен сообщениями. Они не являются
прямым аналогом ни одной стандартной WCF-привязки, но близки NetMsmqBinding и
NetPeerTcpBinding с точки зрения семантики обмена сообщениями.
NetTcpRelayBinding
Привязку NetTcpRelayBinding можно было видеть в первом примере HelloServiceBus в начале
данной главы. Это еще одна привязка, рекомендуемая Microsoft к использованию по умолчанию
при отсутствии веских причин для применения других привязок. Основанием этому является то,
что NetTcpRelayBinding очень близка стандартной WCF-привязке NetTcpBinding и оптимизирована
для обеспечения максимальной производительности и пропускной способности. Основное
отличие между ними в том, что NetTcpRelayBinding создает на сервисе ретрансляции открытую
для всеобщего доступа конечную точку TCP.
По умолчанию NetTcpRelayBinding поддерживает SOAP 1.2 через TCP и использует двоичную
сериализацию для обеспечения эффективности. Хотя ее настройка очень близка NetTcpBinding,
эти привязки используют разные базовые сокеты TCP и, следовательно, не являются напрямую
совместимыми друг с другом. Это означает, что для обеспечения возможности интеграции
клиентские приложения также должны будут использовать NetTcpRelayBinding.
Рассмотрим, что происходит, при использовании этой привязки с режимом подключения по
умолчанию «relayed» (рис. 22). Прежде всего, получатель устанавливает безопасное исходящее
TCP-соединение с сервисом ретрансляции. В ходе этого процесса он должен пройти
аутентификацию, указать прослушиваемый адрес и тип слушателя, который должен быть создан
на ретрансляторе. До этого момента все очень похоже на работу с привязкой
NetOnewayRelayBinding.
Когда отправитель устанавливает подключение с сервисом ретрансляции и проходит
аутентификацию по конкретному адресу, сервис ретрансляции создает компонент пересылки от
сокета к сокету. После этого данный компонент через среду маршрутизации серверной части
передает получателю управляющее сообщение, указывая ему установить исходящее соединение
с собой. Как только подключение установлено, сервер ретрансляции получает эффективный
компонент пересылки для ретрансляции двунаправленного байтового потока. Именно это
происходит «за кулисами» в представленном ранее примере HelloServiceBus.
Backend Naming Routing Fabric
Frontend Nodes
Oneway Rendezvous Ctrl Msg
Серверная среда именования и маршрутизации
Интерфейсные узлы
Одностороннее управляющее сообщение для
установления подключения
Service Bus
Сервисная шина
Msg
Сообщение
Sender
Отправитель
outbound socket connect
исходящее подключение сокета
outbound socket rendezvous
встреча с исходящим сокетом
Receiver
Получатель
Socket-to-Socket Forwarder
Компонент пересылки от сокета к сокету
Рис. 20: NetTcpRelayBinding – режим ретрансляции (Relayed)
NetTcpRelayBinding поддерживает три различных режима подключения, которые определяют
порядок взаимодействия отправителя и получателя через сервис ретрансляции (рис. 23).
TcpConnectionMode
Relayed
(по
умолчанию)
Hybrid
Описание
Вся связь ретранслируется через сервис ретрансляции. Защищенное SSL управляющее
подключение используется для согласования ретранслируемого сквозного
подключения через сокет, по которому проходит весь обмен данными. Как только
соединение установлено, сервис ретрансляции выступает в роли прокси-сервера
пересылки между сокетами, ретранслирующего двунаправленный байтовый поток.
Пока отправитель и получатель согласовывают установление прямого подключения
друг с другом, ретрансляция данных выполняется через сервис ретрансляции.
Координирует прямое подключение сервис ретрансляции. Алгоритм прямого
подключения через сокет обеспечивает возможность установления прямых
соединений между двумя сторонами, располагающимися за разными межсетевыми
экранами и NAT-устройствами. Для обхода межсетевых экранов данный алгоритм
использует только исходящие подключения и обход NAT реализуется с помощью
алгоритма взаимного прогнозирования портов. Как только появляется возможность
установления прямого подключения, подключение с ретрансляцией автоматически
переводится в прямое подключение без потери сообщений или данных. Если прямое
Direct
подключение не может быть установлено, данные будут передаваться через сервис
ретрансляции, как обычно.
Этот режим использует только прямое подключение, если таковое может быть
установлено, и никогда не передает какие-либо данные приложения через сервис
ретрансляции.
Рис. 21: Возможные значения TcpConnectionMode
Только что описанный режим Relayed (Ретрансляция) является режимом по умолчанию. Также
поддерживается любопытный режим Hybrid (Гибрид), при котором сервис ретрансляции делает
попытки установления прямого подключения между отправителем и получателем, чтобы
обеспечить прямую передачу данных, без ретрансляции. Этот режим считается «гибридным»,
потому что при нем вначале данные ретранслируются, но в этом время выполняются попытки
установления прямого подключения. Если эти попытки заканчиваются успешно, выполняется
переход к прямому соединению без какой-либо потери данных (рис. 24). Если прямое
подключение не может быть установлено по каким-либо причинам, продолжается использования
сервиса ретрансляции.
Backend Naming Routing Fabric
Frontend Nodes
Oneway Rendezvous Ctrl Msg
Серверная среда именования и маршрутизации
Интерфейсные узлы
Одностороннее управляющее сообщение для
установления подключения
Service Bus
Сервисная шина
NAT Probing
Тестирование NAT
relayed connect
ретранслируемое подключение
Sender
Отправитель
relayed rendezvous
ретранслируемое подключение
Receiver
Получатель
NAT Traversal Connection
Подключение в обход NAT
upgrade
Переход
Рис. 22: NetTcpRelayBinding – гибридный режим (Hybrid)
Сервис ретрансляции реализует это с помощью специального алгоритма взаимного
прогнозирования портов на основании сведений, полученных от отправителя и получателя.
Сервис ретрансляции анализирует полученные в результате тестирования данные и пытается
спрогнозировать, какие порты открыты в соответствующих NAT-устройствах. После этого данная
информация предоставляется отправителю/получателю, которую они используют для
установления прямого подключения друг с другом. Если прогнозы сервиса ретрансляции верны,
подключение успешно устанавливается, в противном случае, попытка спрогнозировать открытые
порты выполняется вновь до тех пор, пока не будет принято окончательное решение об
использовании ретрансляции.
Такой подход используется многими современными приложения обмена мгновенными
сообщениями при передаче файлов между пользователями. Когда в следующий раз
воспользуетесь этой возможностью, обратите внимание на исходную скорость передачи файла и
на то, произойдет ли ее заметное увеличение в ходе процесса. Такой скачок свидетельствует о
переходе от ретрансляции к прямому подключению.
С .NET Services SDK поставляется пример, иллюстрирующий это. Для сервиса задана единственная
конечная точка NetTcpRelayBinding, которая настроена на использование режима подключения
Hybrid:1
<configuration>
<system.serviceModel>
<bindings>
<netTcpRelayBinding>
<binding name="default" connectionMode="Hybrid">
<security mode="None" />
</binding>
</netTcpRelayBinding>
</bindings>
<services>
<service name="Microsoft.ServiceBus.Samples.HelloService">
<endpoint address=
"sb://pluralsight.servicebus.windows.net/direct"
contract="Microsoft.ServiceBus.Samples.IHelloContract"
binding="netTcpRelayBinding"
bindingConfiguration="default" />
</service>
</services>
...
</system.serviceModel>
</configuration>
Соответствующее клиентское приложение также конфигурируется эквивалентным описанием
конечной точки (с использованием все того же режима подключения Hybrid). В данном примере
1
Обратите внимание, что здесь для примера я использовал адрес одного из моих решений. Пример SDK приглашает
ввести имя решения и динамически формирует адрес во время выполнения.
реализация сервиса, фактически, ничего не делает: здесь выполняется подсчет количества
сообщений, которые клиент может отправлять в «пустую» операцию сервиса каждые 250
миллисекунд. Это число выводится в окне консоли клиента (рис. 25).
Обратите внимание на существенное увеличение количества отправляемых клиентом сообщений
через несколько секунд после запуска программы. Это происходит как раз в момент перехода от
ретрансляции к прямому подключению.
Рис. 23: Выполнение примера с использованием привязки NetTcpRelaying в режиме «Hybrid»
Также можно зарегистрировать обработчик событий изменения статуса подключения во время
выполнения. При использовании этой привязки у канала на стороне клиента имеется свойство
типа IHybridConnectionStatus, которое предоставляет событие ConnectionStateChanged (Состояние
подключение изменилось). Рассмотрим пример настройки пользовательского обработчика
событий клиентского подключения:
...
ChannelFactory<IHelloChannel> channelFactory = new
ChannelFactory<IHelloChannel>("RelayEndpoint", new EndpointAddress(serviceUri));
channelFactory.Endpoint.Behaviors.Add(relayCredentials);
IHelloChannel channel = channelFactory.CreateChannel();
channel.Open();
IHybridConnectionStatus hybridConnectionStatus =
channel.GetProperty<IHybridConnectionStatus>();
hybridConnectionStatus.ConnectionStateChanged += ( o,e ) =>
{
Console.WriteLine("Upgraded!");
};
// используем канал здесь...
Если повторно запустить пример с этим обработчиком, в окне консоли в момент изменения
состояния соединения появится уведомление «Upgraded!» (рис. 26).
Рис. 24: Использование события IHybridConnectionStatus.ConnectionStateChanged
NetTcpRelayBinding также поддерживает режим подключения Direct (Прямое), при котором для
передачи данных приложения может использоваться только прямое подключение, если оно
возможно, и не может применяться сервис ретрансляции.
Во время длительной передачи всегда существует вероятность разрыва подключения через сокет.
Решить эту проблему поможет WS-ReliableMessaging через привязку NetTcpRelayBinding. При
использовании WS-ReliableMessaging базовый стек WCF-канала будет автоматически делать
попытки восстановить любое разорванное соединение от вашего имени, делая, таким образом,
прямые соединения надежными. Чтобы применить WS-ReliableMessaging, нет необходимости
вносить какие-либо изменения в код приложения, требуется лишь настроить NetTcpRelayBinding.
Очевидно, что при предоставлении конечных точек NetTcpRelayBinding через .NET Service Bus с
ними смогут работать только клиентские приложения WCF, конфигурированные на использование
NetTcpRelayBinding. Такая настройка обеспечивает наилучшую производительность и пропускную
способность, но не охватывает широкий круг клиентов. Если определяющими требованиями
приложения являются область действия и возможность взаимодействия, следует использовать
одну из многочисленных HTTP-привязок, поддерживаемых .NET Service Bus.
HTTP-привязки ретрансляции
Все рассматриваемые до сих пор привязки требовали использования WCF на стороне клиентов
для обеспечения возможности взаимодействия. Если с конечными точками .NET Service Bus
необходимо интегрировать не WCF-клиентов, следует выбрать одну из многочисленных HTTPпривязок, поддерживаемых сервисом ретрансляции. .NET Service Bus поставляется с несколькими
HTTP-привязками:
WebHttpRelayBinding,
BasicHttpRelayBinding,
WSHttpRelayBinding
и
WS2007HttpRelayBinding. Все они предлагают большую область действия и более широкие
возможности взаимодействия, потому что могут поддерживать любого клиента, умеющего
работать со стандартными протоколами, поддерживаемыми каждой из этих привязок.
Привязки WebHttpRelayBinding и BasicHttpRelayBinding обеспечивают большую область действия,
потому что основаны на простых HTTP/REST и базовом SOAP, соответственно. Остальные HTTPпривязки ретрансляции способны обеспечивать дополнительные уровни функциональности через
протоколы WS-*. Например, при использовании WSHttpRelayBinding клиентам придется
поддерживать тот же набор протоколов WS-*, который используется конечной точкой. Основной
недостаток HTTP-привязок ретрансляции в том, что они требуют сравнительно больших затрат на
обработку.
Независимо от используемой HTTP-привязки ретрансляции процессы, имеющие место на сервисе
ретрансляции, во многом аналогичны (рис. 27). Сначала получатель устанавливает с сервисом
ретрансляции безопасное исходящее TCP-подключение (да-да, TCP-подключение). После этого
клиенты могут начинать передачу сообщений на конечную точку HTTP/SOAP, предоставленную
сервисом ретрансляции, используя стандартные методы HTTP/SOAP. Это означает, что больше нет
необходимости в использовании WCF на стороне клиента, подойдет любая совместимая с
HTTP/SOAP библиотека программ.
При поступлении входящего сообщения на один из интерфейсных узлов получателю отправляется
управляющее сообщение с инструкциями о том, как создать подключение для соединения с
интерфейсным узлом отправителя. Таким образом, формируется компонент прямой пересылки
HTTP-сокет для ретрансляции HTTP-сообщений.1
1
Этот процесс, по сути, является обратным тому, что происходит с NetOnewayRelayBinding при использовании режима
подключения HTTP. В том случае отправитель создает TCP-подключение с сервисом ретрансляции, в то время как
получатель получает сообщения по HTTP. Если необходимо, чтобы получатель тоже мог использовать HTTP, придется
создать специальную составную привязку на основании двух однонаправленных HTTP-каналов.
Backend Naming Routing Fabric
Frontend Nodes
Oneway Rendezvous Ctrl Msg
Серверная среда именования и маршрутизации
Интерфейсные узлы
Одностороннее управляющее сообщение для
установления подключения
Service Bus
Сервисная шина
HTTP/HTTPS request
запрос HTTP/HTTPS
HTTP-Socket Forwarder
Компонент пересылки HTTP-сокет
Sender
Отправитель
Receiver
Получатель
outbound socket rendezvous
исходящее подключение для встречи через
сокет
Рис. 25: HTTP-привязки ретрансляции
Сервис ретрансляции знает, как прозрачно выполнять маршрутизацию сообщений SOAP 1.1, SOAP
1.2 и незашифрованных сообщений HTTP (REST). Управление стилем обмена сообщений и
применением различных протоколов WS-* осуществляется через настройку одной из HTTPпривязок ретрансляции, как это делалось бы с любой другой WCF-привязкой.
Начнем с примера публикации RESTful-сервиса через .NET Service Bus. .NET Services SDK
поставляется с полным примером SimpleShare, который обеспечивает возможность совместного
использования локальных файлов и папок через .NET Service Bus. Этот сервис представляет
простой контракт RESTful-сервиса, использующий модель программирования для Веб WCF 3.5, как
показано ниже:
[ServiceContract(Name = "ISimpleShareHttpContract",
Namespace = "http://samples.microsoft.com/SimpleShare")]
public interface ISimpleShareHttpContract
{
[OperationContract, WebGet(UriTemplate="/*")]
Message Get();
}
Метод Get реализован таким образом, что выполняет проверку сегментов пути URI входящих
HTTP-запросов и определяет, как спроецировать их на локальную файловую систему. При запуске
приложения локального сервиса вы задаете каталог, который хотите сделать используемым
совместно, а также имя совместно используемого ресурса. Конфигурация приложения содержит
единственную конечную точку WebHttpRelayBinding, которая выглядит примерно так:1
1
Обратите внимание, что здесь для примера я использовал адрес одного из моих решений. Пример SDK приглашает
ввести имя решения и динамически формирует адрес во время выполнения.
<configuration>
<system.serviceModel>
<services>
<service name="Microsoft.ServiceBus.Samples.SimpleShareService">
<endpoint name="RelayEndpoint"
contract="Microsoft.ServiceBus.Samples.ISimpleShareHttpContract"
binding="webHttpRelayBinding"
address=
"http://pluralsight.servicebus.windows.net/SimpleShareService/" />
</service>
</services>
...
</system.serviceModel>
</configuration>
Запустим этот пример, задавая «c:\Demos» как каталог для совместного использования и
«demoshare» как имя совместно используемого ресурса. На рис. 28 показано, как выглядит
выполняющееся консольное приложение:
Рис. 26: Выполнение хост-приложения SimpleShare
Теперь мы имеем выполняющийся локально RESTful-сервис WCF, для которого опубликована
конечная точка на сервисе ретрансляции. И сервис ретрансляции знает, как направлять
поступающие HTTP-запросы на этот локальный WCF-сервис. Когда это приложение выполняется,
кто угодно, обладающий разрешениями для этого, может перейти по адресу
http://pluralsight.servicebus.windows.net/SimpleShareService/ и просматривать мой локальный
каталог, предоставленный для совместного использования (рис. 29).
Рис. 29: Переход к конечной точке HTTP
Обратите внимание, что данные возвращаются в виде RSS-канала, формируемого в Internet
Explorer. Сервис позволяет просматривать совместно используемый ресурс, переключаясь между
папками канала. Например, если щелкнуть папку «demoshare», на экран будут выведены
результаты, представленные на рис. 30.
Рис. 30: Просмотр подпапок совместно используемого ресурса
Когда пользователь находит файл, который хотел бы извлечь (скажем, большой zip-архив), он
может сформировать HTTP-запрос GET для получения этого zip-архива через сервис ретрансляции.
В общем, этот пример из SDK хорошо демонстрирует, как через .NET Service Bus можно
предоставить клиентам основанные на WCF RESTful-сервисы.1
В SDK имеется множество примеров, иллюстрирующих использование WSHttpRelayBinding с
различными вариантами настроек. Следующий пример показывает, как конфигурировать
конечную точку WSHttpRelayBinding для использования безопасности на базе сообщений с
маркерами имени пользователя и компонентом проверки клиента:
<configuration>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="usernamePasswordServiceBehavior">
<serviceCredentials>
<serviceCertificate findValue="localhost"
storeLocation="LocalMachine"
storeName="My" x509FindType="FindBySubjectName" />
<userNameAuthentication userNamePasswordValidationMode="Custom"
includeWindowsGroups="false" customUserNamePasswordValidatorType=
"SimpleUsernamePasswordValidator, WSHttpRelayMsgSecUserNameService" />
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<wsHttpRelayBinding>
<binding name="default">
<security mode="Message" relayClientAuthenticationType="None">
<message clientCredentialType="UserName"/>
</security>
</binding>
</wsHttpRelayBinding>
</bindings>
<services>
<service name="Microsoft.ServiceBus.Samples.EchoService"
behaviorConfiguration="usernamePasswordServiceBehavior">
<endpoint name="RelayEndpoint"
contract="Microsoft.ServiceBus.Samples.IEchoContract"
binding="wsHttpRelayBinding"
bindingConfiguration="default"
address=
"http://pluralsight.servicebus.windows.net/echo" />
</service>
</services>
...
</system.serviceModel>
</configuration>
1
В CTP-версии WebHttpRelayBinding не полностью совместима с WebScriptEnablingBehavior. На данный момент
специальная конечная точка, формирующая прокси-сервер JavaScript, недоступна через .NET Service Bus.
Вы просто настраиваете функции безопасности и надежного обмена сообщениями конечной
точки WSHttpRelayBinding, как делали бы это для WSHttpBinding. В приведенном выше примере
сервис ретрансляции не проводит никакой аутентификации, он просто ретранслирует сообщения
и предоставляет возможность позаботиться об этом сервису.
В общем, BasicHttpRelayBinding и WSHttpRelayBinding очень похожи на эквивалентные
стандартные WCF-привязки. Основная функция, не поддерживаемая WSHttpRelayBinding, –
транзакции, и это сделано намеренно.1 Не забудьте рассмотреть остальные примеры SDK, в
которых представлены различные варианты конфигурации и использования этих HTTP-привязок.
Управление доступом
Прежде чем создавать слушателя для получателя, .NET Service Bus требует, чтобы получатель
прошел аутентификацию и авторизацию для определенного URI. Клиенты также должны быть
аутентифицированы и авторизованы по умолчанию, только после этого .NET Service Bus будет
ретранслировать сообщения от их имени. Однако при настройке опций получателя в сервисе
ретрансляции аутентификация клиента может быть полностью отключена.
Аутентификация и авторизация
Традиционно аутентификация и авторизация являются отдельными вопросами. Аутентификация –
это процесс идентификация клиента, тогда как авторизация – это процесс принятия решения о
том, что позволено делать этому клиенту. .NET Service Bus позволяет обрабатывать эти аспекты
безопасности независимо друг от друга, но поведение по умолчанию в CTP-версии немного
размывает грань между ними.
Аутентификация .NET Service Bus может осуществляться любым поставщиком удостоверений,
которому доверяет .NET Access Control Service. После этого уже .NET Access Control Service
занимается приведением утверждений в форму, требуемую .NET Service Bus для целей
авторизации.
Доверенным поставщиком удостоверений для .NET Access Control Service негласно является
Windows Live ID (WLID). В следующей версии Active Directory Federation Services (кодовое название
«Geneva Server») можно будет использовать также собственные удостоверения Active Directory.
Кроме этих поставщиков удостоверений, сегодня, чтобы упростить начальный этап работы с ним,
.NET Access Control Service включает собственный встроенный поставщик удостоверений для
учетных записей решений, но, в конце концов, эта функция будет упразднена и придется
1
Поддержка транзакций в установленном канале связи между сторонами требует наличия у них координаторов
распределенных транзакций. При прохождении через .NET Service Bus установление такого отношения связано с
большими трудностями. Кроме того, поскольку для выполнения атомарных транзакций требуется блокировка ресурса,
как правило, он не рекомендуется к применению в Интернете, где время ожидания имеет решающее значение. Таким
образом, на данный момент транзакции не поддерживается ни одной привязкой.
ограничиться обычными провайдерами, такими как WLID или Geneva Server. Встроенный
провайдер удостоверений проводит аутентификацию на основании имени решения и пароля,
предоставленных при создании решении. В то же время, .NET Access Control Service может
объединяться с несколькими провайдерами удостоверений, выступая, таким образом, в роли
центрального органа управления доступом.1
.NET Service Bus специально спроекирован для работы с.NET Access Control Service. .NET Service Bus
ищет определенные утверждения в маркерах доступа, предоставленных отправителями и
получателями (которые они получили от .NET Access Control Service). Это два утверждения:
«#Listen» и «#Send». Когда получатель делает попытку создания слушателя, .NET Service Bus в
предоставленном .NET Access Control Service маркере доступа ищет утверждение «#Listen». Если
он находит его, и маркер не был поврежден или подделан, .NET Service Bus санкционирует
создание нового слушателя. То же самое происходит на стороне клиента, только в данном случае
.NET Service Bus ведет поиск утверждения «#Send».
Когда отправитель или получатель представляет учетные данные решения или маркер доступа
(полученные от доверенного провайдера удостоверений), .NET Access Control Service,
руководствуясь правилами, принимает решение о выпуске маркера авторизации (с утверждением
«#Send» или «#Listen») для целевого сервиса, .NET Service Bus в данном случае. При условии
предоставления действительного удостоверения .NET Access Control Service выпустит
соответствующий маркер для авторизации на .NET Service Bus.
.NET Access Control Service подписывает и шифрует результирующий маркер доступа, чтобы
утверждения могли быть прочитаны только целевым сервисом (т.е. .NET Service Bus). В результате,
только .NET Service Bus может дешифровать это сообщение и прочитать его содержимое. После
проверки достоверности и обработки маркера авторизации, переданным с сообщением, и перед
ретрансляцией сообщения получателю .NET Service Bus удаляет маркер авторизации. В любом
случае, маркер авторизации .NET Service Bus не имеет никакого значения для получателя.
Рис. 31 иллюстрирует описанную выше модель управления доступом .NET Service Bus, как для
отправителя, так и для получателя. Пронумерованные блоки желтого цвета представляют
последовательные действия, предпринимаемые получателем, тогда как пронумерованные блоки
синего цвета представляют действия отправителя.
1
Большинство примеров, поставляемых с .NET Services SDK, используют встроенный в .NET Access Control Service
провайдер удостоверений. Именно наличие такого встроенного провайдера удостоверений придает ощущение того,
что в .NET Access Control Service аутентификация/авторизация является единым процессом. Это может ввести в
заблуждение. При использовании другого провайдера удостоверений различие этих процессов, несомненно, будет
более очевидным.
1. Acquire Access Token #Send
1. Запрос маркера доступа #Send
2. Pass Access Token with Message
2. Передача маркера доступа с сообщением
3. Token Evaluated and Removed
3. Анализ маркера и удаление
4. Message Passed on to Receiver
4. Передача сообщения получателю
1. Acquire Access Token #Listen
1. Запрос маркера доступа #Listen
2. Pass Access Token with Subscription
2. Передача маркера доступа с подпиской
3. Token Evaluated
3. Анализ маркера
Access Control STS
STS для управления доступом
Service Bus Relay
Ретранслятор сервисной шины
Sender
Отправитель
Receiver
Получатель
Token Header
Заголовок маркера
Рис. 27: Модель управления доступом .NET Service Bus
Модель программирования WCF для управления доступом
Модель программирования WCF для .NET Service Bus обеспечивает несколько простых
абстракций, которые упрощают работу с моделью управления доступом .NET Service Bus,
представленной на рис. 31. Учетные данные, используемые для конкретной конечной точки .NET
Service Bus, задаются через TransportClientEndpointBehavior, применение которого было
продемонстрировано в самом первом примере этого документа, HelloServiceBus.
Свойство credentialType (тип учетных данных) принимает одно из значений, описанных на рис. 32.
Могут использоваться информационные карточки Windows CardSpace, сертификаты X.509, имя
пользователя/пароль или вообще не использоваться никакие учетные данные. В SDK имеется
множество примеров, иллюстрирующих применение различных вариантов учетных данных.
Значение CredentialType
CardSpace
Описание
В качестве учетных данных клиента используется самостоятельно
выдаваемая информационная карточка Windows CardSpace,
AutomaticRenewal
FederationViaCardSpace
UserNamePasssword
X509Certificate
Unauthenticated
зарегистрированная .NET Access Control Service.
В качестве учетных данных клиента используется самостоятельно
выдаваемая информационная карточка Windows CardSpace,
зарегистрированная .NET Access Control Service. Разница в том, что в
случае необходимости маркер доступа будет автоматически обновлен.
В качестве учетных данных клиента используется управляемая
информационная карточка Windows CardSpace, выданная издателем
удостоверений, которому доверяет .NET Access Control Service.
В качестве учетных данных клиента используются имя
пользователя/пароль решения .NET Service Bus, зарегистрированные в
.NET Access Control Service.
В качестве учетных данных клиента используется сертификат X.509
решения .NET Service Bus, зарегистрированный в .NET Access Control
Service.
Учетные данные клиента не предоставляются.
Рис. 28: Значения свойства CredentialType
Информационные карточки Windows CardSpace и сертификаты X.509 регистрируются на .NET
Access Control Service через портал Azure Services Platform. После регистрации информационная
карточка Windows CardSpace или сертификат X.509 могут использоваться для аутентификации.
Также управлять необходимостью аутентификации клиентов на .NET Service Bus можно через
настройку
привязки
для
получателя.
Делается
это
с
помощью
свойства
relayClientAuthenticationType (Тип аутентификации клиента ретрансляции) элемента <security>
(безопасность), поддерживаемого всеми привязками ретрансляции. Если этому свойству задано
значение «None», клиентам не надо будет проходить аутентификацию для ретрансляции
сообщений получателю. Если задать значение «RelayAccessToken» (Маркер доступа для
ретрансляции), клиенты должны будут предоставлять маркеры авторизации сервису
ретрансляции. Следующий фрагмент кода демонстрирует, как следует изменить настройки
примера SimpleShare, чтобы аутентификация клиента при ретрансляции не проводилась:
<configuration>
<system.serviceModel>
<services>
<service name="Microsoft.ServiceBus.Samples.SimpleShareService">
<endpoint name="RelayEndpoint"
contract="Microsoft.ServiceBus.Samples.ISimpleShareHttpContract"
binding="webHttpRelayBinding"
bindingConfiguration="default"
address="http://pluralsight.servicebus.windows.net/share/" />
</service>
</services>
<bindings>
<webHttpRelayBinding>
<binding name="default">
<security relayClientAuthenticationType="None" />
</binding>
</webHttpRelayBinding>
</bindings>
...
</system.serviceModel>
</configuration>
Также можно применять «гибридный» режим безопасности, сочетая безопасность на базе
сообщений (WS-Security) с режимом аутентификации клиента ретрансляции «RelayAccessToken».
Для этого необходимо задать стандартный режим безопасности «Message» (для привязки) и
«RelayAccessToken» в качестве режима аутентификации для клиента ретрансляции. После этого
потребуется указать для клиента два отдельных удостоверения: одно через WCF-свойство
ClientCredentials (Учетные данные клиента) (для получения доступа к целевому сервису) и другое
через TransportClientEndpointBehavior (для получения доступа к .NET Service Bus).
Аутентификация в стиле Веб (REST)
Если используется WebHttpRelayBinding и свойству relayClientAuthenticationType задано значение
«RelayAccessToken», сервис ретрансляции обеспечивает уровень защиты через HTTP-сервис
RESTful, который требует аутентификации и авторизации клиентов с помощью маркера
авторизации .NET Service Bus. Существует два способа предоставления необходимого маркера
авторизации сервису ретрансляции: либо через интерактивно вводимые учетные данные, либо
программно через интерфейс RESTful.
Если клиент формирует HTTP-запрос к конечной точке .NET Service Bus без предоставления
маркера авторизации, сервис ретрансляции перенаправит этот запрос на интерактивную страницу
регистрации (рис. 33). Эта страница принимает ассоциированные с решением CardSpace или имя
пользователя/пароль. После введения действительных учетных данных пользователь, а также
необходимый маркер авторизации, будут возвращены к исходному запросу, и запрос будет
успешно ретранслирован.1
Рис. 29: Интерактивная страница регистрации
Также можно пройти этот этап авторизации программно через RESTful-интерфейс .NET Access
Control Service. Сейчас запросить маркер авторизации можно, просто сформировав следующий
HTTP-запрос GET к .NET Access Control Service:2
https://accesscontrol.windows.net/isssuetoken.aspx?u={имя-решения}&p={пароль}
Ответ содержит файл cookie ссылок (в обычном текстовом формате) на маркер, находящийся на
.NET Access Control Service. Клиент может использовать этот cookie для получения доступа к
сервису ретрансляции, добавляя значение cookie в специальный HTTP-заголовок «X-MS-IdentityToken» исходящих HTTP-запросов. Microsoft настоятельно рекомендует с этой техникой
использовать HTTPS для защиты значения cookie при передаче.
Больше информации о .NET Access Control Service и конкретно об использовании его в сочетании с
собственными сервисами (не просто через .NET Service Bus) можно найти в сопроводительном
документе «Руководство по .NET Access Control Service для разработчиков».
1
Интерактивная страница регистрации является временным решением. Ее уже запланировано заменить в будущем
более гибкой версией, которая обеспечит возможность использования федеративных провайдеров удостоверений и их
сайтов регистрации.
2 Конечная точка GET также временное решение, используемое в CTP-версии как эксперимент.
Очереди и маршрутизаторы
Как можно увидеть из всего вышеизложенного, .NET Service Bus, главным образом, выполняет
роль транзитного ретранслятора между двумя сторонами. При реализации этой функции наличие
активных слушателей на .NET Service Bus является основным условием для начала отправки им
сообщений отправителями. Но что если отправители и получатели не могут всегда выполняться
синхронно? Или если они не могут обрабатывать сообщения с одинаковой скоростью из-за разной
пропускной способности или других ограничений ресурсов? При работе с предыдущими CTPверсиями пользователи чаще всего говорили о необходимости создания механизма ведения
долгосрочных очередей, который позволил бы реализовать семантику асинхронной связи или
связи в отсоединенном режиме через .NET Service Bus.
Понимание очередей и маршрутизаторов
CTP-версия, вышедшая в марте 2009 года, представляет два новых примитива обмена
сообщениями, очереди и маршрутизаторы, которые обеспечивают возможность поддерживать
разнообразные дополнительные требования к связи, обычно предъявляемые сегодня. Эти новые
примитивы являются свидетельством изменения стратегии Microsoft относительно .NET Services
Bus, возможностей, которые он должен предоставлять, и дальнейшего развития. Они являются
долговечными (постоянными) и могут существовать независимо от традиционных слушателей
.NET Service Bus. Иначе говоря, очереди/машрутизаторы могут существовать и функционировать
даже в случае отсутствия активных слушателей.
Очереди, как предполагает их название, обеспечивают долгосрочную структуру данных с
семантикой FIFO. Очередь создается в пространстве имен .NET Service Bus точно так же, как
слушатели. Для этого в пространстве имен решения .NET Service Bus просто задается имя очереди,
определяется политика очереди (чуть позже поговорим об этом более подробно) и формируется
запрос на создание очереди с заданным именем (рис. 34).
Backend Naming Routing Fabric
Серверная среда именования и маршрутизации
Frontend Nodes
Интерфейсные узлы
Route
Маршрутизация
Dequeue
Вывод из очереди
Service Bus
Сервисная шина
HTTP(S) Dequeue
Вывод из очереди, HTTPS
Manager
Диспетчер
Queue Policy
Политика очереди
Sender
Отправитель
Receiver
Получатель
Рис. 30: Очереди в .NET Service Bus
Будучи созданными, отправители могут отправлять сообщения в очередь, и получатели могут
читать сообщения из очереди, но суть в том, что вовсе не обязательно, чтобы эти отправители и
получатели выполнялись одновременно. Отправители могут передавать сообщения в очереди,
используя протоколы HTTP(S) или net.tcp, но получатели могут читать сообщения из очереди
только с помощью HTTP(S). Также очереди поддерживают принцип выбора с блокировкой (peeks
with locks), что гарантирует сохранность сообщений в случае сбоя приложения. Необходимо знать
несколько основных ограничений: очереди поддерживают сообщения размером до 64КБ и не
поддерживают потоковую передачу.
Маршрутизаторы, с другой стороны, отвечают за маршрутизацию сообщений к одному или более
подписчикам. Маршрутизаторы создаются точно так же, как и очереди. В решении .NET Service Bus
выбирается имя маршрутизатора, определяется политика маршрутизатора (чуть позже
поговорим об этом более подробно) и формируется запрос на создание маршрутизатора с таким
именем (рис. 35). Политика маршрутизатора определяет, как должно происходить
распределение: всем подписчикам (многоадресная рассылка) или одному подписчику с
использованием карусельного алгоритма распределения нагрузки. Один или более получателей
(включая очереди) могут создавать подписки на маршрутизаторе, включая себя тем самым в
политику распределения сообщений маршрутизатора (рис. 35).
Backend Naming Routing Fabric
Серверная среда именования и маршрутизации
Frontend Nodes
Интерфейсные узлы
Route
Маршрутизация
Router
Маршрутизатор
Queue
Очередь
Service Bus
Сервисная шина
Subscribe
подписка
Manager
Диспетчер
Router Policy
Политика маршрутизатора
Sender
Отправитель
Receiver
Получатель
Рис. 31: Маршрутизаторы в .NET Service Bus
Созданные в решении .NET Service Bus очереди и маршрутизаторы, имеющие политику,
позволяющую их публикацию, отображаются в реестре сервиса решения. Таким образом, клиенты
могут находить эти конструкции динамически во время выполнения.
Одно из самых интересных свойств очередей и маршрутизаторов – их сочетание друг с другом.
Очереди могут подписываться на маршрутизаторы, так же как и сервисы. Это обеспечивает
долгосрочное постоянное хранилище для маршрутизованных сообщений. Если сообщение
поступило в очередь, оно может оставаться там до тех пор, пока приложение, которое должно его
обработать, не извлечет его, и это может произойти много после завершения работы отправителя.
На рис. 36 показан пример реализации различный сценариев обмена сообщениями путем
сочетания очередей и маршрутизаторов.
Router (Distribution: All)
Маршрутизатор (Распределение: All)
Queue
Очередь
Router (Distribution: One)
Маршрутизатор (Распределение: One)
Service
Сервис
Рис. 32: Сочетание очередей и маршрутизаторов
Как видите, политика распределения интерфейсного маршрутизатора – «All». Это означает, что он
будет рассылать входящие сообщения всем подписчикам. У этого маршрутизатора два
подписчика: очередь и другой маршрутизатор. Очередь просто обеспечивает долговременное
хранение поступивших сообщений, в то время как сервис (Сервис А) периодически выбирает их
непосредственно из очереди. Обратите внимание, что для второстепенного маршрутизатора
задана политика «One», т.е. он будет равномерно распределять входящие сообщения по одному
между всеми подписчиками (Сервис B, C и D). Он также мог бы без труда рассылать сообщения
всем подписчикам; для этого просто необходимо изменить политику на «All».
Программирование очередей
Основной API для взаимодействия с очередями .NET Service Bus построен на REST и WS-Transfer.
Работу с очередями можно программировать непосредственно, используя один из этих открытых
стилей (или любую платформу), или можно использовать различные классы очередей,
предоставляемые .NET Services SDK, которые позволяют абстрагироваться от тонкостей базовых
протоколов и намного упрощают разработку.1
Давайте рассмотрим полный пример, иллюстрирующий создание очереди, отправку сообщений в
очередь и изъятие сообщений из очереди. Для реализации этих задач воспользуемся классами
очереди .NET Services SDK. Тем не менее, не забывайте, что все это можно сделать напрямую,
используя REST/HTTP.
1
В основе встроенных классов API лежат SOAP и интерфейс WS-Transfer. В SDK модно найти множество примеров,
иллюстрирующих, как напрямую использовать API REST через применение традиционной логики программирования
HTTP.
Для создания очереди применяем класс QueueManagementClient (Клиент управления очередью),
который обеспечивает различные методы создания, извлечения, обновления и удаления
очередей и их политик:
public static class QueueManagementClient
{
public static QueueClient CreateQueue(TransportClientEndpointBehavior
credential, Uri queueUri, QueuePolicy queuePolicy);
public static void DeleteQueue(TransportClientEndpointBehavior credential,
Uri queueUri);
public static QueueClient GetQueue(TransportClientEndpointBehavior
credential, Uri queueUri);
public static QueuePolicy GetQueuePolicy(TransportClientEndpointBehavior
credential, Uri queueUri);
public static DateTime RenewQueue(TransportClientEndpointBehavior credential,
Uri queueUri, TimeSpan requestedExpiration);
}
Класс QueuePolicy (Политика очереди) представляет данные политика очереди, используемые
.NET Service Bus для управления очередями. Этот класс упрощает задачу по описанию и работе с
политиками:
[DataContract(Namespace = "http://schemas.microsoft.com/ws/2007/08/connect")]
public class QueuePolicy : JunctionPolicy, IExtensibleDataObject
{
public QueuePolicy();
public QueuePolicy(QueuePolicy queuePolicyToCopy);
public
public
public
public
public
public
public
public
TimeSpan EnqueueTimeout { get; set; }
int MaxConcurrentReaders { get; set; }
int MaxDequeueRetries { get; set; }
TimeSpan MaxMessageAge { get; set; }
long MaxQueueCapacity { get; internal set; }
int MaxQueueLength { get; set; }
OverflowPolicy Overflow { get; set; }
EndpointAddress PoisonMessageDrop { get; set; }
}
Класс QueuePolicy предоставляет свойства для управления различными аспектами поведения
очереди. Благодаря этим двум классам создание очереди становится просто вопросом создания
нового экземпляра QueuePolicy и вызова метода CreateQueue. Это демонстрирует следующий
фрагмент кода:
...
TransportClientEndpointBehavior creds = new TransportClientEndpointBehavior();
creds.CredentialType = TransportClientCredentialType.UserNamePassword;
creds.Credentials.UserName.UserName = solutionName;
creds.Credentials.UserName.Password = solutionPassword;
Uri quri = ServiceBusEnvironment.CreateServiceUri("sb",solutionName,"/myqueue");
QueuePolicy policy = new QueuePolicy();
policy.Discoverability = DiscoverabilityPolicy.Public;
policy.Authorization = AuthorizationPolicy.NotRequired;
policy.ExpirationInstant = DateTime.Now + TimeSpan.FromDays(1);
QueueManagementClient.CreateQueue(creds, quri, policy);
Console.WriteLine("Queue created!");
...
Обратите внимание на использование ServiceBusEnvironment.CreateServiceUri для создания
соответствующего URI очереди в рамках моего решения 1 . Также через экземпляр
TransportClientEndpointBehavior (Поведение конечной точки клиента) мы предоставляем учетные
данные решения .NET Services, абсолютно аналогично предыдущим примерам .NET Service Bus
(ничего нового). Данный конкретный QueuePolicy определяет, что очередь должна быть открыто
доступна для просмотра, что авторизация не нужна и что срок ее жизни – сутки, после чего она
будет уничтожена (если только не будет возобновлена методом RenewQueue (Обновить
очередь)).
Поскольку мы сделали данную очередь доступной для просмотра, ее можно увидеть в реестре
сервиса решения в канале ATOM, как показано на рис. 37.
Рис. 33: Просмотр созданной очереди в реестре сервиса
1
Применение ServiceBusEnvironment.CreateServiceUri является вообще хорошей практикой для создания новых URI .NET
Service.
Теперь, если бы мы посмотрели на исходный код канала ATOM, мы бы увидели следующий XMLдокумент, элемент <entry> которого полностью описывал бы только что созданную очередь:
<feed xmlns="http://www.w3.org/2005/Atom">
<title type="text">Publicly Listed Services</title>
<subtitle type="text">This is the list of publicly-listed services currently
available</subtitle>
<id>uuid:9af6f908-1360-43fc-bdc8-cb67066ffd2f;id=368</id>
<updated>2009-04-08T19:12:51Z</updated>
<generator>Microsoft® .NET Services - Service Bus</generator>
<entry>
<id>uuid:9af6f908-1360-43fc-bdc8-cb67066ffd2f;id=369</id>
<title type="text">myqueue</title>
<updated>2009-04-08T19:12:51Z</updated>
<link rel="alternate"
href="https://pluralsight.servicebus.windows.net/myqueue/"/>
<link rel="self"
href="https://pluralsight.servicebus.windows.net/myqueue/!(queue)"/>
<link rel="queuehead"
href="https://pluralsight.servicebus.windows.net/myqueue/!(queue/head)"/>
<link rel="queuecontrol"
href="https://pluralsight.servicebus.windows.net/myqueue/!(queue/control)"/>
<QueuePolicy xmlns="http://schemas.microsoft.com/ws/2007/08/connect"
xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<Authorization>NotRequired</Authorization>
<Discoverability>Public</Discoverability>
<ExpirationInstant>2009-04-09T12:12:25.392-07:00</ExpirationInstant>
</QueuePolicy>
</entry>
</feed>
В элементе <entry> есть все, что необходимо знать клиенту очереди для взаимодействия с ней.
Первый элемент <link> (rel=”alternate”) представляет адрес очереди. Политика очереди полностью
описывается элементом <QueuePolicy> в конце документа. Также в элементе <entry> можно найти
ссылки на различные ресурсы, образующие тело каждой очереди.
Каждая очередь .NET Service Bus состоит из следующих ресурсов: головы, хвоста, политики и
управления. Работа с очередью осуществляется путем взаимодействия с этими отдельными
ресурсами с использованием REST или WS-Transfer. При выполнении выборок с блокировкой
создаются дополнительные ресурсы, которые представляют эти «блокировки». Взаимодействие с
ними осуществляется аналогичным образом. Использование API REST заключается просто в
формировании запросов GET, POST, PUT и DELETE к URI различных ресурсов, показанным выше, с
использованием ATOM в качестве формата HTTP-сообщений (в SDK можно найти примеры,
демонстрирующие этот подход в действии). Однако, опять же, используемые в этих фрагментах
кода классы SDK скрывают все эти базовые детали от разработчиков.
Теперь рассмотрим, как отправлять сообщения в нашу новую очередь .NET Service Bus. Первым
делом, необходимо извлечь объект QueueClient (Клиент очередь) с помощью метода
QueueManagementClient.GetQueue. QueueClient предоставляет множество
взаимодействия с экземпляром очереди, как показано в данном фрагменте кода:
методов
для
public sealed class QueueClient
{
public void DeleteLockedMessage(Message message);
public void DeleteQueue();
public DateTime GetExpiration();
public QueuePolicy GetPolicy();
public Message PeekLock();
public Message PeekLock(TimeSpan timeout);
public IEnumerable<Message> PeekLockMultiple(int maxMessages);
public IEnumerable<Message> PeekLockMultiple(int maxMessages,
TimeSpan timeout);
public void Purge();
public void ReleaseLock(Message message);
public DateTime Renew(TimeSpan requestedExpiration);
public Message Retrieve();
public Message Retrieve(TimeSpan timeout);
public IEnumerable<Message> RetrieveMultiple(int maxMessages);
public IEnumerable<Message> RetrieveMultiple(int maxMessages,
TimeSpan timeout);
public void Send(Message message, TimeSpan timeout);
public RouterSubscriptionClient SubscribeToRouter(RouterClient routerClient,
TimeSpan requestedTimeout);
}
Воспользуемся методом Send и отправим простое строковое сообщение в нашу новую очередь. С
помощью Message.CreateMessage создадим новый экземпляр WCF-сообщения, который можно
передать в Send. Следующий фрагмент кода представляет полный пример отправки пяти
сообщений в очередь:
...
QueueClient client = QueueManagementClient.GetQueue(creds, quri);
for (int i = 1; i <= 5; i++)
{
Message msg = Message.CreateMessage(
MessageVersion.Default, "urn:testsend", string.Format("hello: {0}", i));
client.Send(msg, TimeSpan.MaxValue);
}
Console.WriteLine("Messages sent to queue!");
...
Процесс извлечения сообщений из очереди практически аналогичен. Просто извлекается
экземпляр QueueClient и выполняется многократный вызов Retrieve до полного освобождения
очереди. Рассмотрим простой пример:
...
QueueClient client = QueueManagementClient.GetQueue(creds, quri);
while (true)
{
Message msg = client.Retrieve();
Console.WriteLine(msg.GetBody<string>());
}
...
После выполнения этого кода в консоли будут выведены результаты, представленные на рис. 38.
Рис. 34: Результаты извлечения очереди
С SDK также поставляются многочисленные примеры очередей, иллюстрирующие различные
функции и возможности связи. SDK предоставляет полные пример использования API REST/ATOM
напрямую с простым программированием HTTP. Поскольку с очередями .NET Service Bus можно
взаимодействовать, используя простой HTTP, для работы с этим сервисом устанавливать .NET
Services SDK не обязательно, т.е. возможности .NET Service Bus очень просто использовать и на
других платформах.
Программирование маршрутизаторов
Модель программирования маршрутизаторов в .NET Service Bus практически аналогична модели
программирования очередей. SDK поступает с подобными классами для программирования
маршрутизаторов, включая RouterManagementClient (Клиент управления маршрутизатором),
RouterPolicy (Политика маршрутизатора) и RouterClient (Клиент маршрутизатора). Ключевое
отличие в случае с маршрутизаторами в том, что SDK также предоставляет классы и методы для
управления подписками маршрутизаторов, что является уникальной концепцией
маршрутизаторов. Но во всем остальном программирование обоих примитивов обмена
сообщениями поразительно симметрично.
Начнем с создания маршрутизатора. Как и в случае с очередями, необходимо создать экземпляр
RouterPolicy и затем с помощью класса RouterManagementClient отправить запрос на создание
маршрутизатора.
Следующий
фрагмент
кода
показывает
описание
класса
для
RouterManagementClient. Обратите внимание на методы для создания, извлечения,
возобновления и удаления маршрутизаторов в решении .NET Service Bus.
public static class RouterManagementClient
{
public static RouterClient CreateRouter(TransportClientEndpointBehavior
credential, Uri routerUri, RouterPolicy routerPolicy);
public static void DeleteRouter(TransportClientEndpointBehavior credential,
Uri routerUri);
public static RouterClient GetRouter(TransportClientEndpointBehavior
credential, Uri routerUri);
public static RouterPolicy GetRouterPolicy(TransportClientEndpointBehavior
credential, Uri routerUri);
public static DateTime RenewRouter(TransportClientEndpointBehavior
credential, Uri routerUri, TimeSpan requestedExpiration);
}
И далее рассмотрим описание класса для RouterPolicy:
[DataContract(Namespace = "http://schemas.microsoft.com/ws/2007/08/connect")]
public class RouterPolicy : JunctionPolicy, IExtensibleDataObject
{
public RouterPolicy();
public RouterPolicy(RouterPolicy otherRouterPolicy);
public
public
public
public
public
public
public
public
TimeSpan BufferTimeout { get; set; }
long MaxBufferCapacity { get; internal set; }
int MaxBufferLength { get; set; }
int MaxSubscribers { get; set; }
MessageDistributionPolicy MessageDistribution { get; set; }
OverflowPolicy Overflow { get; set; }
int PushDeliveryRetries { get; set; }
TimeSpan PushDeliveryTimeout { get; set; }
}
Эти два класса делают создание нового маршрутизатора просто вопросом создания нового
экземпляра RouterPolicy и вызова метода CreateRouter, что демонстрирует следующий фрагмент
кода:
...
Uri ruri = ServiceBusEnvironment.CreateServiceUri("sb", "pluralsight",
"/myrouter");
RouterPolicy policy = new RouterPolicy();
policy.Discoverability = DiscoverabilityPolicy.Public;
policy.Authorization = AuthorizationPolicy.NotRequired;
policy.ExpirationInstant = DateTime.UtcNow + TimeSpan.FromDays(1);
policy.MessageDistribution = MessageDistributionPolicy.AllSubscribers;
RouterManagementClient.CreateRouter(creds, ruri, policy);
Console.WriteLine("Router created!");
...
Данная конкретная политика маршрутизатора определяет, что маршрутизатор должен быть
открыто доступен для просмотра, не требовать аутентификации, что срок его действия – одни
сутки, и что он будет направлять сообщения всем подписчикам.
Выполнив этот код и вернувшись на страницу регистрации решения, мы увидим, что в канале
ATOM появился новый маршрутизатор (рис. 39).
Рис. 35: Просмотр созданного маршрутизатора в реестре сервиса
Теперь, если посмотреть на исходный код канала ATOM, можно увидеть следующий XMLдокумент, элемент <entry> которого полностью описывает только что созданный маршрутизатор:
<feed xmlns="http://www.w3.org/2005/Atom">
<title type="text">Publicly Listed Services</title>
<subtitle type="text">This is the list of publicly-listed services currently
available</subtitle>
<id>uuid:1edbaeed-3f2f-4ed4-8523-96cb9abca1ae;id=155</id>
<updated>2009-04-08T22:24:34Z</updated>
<generator>Microsoft® .NET Services - Service Bus</generator>
<entry>
<id>uuid:1edbaeed-3f2f-4ed4-8523-96cb9abca1ae;id=157</id>
<title type="text">myrouter</title>
<updated>2009-04-08T22:24:35Z</updated>
<link rel="alternate"
href="https://pluralsight.servicebus.windows.net/myrouter/"/>
<link rel="self"
href="https://pluralsight.servicebus.windows.net/myrouter/!(router)"/>
<link rel="subscriptions"
href="https://pluralsight.servicebus.windows.net/myrouter/!(router/subscriptions)"/>
<RouterPolicy xmlns="http://schemas.microsoft.com/ws/2007/08/connect"
xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<Authorization>NotRequired</Authorization>
<Discoverability>Public</Discoverability>
<ExpirationInstant>2009-04-09T22:23:52.119Z</ExpirationInstant>
<MessageDistribution>AllSubscribers</MessageDistribution>
</RouterPolicy>
</entry>
</feed>
В элементе <entry> есть все, что необходимо знать клиенту маршрутизатора для взаимодействия с
нам. Первый элемент <link> (rel=”alternate”) представляет адрес маршрутизатора. Политика
маршрутизатора полностью описывается элементом <RouterPolicy> в конце документа. Также в
элементе <entry> можно найти ссылки на различные ресурсы, образующие тело каждого
маршрутизатора.
Каждый маршрутизатор .NET Service Bus состоит из следующих ресурсов: маршрутизатора,
политики и подписок. Работа с маршрутизатором осуществляется путем взаимодействия с этими
отдельными ресурсами с использованием REST или WS-Transfer. Использование API REST
заключается просто в формировании запросов GET, POST, PUT и DELETE к URI различных ресурсов,
показанным выше, с использованием ATOM в качестве формата HTTP-сообщений (примеры
можно найти в SDK). Однако, опять же, используемые в этих фрагментах кода классы SDK
скрывают все эти базовые детали от разработчиков.
Теперь рассмотрим код для «подписки» слушателя на конкретный маршрутизатор. Подход к
подписке на маршрутизатор может немного отличаться в зависимости от того, подписчика какого
типа необходимо добавить. В роли подписчиков могут выступать однонаправленные сервисы,
использующие NetOnewayRelayingBinding, слушатели на базе HTTP или очереди. Самым простым
для добавления программно является первый тип, поэтому остановимся на нем.
Прежде всего, необходимо извлечь экземпляр RouterClient, вызвав метод GetRouter класса
RouterManagementClient. Этот класс представляет экземпляр маршрутизатора в .NET Service Bus и
предоставляет множество методов для взаимодействия с маршрутизатором, включая подписку на
маршрутизатор, а также возобновление, обновление и удаление его экземпляра. Рассмотрим
описание класса RouterClient:
public sealed class RouterClient
{
public Uri RouterUri { get; }
public ServiceEndpoint AddRouterServiceEndpoint<T>(ServiceHost serviceHost);
public ServiceEndpoint AddRouterServiceEndpoint<T>(ServiceHost serviceHost,
EndpointAddress role);
public ChannelFactory<T> CreateRouterClient<T>();
public void DeleteRouter();
public DateTime GetExpiration();
public RouterPolicy GetPolicy();
public DateTime Renew(TimeSpan expiration);
public void Send(Message message, TimeSpan timeout);
public RouterSubscriptionClient Subscribe(EndpointAddress notifyToAddress,
TimeSpan requestedExpiration);
public RouterSubscriptionClient Subscribe(EndpointAddress notifyToAddress,
TimeSpan requestedExpiration, EndpointAddress endToAddress);
public RouterSubscriptionClient Subscribe(EndpointAddress notifyToAddress,
TimeSpan requestedExpiration, WebHeaderCollection notifyHttpHeaders);
public RouterSubscriptionClient Subscribe(EndpointAddress notifyToAddress,
TimeSpan requestedExpiration, WebHeaderCollection notifyHttpHeaders,
EndpointAddress endToAddress);
public RouterSubscriptionClient SubscribeToRouter(RouterClient routerClient,
TimeSpan requestedTimeout);
}
Имея экземпляр RouterClient, не составляет труда добавить подписчиков с помощью одного из
перечисленных выше методов «подписки». Ниже показано, как добавить в качестве подписчика
однонаправленный WCF-сервис:
...
RouterClient routerClient = RouterManagementClient.GetRouter(creds, ruri);
ServiceHost subscriberHost = new ServiceHost(typeof(OnewaySubscriberService));
ServiceEndpoint subscriberEndpoint =
routerClient.AddRouterServiceEndpoint<IOnewayContract>(subscriberHost);
subscriberHost.Open();
try
{
Console.WriteLine("Subscriber is listening for messages.");
Console.WriteLine("Press <Enter> to exit...");
Console.ReadLine();
subscriberHost.Close();
}
catch
{
subscriberHost.Abort();
throw;
}
...
Для этого просто вызывается метод AddRouterServiceEndpoint (Добавить конечную точку сервиса
маршрутизатора) экземпляра RouterClient с указанием экземпляра ServiceHost (Хост сервиса) для
локального WCF-сервиса. IOnewayContract – это очень простой контракт WCF-сервиса, который
выглядит следующим образом:
[ServiceContract(Name = "IOnewayContract", Namespace =
"http://samples.microsoft.com/ServiceModel/Relay/")]
public interface IOnewayContract
{
[OperationContract(IsOneWay = true)]
void Send(string message);
}
Также довольно просто добавить в качестве подписчика очередь .NET Service Bus. Класс
QueueClient предоставляет для этого метод SubscribeToRouter (Подписаться на маршрутизатор):
private static void SubscribeQueueToRouter(Uri ruri, Uri quri,
TransportClientEndpointBehavior creds)
{
// получаем существующий маршрутизатор
RouterClient routerClient = RouterManagementClient.GetRouter(creds, ruri);
QueueClient queueClient = QueueManagementClient.GetQueue(creds, quri);
// подписываем очередь на маршрутизатор
queueClient.SubscribeToRouter(routerClient, TimeSpan.FromDays(1));
RetrieveMessages(quri, creds);
}
Это два примера добавления подписчиков для нашего маршрутизатора. Теперь можно начинать
отправлять сообщения на маршрутизатор, чтобы увидеть «маршрутизацию» в действии.
Следующий пример иллюстрирует создание однонаправленного канала от экземпляра
RouterClient, который может использоваться для передачи сообщений на маршрутизатор:
...
// получаем существующий маршрутизатор
RouterClient routerClient = RouterManagementClient.GetRouter(creds, ruri);
// создаем канал к маршрутизатору
ChannelFactory<IOnewayChannel> onewayChannelFactory =
routerClient.CreateRouterClient<IOnewayChannel>();
onewayChannelFactory.Endpoint.Behaviors.Add(creds);
IOnewayChannel onewayChannel = onewayChannelFactory.CreateChannel();
onewayChannel.Open();
for (int i = 1; i <= 5; i++)
onewayChannel.Send(string.Format("hello: {0}", i));
onewayChannel.Close();
...
Получив сообщение, маршрутизатор направит его всем подписчикам, поскольку так определено
его политикой. На рис. 40 показаны результаты, полученные WCF-сервисом, подписанным на этот
маршрутизатор. Такие же сообщения были получены ранее в консоли при работе с очередью.
Рис. 36: Результаты маршрутизации сообщений подписчику
.NET Services SDK включает несколько дополнительных примеров, иллюстрирующих работу с
маршрутизаторами с использованием API REST напрямую. Примеры также показывают, как
подписывать на маршрутизатор слушателей на базе HTTP (которые не используют SOAP), что
может быть интересным. Мы лишь слегка коснулись возможностей, открываемых перед
разработчиками очередями и маршрутизаторами. Все детали и подробности по этим вопросам
можно найти в SDK.
Рекомендации
Один из самых сложных вопросов при работе с .NET Service Bus – выбор привязки. В данном
разделе представлены общие рекомендации, которые помогут принять правильное решение.
Microsoft рекомендует по умолчанию, если нет необходимости в какой-то конкретной функции
связи, предоставляемой другой привязкой, использовать NetTcpRelayBinding. Эту привязку можно
увидеть в примере HelloServiceBus в начале данного документа. NetTcpRelayBinding предлагает
самый компактный формат подключения и наиболее эффективный канал связи через
инфраструктуру сервиса ретрансляции. Таким образом, она обеспечит самую высокую
пропускную способность из всех WCF-привязок ретрансляции и минимальный объем затрат на
обработку на слушающем сервисе.
Если требуется передавать большие сообщения между равноправными участниками сети,
режимы
Hybird/Direct
являются
более
предпочтительными
при
использовании
NetTcpRelayBinding.
При работе в защищенных сетевых средах NetTcpRelayBinding может не подойти, если слушатели
требуют применения исходящих TCP-портов. В таких ситуациях придется использовать
NetOnewayRelayBinding или NetEventRelayBinding. Эти привязки обеспечивают опции для более
агрессивного обхода NAT/сетевых экранов, потому что предлагают необязательный режим связи
через HTTP, который позволяет слушателям получать сообщения через обычно открытые HTTPпорты (80/443). NetEventRelayBinding применяется, главным образом, когда требуется обеспечить
распределение событий в сценариях многоадресных рассылок.1
Привязки NetTcpRelayBinding, NetOnewayRelayBinding и NetEventRelayBinding не подходят, если
требуется обеспечить связь с не-Майкрософт клиентами. В этом случае необходимо обратиться к
HTTP-привязкам ретрансляции. HTTP-привязки ретрансляции обеспечивают самый высокий
уровень возможности взаимодействия с остальным миром, потому что предоставляют конечные
точки, основанные на открытых стандартах, включая HTTP, SOAP 1.1 и SOAP 1.2. При
использовании HTTP-привязок ретрансляции любой совместимый клиент веб-сервисов сможет
устанавливать подключение с конечными точками .NET Service Bus. Основной недостаток HTTPпривязок ретрансляции – большие затраты на обработку на прослушивающем сервисе.2
Выбор между различными HTTP-привязками ретрансляции производиться, главным образом, на
основании стиля создаваемого сервиса (REST или SOAP) и того, какие дополнительные протоколы
веб-сервисов предполагается поддерживать (WS-*). Для обеспечения поддержки REST,
используется WebHttpRelayBinding. Для поддержки SOAP имеется несколько вариантов. Привязка
BasicHttpRelayBinding подойдет при построении базового профиля, совместимого с сервисами
SOAP, а привязки WSHttpRelayBinding/WS2007HttpRelayBinding – для расширенных сервисов на
базе SOAP, использующих многоуровневые протоколы WS-*.
1
NetEventRelayBinding, главным образом, ориентирована на сценарии интеграции приложений и в настоящее время
оптимизирована для небольшого числа подписчиков на событие (до 10). Она не рассчитана на обработку
пользовательских сценариев с существенно большей базой подписчиков. Также в CTP-версии все решения могут
обеспечивать одновременное прослушивание максимум 5 конечных точек.
2 Канал связи HTTP в настоящее время оптимизирован для передачи больших объемов данных со средними частотами
запросов, но не для сценариев с большой частотой запросов.
В области безопасности Microsoft рекомендует в полной мере использовать преимущества,
предлагаемые методиками обеспечения безопасности на базе сообщений путем подписи и
шифрования сообщений, передаваемых через сервис ретрансляции («гибридный» режим,
описываемый в разделе «Управление доступом»). Модель безопасности при ретрансляции
прекрасно сочетается с WS-Security, обеспечивая, таким образом, гарантию конфиденциальности
и защиты от повреждения или подделки. Сервис ретрансляции не читает и никоим образом не
касается данных тела сообщений, он только просматривает URI и, в некоторых случаях, заголовки
WS-Addressing, чтобы определить, как ретранслировать сообщение.
С появлением очередей .NET Service Bus стала возможна реализация сценариев асинхронной
связи или связи в отсоединенном режиме, при которых отправители и получатели не всегда
выполняются одновременно. Они также позволяют реализовывать «гибкие» требования по
пропускной способности, когда отправители и получатели обрабатывают сообщения с разной
скоростью. Поддержку архитектуры публикации/подписки обеспечивают маршрутизаторы .NET
Service Bus (их можно сочетать с очередями для надежности). Эти два примитива обмена
сообщениями открывают целую гамму новых возможностей при работе с .NET Service Bus.
Последнее важное замечание – CTP-версия .NET Service Bus, вышедшая в марте 2009, не
предоставляет поддержки размещения локальных WCF-сервисов в IIS/WAS. Как упоминалось
ранее, процесс локального сервиса отвечает за установление отношения с сервисом
ретрансляции. Поскольку сервисы IIS/WAS используют модель активации процессов, процесс не
запускается до поступления первого сообщения. Это представляет дилемму при использовании
.NET Service Bus. Microsoft активно работает над решением для будущей версии, но в CTP-версии
следует избегать размещения в IIS/WAS при использовании .NET Service Bus.
Заключение
.NET Service Bus обеспечивает безопасную основанную на стандартах среду обмена сообщениями
для связи приложений через Интернет, позволяя в случае необходимости обходить сложные
преграды, создаваемые межсетевыми экранами и NAT. Он состоит из глобальной системы
присваивания имен, доступного для просмотра реестра сервиса, многочисленных опций обмена
сообщениями и подключения, а также механизма управления доступом на базе утверждений.
.NET-разработчики могут воспользоваться преимуществами .NET Service Bus, просто применяя
новые привязки WCF. Все остальное, что касается WCF-кода, остается абсолютно неизменным. В
конечном счете, среда обмена сообщениями, предлагаемая .NET Service Bus, устраняет многие
препятствия на пути претворения в жизнь технологии ПО + сервисы.
Дополнительные ресурсы
Ниже представлены ссылки на некоторые ресурсы, которые помогут продолжить изучение в
области Microsoft® .NET Services в целом и .NET Service Bus в частности.
Пакеты документов по Microsoft® .NET Services




Введение в Microsoft .NET Services для разработчиков
o http://go.microsoft.com/?linkid=9638347
Руководство по Microsoft® .NET Service Bus для разработчиков (данный документ)
o http://go.microsoft.com/?linkid=9638348
Руководство по Microsoft® .NET Access Control Service для разработчиков
o http://go.microsoft.com/?linkid=9638349
Руководство по Microsoft .NET Workflow Service для разработчиков
o http://go.microsoft.com/?linkid=9638350
Ресурсы .NET Service Bus




Azure Services Platform
o http://www.microsoft.com/azure/services.mspx
Реестр для Azure Services
o http://www.microsoft.com/azure/register.mspx
Microsoft® .NET Services
o http://www.microsoft.com/azure/netservices.mspx
Java SDK для Microsoft .NET Services
o http://www.jdotnetservices.com/
Об авторе
Аарон Сконнард (Aaron Skonnard) является соучредителем Pluralsight, ведущим разработчиком
учебных курсов Microsoft .NET, как обычных, так и онлайн. Аарон является автором
многочисленных книг, статей и официальных документов, а также курсов Pluralsight по REST,
Windows Communication Foundation и BizTalk. Уже много лет он занимается разработкой курсов,
делает доклады на конференциях и обучает разработчиков по всему миру. Его можно найти по
адресу http://pluralsight.com/aaron.
Благодарности
Основная благодарность за наполнение данного документа Клементу Вастерсу (Clemens Vasters).
Его выступления на последних PDC и MIX, публикации в блоге и другие работы легли в основу и
сформировали концепцию данного документа. Спасибо Клементу за его готовность помочь и
иллюстрации, которые значительно упростили мою задачу. Кроме того, спасибо Анджану Дасу
(Anjan Das) и Ронену Хайлевичу (Ronen Hilewicz) за их отзывы при работе над этим документом.
Download