Tuesday, October 11, 2011

WCF - Store and Forward

When designing WCF services, specifically, OneWay operation contracts, developers usually expect the service to be stable. One doesn’t consider network instability between the service and its clients.

That’s why, many messaging engine, such as BizTalk and Tibco EMS has a built-in feature called Store and Forward.  That is, the client doesn’t consume the service directly but rather publish the messages into a store, and then the messaging engine peeks on the message store and route it to pre-designated subscribers. This architecture pattern is called Pub/Sub. You can look it up here.

In WCF world, developers have the facility to build this store and forward capability using MSMQ binding (netMsmqBinding). However, MSMQ has a lot of networking issues, especially if it’s used as a network resource in a multi-forest or multi-domain environment.

I have worked on a small-scale solution to accomplish this task using a database message store. It’s built on the following components:

  1.  Router: the router is called by the client. Currently it’s a stateless router based on WCF 4.0 routing service (http://msdn.microsoft.com/en-us/library/ee354381.aspx - Routing Service).
  2. Persistence Service: a WCF service with a single Operation Contract (Publish). It’s used to publish WCF messages into the message store.
  3. Message Store: a database to store WCF messages.
  4. Message Processor: Peeks the message store for new messages based on subscriptions and route them to subscribers.
  5. Subscription Manager: a WCF service used to subscribe or unsubscribe. It has two Operation Contracts. Subscribe and Unsubscribe.

Known Issues:
Ø  It works only with basicHttpBinding.
Ø  Subscription manager is not testedJ
Ø  It uses the SOAP action to route messages. That means that you’ll have to subscribe for each SOAP action. I’m planning to use Regex to match subscriptions instead.
Ø  It’s not tested with large messages (> 4mb). I believe it will need some work to adjust the readerQuotas on the channel binding.
The solution code and database script can be found here.