Using Windows Azure Service Bus Messaging.






4.94/5 (27 votes)
This article describes consuming Windows Azure Service Bus by WCF and WF Technologies.
Contents
Introduction
The Windows Azure AppFabric Service Bus September 2011 (version 1.5) release introduces enhancements to the Service Bus such as "brokered" messaging capabilities, through namespace entities represented by queues, topics and subscriptions. The Brokered Messaging infrastructure enables to build an Event-driven distributed Service Oriented Architecture, Distributed Asynchronous Cloud Notifications and Intra-Application Messaging. Basically, it can be useful anywhere where a loosely decouple messaging is required such as Queuing and Publish-Subscribe messaging across both on-promises and cloud targets.
From the abstraction point of the view, the Azure Service Bus represents a logical connectivity between the event sources and their consumers using a loosely decouple model. The consumers need to subscribe their interest to the Service Bus in prior of receiving a specific event interest. This metadata (subscriptions) represents a logical connectivity for event interest; they are stored on the cloud a managed by tools and/or specific client applications.
The following picture shows an Azure Service Bus abstraction:
The above picture shows very high abstractions to hide an AppFabric infrastructure, entities and etc. to show the basic model of the Azure Service Bus. Basically, there is a Publisher of the event interest, Subscriber for receiving this interest and Administrator to assign a logical connectivity between the Publisher and Subscriber in the secure manner. The Service Bus is highly available, scalable, multi-tenant service for connecting clients such as Publishers, Subscribers, Admin, etc. The model of the logical connectivity is stored in the SQL Azure. Currently, the Azure Service Bus model supports Namespace entities such as Queue, Topic and Subscription.
The following picture shows a screenshot of the WindowsAzurePlatform Service Bus Admin Tool:
As you can see, the Subscription-1 account has one Service Bus
Namespace scope named as rk2011
. As I mentioned earlier, the Service Bus is
multi-tenant model, where Namespaces are logical isolated entities, in other
words, Publishers, Subscribers and admin tools are visible each to other based on
the Namespace scope.
The following picture shows next drill-down level of the Service Bus abstraction:
Basically, the above picture shows service-client architecture. The current release
version of the Azure SDK 1.5 includes many "horse-worker" classes and methods to
simplify access to the Service Bus Service. The Brokered Messaging feature on
the Azure Service Bus is built on the top of the WCF paradigm using full-duplex
connection-oriented sessions between the Sender and Receiver (Listener) with a
bi-directional communication (Microsoft.ServiceBus.Messaging.SBmp
internal classes) From the application (business) layer, the
messaging between Sender and Receiver is One-way supporting unicast and
multicast datagram distribution.
This article is focusing on consuming Azure Service Bus by WCF and WF Technologies. I will discuss how it can be used in the transparent manner as part of the Logical Model Connectivity. In the References, you can find more details about the Service Bus entities and their programming using an API methods and RESTful from the Microsoft.ServiceBus.Messaging Namespace. I strong recommend to read Service Bus Brokered Messaging Performance - Best Practices Guide.
Let's describe the major entities of the Azure Service Bus focusing on the WCF/WF usage.
Brokered Message
The Brokered Message (BM) is a fundamental entity in the Service Bus
Messaging infrastructure. Its conceptual design is similar to WCF Message.
The BM is holding sys properties such as Label
, TimeToLive
,
CorrelationID
, etc. for message control flow and user
application
specific properties and of course the body (message payload). The sys
and user
properties are packaged to the bag under
the name BrokeredMessageProperty
(BMP) The important thing is
that this BMP bag can flow between the Business-To-Business layers. The following
picture shows a WCF Message for ServiceBus Messaging:
The BrokeredMessageProperty
bag is attached to the WCF Message
via its Properties collection. Having the BMP out of the message body allows us
to use it without serializing/deserializing the business payload by Service Bus
infrastructure. Note, that the name of the key in the collection is
BrokeredMessageProperty
.
Adding BMP into the WCF Message Properties collection is very straight forward like it is shown in the following code snippet:
using (OperationContextScope scope = new OperationContextScope((IContextChannel)channel)) { var bmp = new BrokeredMessageProperty() { Label = "HelloCloud" }; bmp.Properties.Add("abcd", (long)12345); bmp.Properties.Add("id", Guid.NewGuid()); OperationContext.Current.OutgoingMessageProperties.Add(BrokeredMessageProperty.Name, bmp); channel.Message(text); }
The above example is for adding the BMP in an imperatively way using an
OperationContextScope
for channel (proxy). The following picture shows
this process graphically. The point is that the Sender/Publisher is a
producer of the BrokeredMessage
to the Azure Service Bus. In other
words, the WCF Message + BMP are converted into the BrokeredMessage
.
This task is implemented by custom channel for NetMessagingTransport
included in the Azure SDK 1.5.
The behind the above picture is implementation of the
ServiceBusOutputChannel
, where the wcfMessage is converted to
BrokeredMessage and sent it by SbmpMessageSender
to the Service Bus
channel. The following code snippet from .NetReflector shows this logic in the
Microsoft.ServiceBus.Messaging.Channels.ServiceBusOutputChannel
:
public SendAsyncResult(ServiceBusOutputChannel outputChannel, Message message, TimeSpan timeout, AsyncCallback callback, object state) : base(callback, state) { this.outputChannel = outputChannel; outputChannel.AddHeadersTo(message); outputChannel.TraceSendingMessage(message); BrokeredMessage message2 = null; try { message2 = outputChannel.ConvertToBrokerMessage(message, out this.bufferToReturn); IAsyncResult result = outputChannel.MessageSender.BeginSend( new BrokeredMessage[] { message2 }, timeout, base.PrepareAsyncCompletion(onSendComplete), this); if (base.SyncContinue(result)) { base.Complete(true); } } catch (MessagingException exception) { // ... throw FxTrace.Exception.AsError(exception2); } catch (Exception) { // ... throw; } }
That's great. But do I need to modify my existing WCF Sender/Publisher for Azure Service Bus Messaging?
Well, it is not necessary, this article gives you a solution for adding a
BrokeredMessageProperty
declaratively using a config file and
custom EndpointBehavior
. The following code snippet shows this
feature in the code:
serviceEndpoint.Behaviors.Add(
new RKiss.Activities.Azure.Messaging.MessagePropertyActionEndpointBehavior()
{
Expression = "SET sys.Label='HelloCloud'; SET abcd=12345; SET id=newid()"
});
As you can see, this custom endpoint behavior implements an Action feature based
on the SqlExpression. The above example will setup a message label (sys property) and
couple user properties such as abcd
and id
with a
new Guid value. Note, that the BMP
is important for
message processing, for example, based on the user properties the message can be
forwarded to the subscriber, etc. More details can be found later in the
usage examples of this article.
Queue Entity
The Queue Entity represents a logical connectivity between the producer and consumer ends. It's point to point pattern connectivity. The concept is similar to the on-promises MSMQ Technology. The following picture shows this basic concept:
The Sender sending a BrokeredMessage
to the specific queue from
where the message can be pulled by its Receiver. There are advanced messaging
features such as schedule time, time to live, session capability, etc.
More details can be found in the References. Basically, this messaging can be
used for migrating NetMsmqBinding
configuration to the
NetMessagingBinding
(Azure Service Bus) in the transparent manner, just
by updating the config file. In some cases, during this migration we can use better
pattern, for example, using SchedulerEnqueueTimeUtc
property
allows sending a message to the queue in the specific time, which can be
useful for retry mechanisms.
As the above picture shows, there are multiple ReceiverN
for the
same queue. In this scenario, the message will balance between the receivers in round-robin manner, which is perfect use for IIS/WAS/WebRole hosting. Note,
the receiver service on the hosting environment must have Auto-Start enabled.
The following code snippet shows example of receiver configuration on the
queue 'Queue1
':
That's great. As you can see, the above configuration will "plug-in" WCF
Service to receiving a message from the Azure Service Bus Queue. All the magic work
is done in the WCF paradigm using its extension such as
netMessagingBinding
and transportClientEndpointBehavior
.
This capability allows building a logical connectivity stored in the Repository
and physically deployed to the target based on the deployment model.
Topic Entity
The Topic Entity represents a logical connectivity for event interests in the
specific Namespace. This is a Publish/Subscribe (Pub/Sub
) pattern connectivity,
where sources publish an event interest on the logical channel known as Topic
and consumers will receive it based on their interest. This connectivity pattern
enables us to build an event-driven distributed architecture where producers and
consumers are loosely decoupled and disconnectable.
The following picture shows the topic-based messaging concept to see a fundamental difference from the previous, queue-based messaging:
As you can see, the Publisher sends a BrokeredMessage
to the
Namespace/Topic virtual channel without any knowledge of its consumers in the
loosely decouple manner. Publishers can decide on a lifetime of the sent message
such as TimeToLive
, SchedulerEnquueTime
, etc. The
application can mark the message with a source event interest to identify
a specific event. In the loosely decouple manner, there are Subscribers registered
to the Topic which represents a consumers of the event interest. Registration
process is known as subscribing interest on topic.
Subscription Entity
In the Topic Model, this abstraction is represented by Subscription
.
Every Subscriber must have a Subscription. This entity represents a logical
connectivity between the Publisher and Subscriber on the specific Topic channel.
Based on the Subscription, the Subscriber gives an interest for Topic to receive
a message (described by RuleDescription) and some information for message control flow in the case of
exceptions, batch operation, etc.
As I mention earlier, to receive a copy of published message, Subscriber needs
to subscribe its subscription to the specific Topic. The Subscriptions can be
empty, default with one RuleDescription
or with multiple
RuleDescriptions.
The following picture snippet shows this abstraction, where Subscription is a
collection of the RuleDescription
entities:
To obtain the copy of the BrokeredMessage from the Topic channel, the RuleDescription
within the Subscription must be succeeded. In other words, based on
the Subscription Filter(s), the message copy is delivered to the Subscriber. The
RuleDescription
in the Azure Service Bus Messaging has built-in two features,
such as Filter and Action. Both are based on
SqlExpression and have been implemented with certain limitation to the
BrokeredMessage
entity, for example: scope of the property can be sys
and/or user
.
From the Topic point of the view, the message is delivered only if we have
valid subscription during the message lifetime. Basically, if we don't have any
valid Subscribers to the Topic, messages will live there based on their
TimeToLive
property. In other hand, the Topic can have many (based on the
Quotas such
as 2000 subscriptions per Topic) empty subscriptions, default subscriptions -
TrueFilter
(one default RuleDescription) or subscription with multiple
RuleDescriptions
.
As I motioned earlier, the Topic channel is loosely decouple model, where Subscribers and Subscriptions are independed of each other. In other words, Subscription can be created and registered by Subscriber or any application component and/or management portal site. The Subscription can be static or dynamicly created on the fly.
Keep in mind, when Subscription is unregistered (deleted) from the Topic, its active Subscriber is disconnected, and it will be required to reconnected in order to renew the subscription. In the case of the dynamic subscription, when subscriber will create its own subscription, it is not a problem, but for static subscription needs to be handle it.
Empty Subscription vs. Default Subscription
As we know, the Subscriber needs to subscribe an interest to the specific Topic. But there is a special case when the subscriber (or management) doesn't know in advance of this interest. Therefore, it is beneficial to use an Empty Subscription, which will allow creating the Subscriber for Topic and its Listener on the Empty Subscription.
When Subscription is created automatically, it is created for one (default)
RuleDescription
. If there is no filter expression (default constructor),
the TrueFilter
is applied as a Default Subscription. In this case,
every published message delivers its copy to this Subscriber. Keep in
mind this feature when the multicast messaging is required.
By deleting the default RuleDescription
in the Default Subscription, we can
obtain an Empty Subscription
without any glitches on the active
Subscriber. Deleting RuleDescription in the Subscription can be done by its
Subscriber (one time message receiver) or other components.
In the opposite
process, the RuleDescription
can be added into the Subscription. Note, that
each
Filter in the RuleDescription
must match for message (copy)
delivery to its
Subscriber.
RuleDescription
The BrokeredMessage received by Topic channel is flowing via each Subscription for checking its interest. This interest is declared by the Filter Entity. The Service Bus Messaging has built-in few filters such as TrueFilter, FalseFilter, CorrelationFilter and SqlFilter for generic SQL92 Expression. When the filter match is true, the RuleDescription offers to execute its Action. The default action is EmtyRuleAction and for custom action, SqlRuleAction can be used using the SQL92 expression.
The scope of the filter and action is BrokeredMessage entity. The SqlExpression supports only two scopes of the BrokeredMessage such as its properties (scope name is sys) and the user scope (default scope) declared in the BrokeredMessage.Properties collection.
Filter example: "sys.Label='Order" AND TicketID=12345"
Action example: "SET sys.Label='Order'; SET abcd=12345; REMOVE TicketID; SET flag=TRUE"
Balancing vs. Multicasting (Multiple Subscriptions)
In the Queuing, we saw the by sharing a queue entity we can balance message between queue receivers in the round-robin manner. We have the same feature at Subscription, when the Subscribers are using the same Subscription. That's fine and very useful for load-balancing purposes. But wait a moment, what will happen when Subscription will have the same Filter expression?
Well, we can get a new pattern connectivity such as multicasting. The following picture shows these two scenarios:
and their abstraction is shown here:
Basically, we can say, that "sharing" subscriptions is for balancing and "sharing" filters for message multicasting. Note, that "sharing" is used for logical explanation. I would be nice to have a Topic Model that supports referencing entities and sharing them in the Repository, but current release doesn't support it.
Addressing Queue, Topic and Subscription
The following are examples of addressing Queue, Topic and Subscription in the connected Namespace:
Addressing can also use a branching structure, for example: /myTopics/myTopic
,
etc. Usage of addressing can be see in the following configuration
example for receiver, publisher and subscriber:
It is a straightforward standard endpoint configuration and the interesting point is
the subscriber endpoint. As you can see, the base address is for addressing Topic
entity and the listenUri
is addressing for its subscription. Each
endpoint must have a behaviorConfiguration
for credentials.
That's great. We can create Namespaces, Topics and Subscriptions in the Windows Azure Platform for our subscription. From the business model point of the view, we can look at on the Service Bus like abstraction of the connectivity, where business entities are logically connected and driven by the metadata. We can consider Service Bus such as Namespace, Queue, Topic and Subscriptions (NQTS) as part of this metadata as well. In the logical model, we can declare a logical subscription without knowledge of the physical topology of the Pub/Sub model. Basically, the Subscriber interested in the event (message) in the business model can be decomposited into multiple topics, etc. We can help our business model by declaring NQTS for public and private scope. However, our logical business model stored in the Repository will need to be physical deployed to the target and the deployment model will need a mapping process for specific physical entities of the target.
To end this thought, the current version of the Azure Service Bus Messaging doesn't support "wildcard" feature for subscription or publisher for multiple topics. In the current version, we can consider each subscription as tightly coupled with a specific one Topic. It is the same Publisher side, when on event interest is distributed only for specific Topic, not across multiple topics. It will be nice to have support like subscription for multiple topics - wildcard subscription, which will simplify our mapping from the business model.
However, we can build (on top of the fundamental Service Bus Entities) advanced hierarchy such as "wildcard subscription", publishing over multiple topics, namespaces, creating public and internal gateways, bridges, etc. The concept is very simple, subscribing interest to the specific topic and distributing it to some other one, or multicasting an event interest for multiple topics.
In the following section I will describe this pattern scenario using a WCF RoutingService, which basically represents a Subscriber/Publisher component driven by metadata located in the config file (endpoints, routing table, filters, etc.). Note that this service has a built-in capability to update a routing table and outbound clients remotely on the fly.
WCF4 Routing Service on the Service Bus
The WCF RoutingService
is a perfect solution for building a
gateway and/or bridges for Service Bus. For this scenario, it can be fully
transparent and declaratively configured. The RoutingService
supports
both contracts for Service Bus such as ISimplexDatagramRouter
and
ISimplexSessionRouter
.
The following picture shows one possible
example, where the event interest from one Namespace/Topic must be delivered to
other Topic channel (bridge pattern) and also some "legacy" producer/consumer
that wants to be part of the Service Bus in the Pub/Sub scenario (gateway pattern).
In the above example, the RoutingService
can be configured for
receiving two kinds of messages such as BrokeredMessage
and
Message
. This is a straightforward configuration, setting an address on
the Topic channel and Listener on Subscription. For "legacy" Publisher, we can
use a standard addressing. That's all for inbound messages. For outbound
messages such as "legacy" Subscribers and Topic channel (2) we can setup a
client endpoint with addressing based on the target (service or Topic).
Now, we need to configure a Routing Table which will be "connect"; - forward the inbound message to the specific outbound channel. For simple forwarding messages from Publishers to Subscribers ("legacy" connectivity), we can use standard built-in message filters (Action, XPath, EndpointName, etc.), but for BrokeredMessage we need a custom message filter based on BrokeredMessageProperty with capability to declaratively setup this property bag for outbound message to the Service Bus. The other option is to forward an inbound BrokeredMessage without the filtering on BMP bag, for example: EndpointName, Action, Address. etc.
OK, without any implementation details (it will be described later) the following configuration allows filtering inbound message from the Service Bus and generating BMP bag for outbound message to the Service Bus:
The messagePropertyAction
is a custom endpoint behavior
for message inspector to update outgoing message properties for BMP bag. The
other element is a custom MessageFilter to execute SqlExpression
on the incoming message with a BMP bag.
This is exciting, we can have a generic solution for gateway and bridge from/to Service Bus which can be very easily deployed on the cloud and used as an Azure Storage Blob for routing table - see more details about this solution in my previous article RoutingService on Azure. This article gives you a solution how we can mediate a message to/from the Service Bus using a WF Technology.
Note, that the RoutingService has a built in capability for backup message delivery, which can also be used it in our scenario.
Based on this concept described in the above example, the RoutingService can be configured for bridging messages across multiple Namespaces and Topics. The RoutingService can have multiple endpoints configured for different Topics and Subscriptions. The following picture shows this abstraction:
Another advanced feature of the RoutingService for Service Bus. As we know, the current release Service Bus Quotas limited number of subscription on the Topic. The following picture shows how we can work around this limitation:
The concept is very simple and straightforward. The RoutingService can be subscribed to the Topic and based on the FilterTable rules can forward a message to multiple clients in the multicasting manner.
One more advanced feature of the RoutingService on the Service Bus. The following picture shows subscribing a RoutingService with Subscription contains multiple RuleDescriptions. The inbound messages received by this Subscription (from each Rule) can be forwarded to the proper outbound channel based on the custom message filter for BrokeredMessageProperty bag driven by Routing (Filter) Table.
Publisher
Publisher represents a sender (producer) of the event interest. In the
Pub/Sub pattern, the Publisher is loosely decoupled from the consumers, therefore
its publishing is addressed to the virtual channel which in the Azure Service
Bus Messaging is represented by Topic. The Publisher supports only one message
exchange pattern such as One-Way operation (Fire&Forget) without the
SessionMode.Required
, therefore
the Publisher WCF channel can be implemented IOutputChannel
channel
only. The following
example shows a generic (untyped) contract for Publisher:
[ServiceContract] public interface IGenericOneWayContract { [OperationContract(IsOneWay = true, Action="*")] void Message(System.ServiceModel.Channels.Message msg); }
Let's look at how we can create a Publisher for Topic. I will demonstrate it
by WF Technology using a declarative way. Basically, in simple case, when the event
interest can be signed statically in the BMP bag, there is no difference for
proxy channel (sender), the BMP bag can be created declaratively like it has
been described earlier, using the custom endpoint behavior (messagePropertyAction
).
When the BMP bag is created dynamically, based on the business
model, we need a mechanism how to add it to the outgoing message properties.
The following example shows adding BMP bag to the untyped message created by custom activity CreateMessage based on the Contract-First Model and then sending it by activity Send:
The above picture shows two custom activities to simplify this message mediation, the first one can be found in my article WF4 Custom activities for message mediation and the other one is part of this article and it will described in detail later on. So, these two custom activities will create a complete message for sending by Send Activity, including headers, properties, body, etc. using a full declaratively way for any element and entity.
The other way, when we want to use strong type message contract, we can use the following pattern based on the injecting a BMP bag in the message inspector. The following picture shows this case:
Again, we need some help with this extension, that's why here is a custom
activity SendScope
which is basically wrapper for Send
Activity.
The Message
mediation for Service Bus such as adding a BMP bag to the message properties is
very simple and straightforward. First step is creating this BMP bag and the
second one is to assign to the Properties in the SendScope activity. This custom
activity is included in this article download.
Note: The WF4 Send Activity didn't allow to add a custom endpoint behavior declaratively. There is only one way how it can be done such as explicitly setup the Send.EndpointConfigurationName property by name of the client endpoint from the config file (e.g. topic). It will be nice to have a capability for injecting a custom endpoint behavior using a custom wrapper around the Send activity in the next release WF 4.5.
AssignBMP<T>
AssignBMP<T> is a custom activity for creating an instance of the
BrokeredMessageProperty
object and assigning it to the
System.ServiceModel.Channels.Message.Properties
or
Microsoft.ServiceBus.Messaging.BrokeredMessageProperty
declared variable.
The design and implementation of this custom activity is based on BMP class type for properties in the sys scope and one collection of the user parameters. This BMP bag is required by Service Bus infrastructure for a message control flow and additional user specific data between the producer and the consumers. The custom AssignBMP activity simplifies a message mediation process.
Subscriber
The Subscriber represents a receiver (consumer) end point of the BrokeredMessage. In
the case of no interesting BMP in the service mediation, the Subscriber is a
regular Receiver. In the other case, when the service mediation needs a BMP bag
(additional business data), we need to obtain it from the custom activity OperationContextScope
. This is a Receiver wrapper to inject a value of the
OperationContext.Current to the workflow thread scope, which will get our BMP bag from the IncomingMessageProperties collection.
The Service Bus supports for Subscription and Queue two message
exchange patters such as IInputChannel
and IInputSessionChannel
. Once these
Service Bus entities have been declared for session (required), the Subscriber (Receiver)
needs to implement a session-aware contract. The following is an example of the untyped contract for sessionful pattern:
[ServiceContract(SessionMode = SessionMode.Required)] public interface IGenericOneWaySessionContract { [OperationContract(IsOneWay = true, Action="*")] void Message(System.ServiceModel.Channels.Message msg); }
The example of the Subscriber declared by xaml is shown in the following picture:
This article download contains an AzureMessagingActivityPack solution, with extensions to the BrokeredMessageProperty
and
MessageProperties
classes. The above GetBrokeredMessageProperty
method is one of them to hide same details.
The Subscriber can be configured in the config file. The above example shows this service Subscriber2 config section, where its endpoint has an address to the Topic channel and listener is addressed on the subscription address.
Subscriber and Multiple Publishers
The following scenario shows a mediator where we have one Subscriber and
multiple Publishers. This mediator is an example of the event driven virtual
storage. Mediator (StoragePublisher
) has a responsibility to put a
resource to the virtual storage (for example: Azure Blob Storage), publishing
this event to the Topic channel and triggering a cleaner mechanism sending an
event message to the queue. This message is marked with ScheduledEnqueueTimeUtc
property which represents a resource TimeToLive. The receiver of this message
will clean-up a specific resource in the Storage.
This is an example of the pattern where consumers will pull-up a resource from the rental Storage. Instead of multicasting a heavy business payload (a resource body), the service mediator will send notification (short message) to the unknown number of consumers via the Topic channel.
The following picture shows a BMP bag:
For event-driven storage demonstration, a custom activity Microsoft.Activities.Azure.Storage.PutBlob is used. As you can see, the design is very straightforward using custom activities for putting a resource to Azure Storage and publishing events to the Azure Service Bus Topic. Note that this process is not under TransactionScope like we can have on promises environment SQL/MSMQ and it should be covered by some watchdog mechanism.
All plumbing job is done in the configuration file. The following code snippet shows this example:
<configuration> <appSettings> <add key="AzureStorageConnectionString" value="DefaultEndpointsProtocol=https;AccountName=MY_ACCOUNT;AccountKey=MY_ACCOUNT_KEY"/> </appSettings> <system.serviceModel> <services> <service name="Subscriber3"> <endpoint address="sb://MY_NAMESPACE.servicebus.windows.net/worker" listenUri="sb://MY_NAMESPACE.servicebus.windows.net/worker/subscriptions/image12" binding="netMessagingBinding" contract="IGenericOneWayContract" behaviorConfiguration="sharedSecretCredentials" /> </service> </services> <client> <endpoint name="TopicPublisher" address="sb://MY_NAMESPACE.servicebus.windows.net/worker" binding="netMessagingBinding" contract="IGenericOneWayContract" behaviorConfiguration="sharedSecretCredentials" /> <endpoint name="QueuePublisher" address="sb://MY_NAMESPACE.servicebus.windows.net/search" binding="netMessagingBinding" contract="IGenericOneWayContract" behaviorConfiguration="sharedSecretCredentials" /> </client> <behaviors> <endpointBehaviors> <behavior name="sharedSecretCredentials"> <transportClientEndpointBehavior credentialType="SharedSecret"> <clientCredentials> <sharedSecret issuerName="MY_ISSUER_NAME" issuerSecret="MY_ISSUER_SECRET" /> </clientCredentials> </transportClientEndpointBehavior> </behavior> </endpointBehaviors> <serviceBehaviors> <behavior> <serviceMetadata httpGetEnabled="true"/> <serviceDebug includeExceptionDetailInFaults="false"/> </behavior> </serviceBehaviors> </behaviors> <extensions> <behaviorExtensions> <add name="transportClientEndpointBehavior" type="Microsoft.ServiceBus.Configuration.TransportClientEndpointBehaviorElement, Microsoft.ServiceBus, Version=1.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/> </behaviorExtensions> <bindingElementExtensions> <add name="netMessagingTransport" type="Microsoft.ServiceBus.Messaging.Configuration.NetMessagingTransportExtensionElement, Microsoft.ServiceBus, Version=1.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/> </bindingElementExtensions> <bindingExtensions> <add name="netMessagingBinding" type="Microsoft.ServiceBus.Messaging.Configuration.NetMessagingBindingCollectionElement, Microsoft.ServiceBus, Version=1.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/> </bindingExtensions> </extensions> </system.serviceModel> </configuration>
As you can see, there is an appSettings section for connection string to Azure
Storage and the rest is a configuration for one Subscriber and two Publishers
and of course, we have to put extensions for Service Bus such as transportClientEndpointBehavior
,
netMessagingTransport
and netMessagingBinding
.
That's all for the introduction. I hope you get the picture of the Service Bus position in the logical connectivity model between producers and consumers based on the WCF/WF Technology. I didn't describe a Service Bus management tools, creating Entities such as Queue, Topic, Subscription, etc. More about that, including their API programming can be found in the References. Also, I assume that you have a working knowledge of Windows Azure Platform and WCF/WF Technology.
OK, let's continue, there is lots of stuff to show before we getting into the usage and the test part.
AzureMessagingActivityPack
The AzureMessagingActivityPack is a small package of the custom activities and class extensions for message mediation from/to Azure Service Bus Messaging. Its solution with full implementation is included in this article download. Basically, there are two groups, such as:
1. Endpoint and Class Extensions
This extensions have been created to simplify access and manipulation with
BrokeredMessageProperty
Bag. It can be used imperatively or
declaratively in the xaml or config file.
There are two classes extension such as MessagePropertiesExtension
and
BrokeredMessagePropertyExtesion
. The following example shows some
of the usage.
var bmp = OperationContext.Current.IncomingMessageProperties.GetBrokeredMessageProperty(); long prop1 = bmp.RequiredItem<long>("prop1"); string prop2 = bmp.RequiredItem("prop2", "Missing {0} in the bag", "prop2"); XElement xbmp = bmp.ToXml(); Trace.WriteLine(bmp.ToXml().ToString()); var bmp1 = message.Properties.GetBrokeredMessageProperty("Missing BMP bag"); string prop3 = message.Properties.GetBrokeredMessageProperty().RequiredItem("prop3"); bmp1.Put(message2.Properties);
MessagePropertyAction
This is a client endpoint behavior extension to inject a BrokeredMessageProperty bag for outgoing message in the config file. Having this extension, we can "fire event interest" from the "legacy" Publisher to the Service Bus Topic channel.
public class MessagePropertyActionClientInspector : IClientMessageInspector { public string Expression { get; set; } void IClientMessageInspector.AfterReceiveReply(ref Message reply, object correlationState) { // nothing to do } object IClientMessageInspector.BeforeSendRequest(ref Message request, IClientChannel channel) { if (request.Properties.ContainsKey(BrokeredMessageProperty.Name)) { var bmp = request.Properties[BrokeredMessageProperty.Name] as BrokeredMessageProperty; var sra = new SqlRuleAction(this.Expression); sra.Preprocess().Execute(bmp.Message); } else { var bmp = new BrokeredMessageProperty(); var sra = new SqlRuleAction(this.Expression); var bm = sra.Preprocess().Execute(bmp.Message); request.Properties.Add(BrokeredMessageProperty.Name, bmp); } return null; } }
The core of the above inspector is the execution of the SqlExpression on the BrokeredMessage object.
The following code snippet shows its usage in the config file:
<behaviors> <endpointBehaviors> <behavior name="sharedSecretClientCredentials"> <transportClientEndpointBehavior credentialType="SharedSecret"> <clientCredentials> <sharedSecret issuerName="MY_ISSUER_NAME" issuerSecret="MY_ISSUER_SECRET" /> </clientCredentials> </transportClientEndpointBehavior> <!-- Set BrokeredMessageProperty Bag --> <messagePropertyAction enable="true" expression="SET sys.Label='Router';SET sys.TimeToLive='00:01:00';SET id=newid()"/> </behavior> </endpointBehaviors> </behaviors>
It can be used programmatically, as well:
serviceEndpoint.Behaviors.Add(
new RKiss.Activities.Azure.Messaging.MessagePropertyActionEndpointBehavior()
{
Expression = "SET sys.Label='Router'; SET sys.TimeToLive='00:01:00'; SET id=newid()"
});
BrokeredMessageFilter
The BrokeredMessageFilter has been created for RoutingService to customize a message filtering on the BrokeredMessageProperty bag. It is a valuable extension for RoutingService Subscriber to forward a message to the proper outbound channel.
public class BrokeredMessageFilter : MessageFilter { public string Expression { get; set; } public BrokeredMessageFilter(string expression) { this.Expression = expression; } public override bool Match(System.ServiceModel.Channels.Message message) { if (message.Properties.ContainsKey(BrokeredMessageProperty.Name)) { var bmp = message.Properties[BrokeredMessageProperty.Name] as BrokeredMessageProperty; var filter = new SqlFilter(this.Expression); bool bMatch = filter.Preprocess().Match(bmp.Message); return bMatch; } else { return false; } } public override bool Match(System.ServiceModel.Channels.MessageBuffer buffer) { throw new NotImplementedException(); } }
The core of the above filter is executing a SqlFilter on the BrokeredMessage object. The following code snippet show usage this custom filter in the config file (routing section):
<filters> <clear /> <filter name="MatchForSubscriber1" filterType="Custom" filterData="image=111 AND sys.Label='Hello Cloud'" customType="RKiss.Activities.Azure.Messaging.BrokeredMessageFilter, RKiss.Activities.Azure.Messaging" /> </filters>
Note, that the above extensions are very helpful for connecting "legacy" Pub/Sub producer and consumers to the Azure Service Bus via modification of their config files.
2. Custom Activities
AssignBMP<T>
AssignBMP<T> is a custom activity to create a BrokeredMessageProperty
bag and assign it to the T type which can be accepted only for
System.ServiceModel.Channels.Message
or
Microsoft.ServiceBus.Messaging.BrokeredMessageProperty
types. Its design is
based on the BrokeredMessageProperty class, where Service Bus properties (sys
scope) and application (user) properties in the Parameters collection (user
scope) are found:
Collection of the Parameters can be declared in the pop up dialog. The following picture shows an example of declaring different type of the user properties:
AssignBMP<T> is factorized for the required type T. The following code snippet shows these templates. It shows some examples of how we can predefine some common application properties in the collection of the parameters:
public class AssignBMPtoMessage : IActivityTemplateFactory { public Activity Create(DependencyObject target) { AssignBMP<Message> assign = new AssignBMP<Message>() { DisplayName = "AssignBMPtoMessage" }; assign.Parameters.Add(new KeyValuePair<string,InArgument>("myKey", InArgument<string>.FromValue("12345"))); return assign; } } public class AssignToBMP : IActivityTemplateFactory { public Activity Create(DependencyObject target) { return new AssignBMP<BrokeredMessageProperty>() { DisplayName = "AssignToBMP" }; } }
SendScope
SendScope is a generic custom activity for Send Activity to allow declaratively way create a binding of the Send activity and dynamically inserting a message headers and properties:
This custom activity will allow adding a BrokeredMessageProperty bag for typed message contract, when the workflow orchestration is based on the clr types (DataContract). Note, that for untyped message, the BMP can be assigned directly to the message properties collection.
Subscribe
This custom activity is to subscribe a subscriber event interest to the Topic channel. The result of this custom activity is creating a subscription with one RuleDescription (name = $Default) based on the Filter and Action SqlExpression.
Behind the Subscribe activity are API calls to the Service Bus, for checking existing subscription, then deleting (if Renew is required) and creating a new one. The current implementation of this custom activity is not full async process, only creating a subscription is done in the async manner, the others are sync process.
Note, that Azure SDK 1.5 doesn't support updating existing subscriptions. It
would be nice to have this feature, instead of always deleting and recreating
again and again. This process will impact all active subscribers relayed on this
renewed subscription. To avoid this glitch, I recommend to use Empty
Subscription and use API call for AddRule
to the subscription, in
other words, keeping a subscription alive.
Unsubscribe
This is a custom activity to delete a subscription from the Topic channel in the async manner. It is very lightweight activity with requirement for Configuration, Namespace, Topic and Subscription names. Note, by processing this activity all active subscribers for this subscription are logically disconnected from the Topic channel.
OperationContextScope
This custom activity is useful for Susbcriber (Receiver) mediator to obtain
operation context of the incoming message, which we need for getting a
BrokeredMessageProperty bag that is sent by the Service Bus. This is a generic custom
activity, originally created in the
WF Security Pack CTP 1
and slightly modified in my package. The concept is very simple and
straightforward such as creating an OperationContext
in the
workflow thread slot within its scope. To obtain a runtime OperationContext, implementation of the built-in message inspector interface such as System.ServiveModel.Activities.IReceiveMessageCallback and
System.ServiveModel.Activities.ISendMessageCallback is used.
That's all for this package. I didn't create a full WF wrapper around the Service Bus API. The above extensions are focusing on the producer and consumer sides, which is publishing and consuming an event interest, creating a subscriber and its subscription. For managing Service Bus, we can use Windows Azure Platform portal and/or 3rd party explorers, like upcoming new version Service Bus Explorer.
OK, let's take a coffee break, because we are going to go through difficult parts such as
Usage and Test
. I am assuming, you have a working knowledge of the
Windows Azure Platform.
Usage and Test
First of all, the following are prerequisites:
- Visual Studio 2010 Sp1
- Windows Azure SDK v1.5 (September 2011)
- Azure Storage Explorer (option, for one example - Test 3)
- WF Azure Activity Pack CTP 1 (option, for one example - Test 3)
- Windows Azure Platform account
- Http/s connectivity to the Internet
- Downloading package for this article
- Some Knowledge and experience for Windows Azure Platform, WCF and WF
Let's start with the Windows Azure Service Bus
Step 1. Create your Namespace on the Service Bus
Step 2. Create the following entities such as Queue and Topic in your Namespace scope
Step 3. Create Container 'box' in your Azure Storage Blob
(this is an option
for one test scenario - Test 3
)
Step 4. Download this article and open it with VS2010SP1.
You should see the following solution:
Basically, the solution is divided into two parts such as
AzureMessagingAcitivtyPack
and Test
. The first one is actually
a package of the
two assemblies to simplify consumption of the Service Bus. The usage of theses
assemblies is shown in the Test package. As you can see, the Test folder
contained different applications (scenarios) driven by WCF and WF Technologies
using imperative and declarative ways to create producers and consumers.
Note, that the solution has been developed and tested on the Windows 7.
Step 5. Compile solution
In this step, you should have successfully built with the provided exe programs such as ConsoleApplications, Management, Publishers and
PubSubRouter. All shortcuts are centralized into the ServiceBusTest
folder, which can be added to the Desktop.
Step 6. Updating config files
Please, replace the following values in all config files located in the Test folder with your account for Azure Service Bus and Storage:
MY_ISSUER_NAME, MY_ISSUER_SECREET, MY_NAMESPACE, MY_ACCOUNT and MY_ACCOUNT_KEY
Step 7. Create Subscriptions
Launch the SubscriptionManager
program to create our test
subscriptions:
This program has been created declaratively, using a workflow with a custom activity Subscribe. See its design in the following picture:
To verify the above subscriptions on the Service Bus, please launch the console program ManagingSubscriptionRules:
As you can see, we have three subscriptions, where the first one has a simple
test Action expression. Note, that this test program is able to add one
more rule into the subscription image12
, which we will need to demonstrate
later.
OK, now our test environment is ready for testing. But, one more comment. The Test Package also includes a simple message inspector for logging messages, including a BrokeredMessageProperty bag on the Console.
Test 1. Send message to the Queue.
This is a very simple test, the Sender will send a message to the Queue (Search) and the Receiver will retrieve the message from the queue. First (but not required) launch the Receiver console program:
and then the Sender console program:
You should see that the message has been received by Receiver:
Great, it's working. Now, you can launch one more Receiver and back to the Sender and press any key to send the message again. You will see that the message is balancing between the Receivers.
This test has been implemented declaratively within the config file. Please,
visit these config files (Sender and Receiver) for more details. As you can see,
migrating NetMsmqBinding
(MSMQ) to NetMessagingBinding
(Service Bus) can be straightforward and
simple.
The following code snippet shows part of the Sender configuration file. There is messagePropertyAction
element for setting BMP bag in the client
endpoint behavior:
Test 2. Publish message to the Topic
In this test scenario, we are going to fire (publish) an event interest in advance of the Subscriber, therefore, please launch the Publish console program. The following screen snippet will show up. You can see the wcf message (yellow color) and the BMP bag (green color) on the console screen. Note, that the message has TTL setup for 30 minutes.
Now, launch the Subscriber console program. You should see the following result on your Subscriber:
That's great, we can see a log message with BMP bag as well as the deserialized message in the service (white color).
Let's make more advance feature for this Pub/Sub scenario, where Subscriber
subscribed subscription image12
with one $Default Rule such as
image=111 or image=222
, that's why we received only one message.
Now, let's add one more Rule to this subscription. We can do so by using a ManagingSubscriptionRules console program, which has this feature built-in (hard coded for test purposes). Please, go back to the ManagingSubscriptionRules program and press the 'a' key. You should see the same result like it is shown in the following screen snippet:
Note, that this Rule (name=abcd)
has declared a RuleAction
for setting a user property Label
.
Now, we can back to the Publisher console program and send a message to the Service Bus Topic channel
by pressing a key (any key). This is a second message from the Publisher, therefore the counter value is 1. What is
interesting in this test is that fact that the Subscriber received two messages from
this subscription based on the successful expression of its RuleDescription.
You can also see that the second message has the BMP bag different than first one.
There is a result of the RuleAction such as SET Label = 'Hello Roman'
.
That's cool, you can come back later and modify the test code for your RuleDescription, launching more Subscribers (may be on a different machine), etc. to see the capability of Pub/Sub on the Azure Service Bus.
This test has been created programmatically, the following code snippet shows implementation of the Publisher:
try { // my Service Bus string issuerOwner = ConfigurationManager.AppSettings.Get("sbIssuerName"); string issuerSecret = ConfigurationManager.AppSettings.Get("sbIssuerSecret"); string namespaceAddress = ConfigurationManager.AppSettings.Get("sbNamespaceAddress"); string text = string.Format("[{0}] Hello Service Bus - {1}", counter, DateTime.Now); EndpointAddress topicAddress = new EndpointAddress(namespaceAddress + "/" + topicName); var binding = new NetMessagingBinding(); var securityBehavior = new TransportClientEndpointBehavior() { TokenProvider = TokenProvider.CreateSharedSecretTokenProvider(issuerOwner, issuerSecret), }; var se = new ServiceEndpoint(ContractDescription.GetContract(typeof(INotify)), binding, topicAddress); se.Name = "TopicPublisher"; se.Behaviors.Add(securityBehavior); se.Behaviors.Add(new RKiss.Logger.LoggerAttribute()); factory = new ChannelFactory<INotify>(se); var channel = factory.CreateChannel(); // programmatically setup bmp using (OperationContextScope scope = new OperationContextScope((IContextChannel)channel)) { var bmp = new BrokeredMessageProperty() { Label = "RKiss", TimeToLive = TimeSpan.FromMinutes(30) }; bmp.Properties.Add("abcd", (long)12345); bmp.Properties.Add("image", (long)111); bmp.Properties.Add("id", Guid.NewGuid()); bmp.Properties.Add("counter", (long)counter); OperationContext.Current.OutgoingMessageProperties.Add(BrokeredMessageProperty.Name, bmp); channel.Message(text); } factory.Close(); Console.WriteLine("Message #{0} has been sent to Topic='{1}'", counter++, topicName); } catch (CommunicationException ex) { // ... } catch (Exception ex) { // ... } Console.WriteLine("Press any key to send message"); Console.ReadLine();
Test 3. Event-driven Storage
This test is a scenario where you can see usage of the multiple technologies such as WCF, WF, Azure Blob Storage, Topic and Queue. The following picture shows this scenario:
Basically, we have Publisher, Subscriber and Cleaner components on the promise. On the Azure side we have a Blob Storage and Service Bus with a Queue and Topic channel. The action is very simple, the Publisher is putting a resource to the Blob Storage, firing an event to the Topic channel and sending a scheduled message to the queue to clean-up the resource in the Storage. This scenario is suitable to avoid a multicast delivering large messages. Instead of copying a large message for each subscription, the Service Bus will deliver a very small notification message to the subscriber(s) to pull a resource from the Storage.
Note, that this test requires an option described in the prerequisites section such as azure storage account, creating a blob container and Azure Storage Explorer.
First of all, please launch the AzureStorageExplorer, connect your storage account and show the container 'box'. The following screen shows that for my account name (rkstorage):
next, launch the StorageReceiver console program:
Now, we can fire a Publisher, please launch the StoragePublisher program. Note, that Publisher will automatically perform an action and wait for next one, therefore please refresh the AzureStorageExplorer to see stored resource in the container 'box'.
Ok, the next step is to launch the StoragePublisher:
To verify, that our resource is stored in the Azure Blob Storage, please press the button Refresh on the following Explorer tool. You should see the following result:
Using this tool, we can also see actual resource in the browser. Note, that the watchdog time has been setup for 1 minute, after that, the Storage Cleaner receiver will receive a message from the queue to perform deleting a specific resource from the Blob Storage.
The following picture is a screen snippet about this action:
I know, the resource TTL time is to short (only 1 minute), however, you can go back to the StoragePublisher and fire an event again and focus on the specific action, etc. You can fire publisher multiple times and watch the Storage container 'box' for its contains.
I like this scenario, its implementation has been straightforward and
readable. The following screen snippet shows a workflow of the StoragePublisher.
There are full sequence of the Put and Notify
activities, it is
simple like 1-2-3.
Test 4. Router
This test is going to show a capability of the WCF4 Routing Service on the Service Bus. To better understand this test scenario, which requires launching more programs for producing and consuming messages, the following picture will give you a brief overview of this test scenario:
As you can see, this test scenario is more complex than previous one. Therefore, let's discuss it further. The goal of this test is to show the capability of the WCF RoutingService, which is the Subscriber and Publisher for Service Bus. The RoutingService can be a gateway from/to Service Bus. For this case, there is a WinForm program SimulatorPub/Sub to represent a WCF producer and subscriber or web service. It is a very simple program that sends or receives a Soap message.
On the other side, we have WCF/WF programs for Pub/Sub message and
one program for receiving message from the queue. The following configuration
snippet shows declaration of the all endpoints such as inbound and outbound
endpoints for Router. Note, that Router subscribed its interest to Topic channel
with subscription image1
:
The logical connectivity between the Router and Service Bus is declared in the routing
section. The following picture shows its filters. As you can see, this routing
table supports three connectivity types (priority 9, 10 and 11). The first one has a
custom message filter for BMP bag (image=111), the second one is based on the
EndpointName
, where any inbound message from the endpointRouter
is
forwarded to the outbound channel TopicPublisher1.
The last one with, the
highest priority 11, is based on the message Action
. If this match is true, the
message is forwarded to the Service Bus Queue.
Please, have a look at the full configuration file PubSubRouter.exe.config
for its contents, specially at the endpoint behavior section.
I hope you understand this config file, especial the routing table, which is necessary for our next step such as runtime use cases:
Please, close all opened programs and launch the following programs:
PubSubRouter
console program (this is a host process for Routing Service)SimulatorPubSub
winform program to simulate Pub/Sub messagesSubscriber
console program for receiving messages from the Service Bus TopicReceiver
console program for receiving messages from the Service Bus Queue
At this moment, you should see on all console programs, a prompt message for listeners. Our SimulatorPubSub has already predefined a Pub message, so our test scenario is waiting for an event. We are going to make three use cases, such as the event is sent by simulator, event from the Topic is received by simulator and one more case when simulator will send a message to the Queue.
1. Simulator is firing an event_1 message
Please, press the button OneWay on the SimulatorPubSub. You should see the log messages on the PubSubRouter console program and on the Receiver, so, our message from the simulator has been sent via Router to the Service Bus Queue and received by the Receiver console program, see the following screen snippet:
2. Simulator is firing an event_2 message
In this case, simulator will send a different event message. Please, modify
Action for this message, for example, replace Broadcaster
by
BroadcasterXYZ
word and press the button OneWay for sending this message.
You should see on the Subscriber console program the following result:
and on the Simulator Sub message from the subscription image1:
That's great. What happens here? Well, the inbound message from the Pub
Simulator has been routed to the Topic channel and all subscribers (which is
also a Sub Simulator) with subscription image1
received a copy
message from the Service Bus Topic.
Ok, let's make one more case. Please, press button Clear to erase a Sub message on the Simulator.
3. WorkflowPublisher1 is firing an event message
In this case, we are going to publish a message to the Service Bus Topic. For this test, we need to launch WorkflowPublisher1 console program. Please, do that and watch the results on the console programs.
First of all, we can see that the Subscriber received two messages
(different BMP bag but the same message payload). That's correct, this
subscriber subscribed for image12
subscription, which at this
moment has two RuleDescriptions, that's way we received two copies of the
message:
We can see on the other result on the Simulator, where a Sub message has been
received. You can check the message payload for its element id.
That's all for this test. One more note, please have a look at the PubSubRouter console program. You will see the log messages for inbound and outbound endpoints including their BMP bag.
If everything is goes well, try to modify the routing table, publishers and/or subscriber in this scenario to create new use cases in order to see how the WCF and WF Technologies work with Azure Service Bus Topic/Queue.
Test 4. Subscribers hosted on the IIS/WAS
The Subscriber folder is included in the Test package. This folder contains an implementation of the three subscribers hosted in the IIS/WAS server. One subscriber is implemented declaratively using a workflow xaml. The following code snippet subscriber is created imperatively by the code::
public class Subscriber1 : IGenericOneWayContract { public void Message(System.ServiceModel.Channels.Message msg) { Trace.WriteLine("*** Subscriber1 ***"); if (msg.Properties.ContainsKey(BrokeredMessageProperty.Name)) { Trace.WriteLine("BrokeredeMessageProperty:"); var bmp = msg.Properties[BrokeredMessageProperty.Name] as BrokeredMessageProperty; foreach (var prop in bmp.Properties) { Trace.WriteLine(string.Format(" {0} = {1}", prop.Key, prop.Value)); } } Trace.WriteLine(msg + "\r\n"); } }
and the following screen snippet shows Subscriber3 created by WF. You
can see the usage of the OperationContextScope
to obtain a message BMP bag:
The complete plug-in setup to the Service Bus is done in the configuration file. Please, visit this file to understand each subscriber hosted by IIS/WAS. Note, that this virtual application must have the Auto-Start feature enabled.
I will leave this test for you and I hope you will see the result of the subscribers on the trace output such as DebugView. You can use the Publisher console program to fire an event to the Topic channel.
Advanced usage
Windows Azure Service Bus Messaging offers advanced features such as
receiving message in the PeekLock
mode, when a message is removed
from the Queue/Subscription after the client will send a request to complete the
message, client batching processing, session-full messaging, etc. These advanced features are not
described in this article. More details can be found in the
Service Bus Brokered Messaging Performance - Best Practices Guide.
In this article, we used access to the Service Bus by .Net API clients (wrapped by wcf paradigm) implemented in the Azure SDK. The REST API can be used for .Not application with some limitations. Please, read more about this in Service Bus REST API Reference.
Conclusion
This article described usage of the Windows Azure Service Bus Messaging by WCF and WF Technologies. The Azure Service Bus Messaging is built in the multi-tenant environment and it represents a logical connectivity between its producers and consumers located on promises and/or Azure environments. The Service Bus is not a technology, it is a service solution for queuing and Pub/Sub messaging for event-driven architecture and intra-application message exchange in the transparent loosely decouple manner. Definitely, the Azure Service Bus plays a significant role in the business model for mapping a centralized logical connectivity to the decentralized physical one. I hope you enjoyed this article.
References:
[1] Service Bus
[2] Windows Azure AppFabric Service Bus Brokered Messaging
[3] Service Bus Brokered Messaging Performance - Best Practices Guide
[4] Service Bus Topics and Queues – Advanced
[5] The Windows Azure AppFabric Service Bus: Topics
[6] Exploring Azure AppFabric Service Bus V2 May CTP: Topics
[7] Best Practices for Leveraging Windows Azure Service Bus Brokered Messaging API
[8] How to integrate a BizTalk Server application with Service Bus Queues and Topics
[9] Overview of Creating a Hosted Service for Windows Azure
[10] Creating a Hosted Service for Windows Azure
[11] Exploring Topics and Queues by Building a Service Bus Explorer Tool–Part 1
[12] Windows Azure AppFabric Samples
[13] Azure AppFabric Service Bus Brokered Messaging GA & Rude CTP Diffs
[14] Exploring Azure AppFabric Service Bus V2 May CTP: Queues
[15] SqlExpression
[16] Service Bus Samples on CodePlex
[17] Using Service Bus Topics and Subscriptions with WCF