Following on from previous samples I wanted to talk about how to implement a scatter gather pattern using the AppFx.ServiceBus framework. In this sample we want to achieve the following:
- Send a message from a client application to a Service Bus topic
- Use the topic filters to route this client to two subscriptions
- Have a service listening to each subscription which will handle the message and return a response
- Have the client wait for multiple responses to come back and return them as a collection.
Hopefully that is straight forward so let's walk through this sample.
Accessing the Sample
On the codeplex site you can download the samples. In the samples folder you need to go to the folder: Sample5-ScatterGather
This folder contains all of the code for the scatter gather sample.
Configuring the Azure Service Bus
To begin with we will need to create the following in the Windows Azure Service Bus
- A response queue which response messages back to the client will be published to. This queue will need to have session enabled
- A topic which the client will publish messages to
- 2 x subscriptions, 1 for each client
- A rule for each subscription using 1=1 so that the message is routed to all subscriptions
The response queue will be called: sample5-scattergather-response
The topic will be called: sample5-scattergather
The subscriptions will be called:
Note that in the samples folder there is an xml file containing the setup for all queues and topics used in these samples which you can import into your namespace using the Service Bus Explorer tool.
The message contract
The message contract follows the usual standard from previous samples. We will use an xsd schema to define out messages and then generate classes to represent these. In the sample the client and server will use this object but as data goes over the wire so to speak it will be in a serialized format which can be either xml or JSON depending on what your specify.
The contract looks like the below picture. You can see that again we are using the get customer sample message.
Configuring the Client
Moving on to the client where we have a simple windows application we will need to begin by setting up the configuration. In the same way as previously we will use the AppFx.ServiceBus configuration section. Firstly I will add my connection string for my service bus namespace like in the below picture.
After the section is declared and also the connection string I will add my AppFx.ServiceBus section and configure it to talk to the Topic in the Windows Azure Service Bus. See the below picture:
You can see that above I have added my client and specified the queue/topic to send the message to and also my response queue. Ive also specified my serialization format.
Client Side Code
Next in the client side code I need to use the SessionScatterGatherMessagingClient class. When I have constructed this class I have used Generics to tell it what type of messages I will be dealing with. I have also specified a client name so it knows what configuration to pick up from the config file (note you cant quite see that in the pic).
When I come to send the message there are a couple of key settings to be aware of. Firstly in the constructor you can override the default timeout if you want to. You can also in the SendScatterGather method specify the minimum number of responses you want to get back. This means that the messaging client class will wait for 30 seconds for responses to come through but if the response queue is empty before 30 seconds but the messaging client has already got your minimum number of responses back then it will return to the caller with what it has regardless.
Hopefully you can see that the client code is pretty simple.
Configuring the Server
On the server side we will take a similar approach to the previous samples. In the ..\Library folder (in relation to the solution file) there is three folders. One has the dll's for the client side of the framework which the client will reference, but the other two contain instances of the AppFx.ServiceBus console host application which will be used to listen on the service Bus.
In the server project in Visual Studio we have two configuration files:
These files contain the configuration for each of the hosts to connect to the service bus. The only real difference between then is the message entity they will listen to. Each host will listen on a different subscription. An example of this is below:
During the build process for this project I have modified the build using the OverrideBuild.targets file in the project so that these two configuration files and the server and contracts assemblies are copied to the right server folders so they can be picked up by each host. If you compile the projects and then check these folders you will see they are copied over.
The server Message Handler
The message handler for each server instance is exactly the same. It will simply return a response. An example of the code is below:
Running the sample
To run the sample, click F5 and the client application will open up. You will also need to go into the ..\library\AppFx.ServiceBus.Hosts.Console…. Folders and run the AppFx.ServiceBus.Hosts.Console.exe file. This will start up the servers listening on their subscriptions.
When you click send you should get a response shortly afterwards displaying that you have responses like the below:
You should also be able to check both server console windows and see that they have processed messages like the below:
If you look carefully at the text in the console window you will see that the message was received and handled by the message handler. You should see the same in both windows.
What about Errors?
It is possible that one or more of the listening services could return an error. Using the AppFx.ServiceBus framework it you have a pattern available to help you deal with this scenario. If any servers return an error then this is returned in the same way that errors were returned in the RPC samples. The key difference is that using the Scatter Gather messaging client class it will catch these errors and return them to you at the end of the call in the response object. You get the reply which contains a list of good responses and a list of error responses.
The calling client can then deal with these however it needs to.
Hopefully you can see this walk through makes it nice and easy to implement the scatter gather messaging pattern. I think in a future release we will also include another option with the scatter gather pattern so that the message client will raise an event each time an error or success response comes back as I can also see scenarios where that will be useful too.