Michael Stephenson

keeping your feet on premise while your heads in the cloud
posts - 358 , comments - 427 , trackbacks - 11

My Links

News

View Michael Stephenson's profile on BizTalk Blog Doc View Michael Stephenson's profile on LinkedIn

Twitter












Archives

Post Categories

Image Galleries

BizTalk

Mates

RabbitMQ – Implementing Scatter Gather in .net

In this article we will try to talk through an implementation of the scatter gather pattern using RabbitMQ. The sample is written using .net to show how this can be achieved.

Before going into the detail of the article you can see get the sample at the following location:

https://s3.amazonaws.com/CSCBlogSamples/Acme.RabbitMq.ScatterGather.zip

In the sample we will use the scenario of an application which needs to request insurance quotes. Imagine a scenario where a user is using a windows application and needs to send out a request for insurance quotes and will get back a list of responses from various applications who can produce quotes depending on the product requested.

The below diagram shows the example architecture. In the sample we will use a simple windows UI application which will simulate a user requesting insurance quotes. On the back end there will be 4 .net console applications which will subscribe for different messages and provide the processing logic to ensure that the pattern can be implemented effectively.

 

 

In the sample you can see the Exchange is a topic exchange in RabbitMQ and this means subscribers can use expressions against the routing key to workout which messages they are interested in. When a message is processed by RabbitMQ a copy of the message is placed on the worker queue for each component/application that is interested. When the back end application processes the quote request it sends its reply to the ReplyTo address that was provided to RabbitMQ with the original request message. The client will pick up responses from the dynamic reply queue and when the client disconnects the reply to queue is deleted.

 

Functional Scenarios

In this section I will talk through the functional scenarios in this sample.

Scenario 1: Both Applications Respond Quickly

In this scenario when a quote request is sent all of the server side instances are configured to process quotes for product 5 and to respond straightaway. This should demonstrate a true scatter gather pattern with lots of responses like you might expect to see in a typical insurance quote scenario. The below gherkin describes how this works in the sample.

 

Given a request for a quote for product id 5

And a timeout of 5 seconds

    And a minimum number of responses of 2

When the user clicks the get quote button

Then all quote server applications will get the request

And all server applications will provide their quote response quickly

And the interface will display text indicating the quote response from each server

 

Scenario 2: One of the server application times out

In this scenario we are attempting to show how the service will handle the fact that some server side services may take longer to respond than desired. The client will fire off its message then wait for up to a certain amount of time to allow responses to come back and then after that time has elapsed it will return with whatever responses have been returned. The below gherkin describes how this scenario works in the sample.

    Given a request for product id 4

    And a timeout of 5 seconds

    And a minimum number of responses of 2

    When the user clicks the get quote button

    Then both servers will get the request message

    And server 2 will respond quickly with a response

    And server 1 will take some time to process the message

    And the client will wait for 5 seconds then return back with just 1 response

    And the UI will display the response from server 2

    And the response from server 1 will be discarded

Note: Using product id = 4 will make server 1 timeout and using product id = 1 will make server 2 timeout.

 

Scenario 3: Minimum Number of Responses

In this scenario we are attempting to demonstrate a feature on the client side where the client may send a message to a topic and have many subscribers. The timeout value may be high for example 5 seconds but we may decide that once we have a certain number of responses back we will make one more sweep of the response queue and get any messages that have come back already and then decide we have got an acceptable number of replies to return back to the user without having to wait for the full timeout duration. The below gherkin describes how this works in the sample.

    Given a request for product id 6

    And a timeout of 5 seconds

    And a minimum number of responses of 2

    When the user clicks the get quote

    Then the client will send the request message to RabbitMQ

    And all 3 servers will receive the message

    And servers 1 and 2 and 4 will respond immediately

    And server 3 will delay for 30 seconds

    And the client will see that there are 2 responses on the response queue

    And the client will dequeue the three responses and not wait for the remainder of the timeout setting

    And the client will display the two responses to the user

    And any future response from server 3 will be discarded

The key difference between this scenario and scenario 2 is that in scenario 2 the client has to wait the full timeout period and then returns with 1 response but in scenario 3 we get 2 responses back almost immediately so the client decides to just show these to the user and obtain a better perceived latency because we got the minimum acceptable number of responses.

This would be particularly useful in a scenario where you had no awareness of how many servers would be available and new ones may be added at anytime.

 

Scenario 4: Topic Filtering

In this scenario we want to demonstrate how the use of a topic exchange for sending the message means that the server side can choose which messages to subscribe to. In this case we have mainly used the product id as the basis for the subscriptions

Given a request for product id 2

    When the user clicks the get quote button

    Then both servers will get the request message

    And server 2 will respond quickly with a response

    And server 1 will not get this message

    And the client will wait for 5 seconds then return back with just 1 response

    And the UI will display the response from server 2

Note: Using product id = 2 will make server 1 not get the message and using product id = 3 will make server 2 not get the message.

 

Feature Implementation

In this section you will see some notes on how we have implemented some of the messaging features within this scatter gather pattern.

Handling timeout scenario

In the RabbitSender class used by the interface to send its messages to RabbitMQ there is some code in the class which will use some parameters in the class to poll the response queue after the request message is send to the Topic. In the case of our sample the UI lets you specify how long the client should poll for response messages. Once the request message has been send the RabbitSender will wait for up to the timeout duration for responses and after the timeout has expired it will return with all of the responses that came back.

You will see in the client interface the timeout value is passed to the RabbitSender class

 

The subscription scenario

In this sample we are using a combination of the RabbitMQ samples for RPC and Topic message exchange patterns. We use the topic scenario particularly around the use of the routing key and expressions on this key to create a subscription model to ensure the server only gets messages its interested in. In the sample we are using the product id as a core part of the subscription to illustrate the scatter gather pattern, however you can do much more complex routing by using the topic exchange. For more info on those pattern refer to the RabbitMQ samples.

RPC Sample - http://www.rabbitmq.com/tutorials/tutorial-six-java.html

Topic Sample - http://www.rabbitmq.com/tutorials/tutorial-five-java.html

 

Minimum Response Count

As mentioned above in the scenario 3 description we have implemented a feature in this sample so that a client can send out its request for quotes but it can specify a minimum number of responses it would ideally like. This has been implemented as a way to reduce the amount of time you may have to wait for server side components to reply. If you imagine that you send the messages out to a number of applications what would be a fair time to wait? And would you really want to wait this length of time for every request when you don't know who has responded and who may be left to respond. In a true pub/sub architecture the client would not be aware of the components that subscribe for messages.

In this feature we wanted to give all applications the opportunity to send a reply within a time out which could be for example 20 seconds but at the same time we would say that as soon as we have 5 replies we will take whatever is on the response queue at that time and then anyone who hasn't replied yet will be ignored.

 

Load Balanced Queue Processors

Its not a core part of this sample but I wanted to draw attention to the server components where you will see the console application start and list 10 consumer processes. I have simply done this to illustrate a more realistic type of scenario where you would have more than one polling process on each queue for good throughput and other reasons. In this case the processes implement a competing consumer pattern so that they will pull messages from the worker queue for their application but only one process will pull each message.

In this sample each server console application will start off 10 processes on its worker queue.

I will go into this in more detail in a separate post.

 

Key Parts of the Sample

In this section I will outline some of the key parts of the sample.

The Shared Assembly

The shared assembly contains some classes which are used across the sample. Firstly there are some contract classes which represent the message which will be send through RabbitMQ. The QuoteRequest and QuoteResponse classes are the ones which we will use for this sample.

The RabbitSender class is used by the client application to encapsulate a lot of the scatter gather functionality by giving a nice easy to use function for the client but then containing the complexity of sending the message and polling for the response.

The RabbitReceiver class is used by the server components to register for the messages they wish to receive and the to interact with the Rabbit queues.

The Servers

There are 4 console applications which will act as the servers. The program class in each will instantiate multiple instances of the RabbitReceiver class which will listen for messages. Each server will implement a slightly different subscription which you should see easily in the program class.

Each server also implements a QuoteService class which implements the IQuoteService interface which contains the logic for how that server processes claims.

The Client

In the client UI project you will very easily see how the windows form uses the RabbitSender class to be able to create a call back queue and then send a message to the exchange. This class also contains the logic to be able to manage the timeout and minimum number of responses functionality. It then allows the client to simply appear to use a normal method call to then wait for its response.

Print | posted on Monday, August 6, 2012 11:54 AM | Filed Under [ RabbitMQ ]

Feedback

Gravatar

# re: RabbitMQ – Implementing Scatter Gather in .net

thanks, saved my life. RabbitMQ rulez:)
8/17/2012 11:09 AM | ügyvitel
Post A Comment
Title:
Name:
Email:
Comment:
Verification:
 

Powered by: