lko
lko

Reputation: 8299

MVC - WCF - RabbitMQ - Domain Event via Message Queue to Consumer speedup or alternatives?

Domain Driven Design Passing Events to separate Bounded Contexts


A user action in MVC should generate an Event which is passed to a remote (same LAN) Event handler.

What I've tested:

  1. MVC: fire and forget service call (asynchronous) ->
  2. (IIS hosted) WCF which gathers data and populates a message ->
  3. Sent via EasyNetQ/RabbitMQ ServiceBus ->
  4. The event is consumed by a Subscriber (using a DI container initialized from a WCF service endpoint) which handles the event & it's data.

I did some testing to see how it works if the service is called fairly quickly by looping in the MVC side

for (int i = 0; i < 200; i++)
{
        ...
        client.MyServiceMethod(someId, startDate); 
        ...
}

The MessageQueue part is quick, based on the timestamps it is sent to the queue and received by the subscriber within the same second. Looping through the WCF service calls is very slow. It takes many seconds to loop through them. I tried switching from wsHttpBinding to netTcpBinding, and playing with the serviceThrottling in WCF.

WCF isn't compulsory, but it seems like a separate event handling project (on the publisher end) would be beneficial and could be physically located elsewhere from the MVC app (load reduction etc.). Is WCF plausible for a situation like this, or should I try using Windows services or some other self-hosted e.g. console app etc, or potentially using a thread in MVC to generate the event data, or are there better scenarios? What are the best practices in this type of Event handling system? Basically it seems like it would be beneficial to have something generating the Event data since it has to be handled somewhere while not slowing down the UI that the end user is using.

Upvotes: 2

Views: 1623

Answers (2)

Ganto
Ganto

Reputation: 133

If I undertood well, your event creation process is "heavy" and you want to avoid to be created in the MVC process. I guess you are sending some information to the WCF service in order to let him prepare the event.

You could think of a 2 consumers scenario avoiding the WCF step:

  1. Your MVC application creates and publish a "light" event with all data required in order to create the "heavy" event (basically with the input data you would pass to WCF)
  2. An EventCreator subscriber consumes this message and prepares the heavy event
  3. Your already existing consumer will then consume the heavy event

EasyNetQ already provides simple functions to publish and consume the message. Most of the tutorials you find online suggest using TopShelf for hosting your consumers in a console application (debug) or windows service (production). EasyNetQ has an example here: EasyNetQ with TopShelf

If you want to "hide" the EasyNetQ dependecy on your MVC project, you could wrap the EasyNetQ IBus to a custom Bus and use an IoC container in order to inject a specific implementation of your bus. The example provided above uses Castle.Windsor as IoC container

Upvotes: 2

Josh Kodroff
Josh Kodroff

Reputation: 28141

Instead of trying to roll your own infrastructure like this, I think you would do well to employ a tool like NServiceBus (not free) or MassTransit (free). (I would consider this best practice.)

I can't speak for MassTransit, but my experience with NServiceBus has been very good. You only need to specify which messages go to which queue. You can use several different queueing technologies, but I would recommend starting with the default MSMQ implementation. No WCF configuration nightmares necessary. ;)

All of your message handlers will also be automatically wrapped in a distributed transaction so that if a DB interaction fails, the entire message will be rolled back and you'll be able to try the message again in the future.

Upvotes: 2

Related Questions