Design considerations for heavy loaded asp.net MVC + Web API application and asynchronous message bus

1.9k views Asked by At

I'm planning to build a quite large application (large in term of concurrent user / number of request, not in term of features).

Basically, I'll have a service somewhere, that is waiting for commands execute them, and acknowledge the completion later. This service will use a service bus to communicate, making the execution eventual, before a acknowledge message is issued.

The consumers of this service can be any kind of application (WPF, SL, ...) but my main (and first) client will be an asp.net MVC application + WebApi (.Net 4.5) or MVC only (.Net 4.0) with ajax controller actions.

The web application will be relying on Ajax call to keep a user friendly responsive application.

I'm quite new to such full blown async architecture, and I'm having some questions to avoid future headache :

  • my web api calls can take some amount of times. How should I design properly the api to support long running operations (some kind of async?). I've read about the new async keyword, but for the sake of knowledge, I'd like to understand what's behind.
  • My calls to the service will consist is publishing a message and wait for the ack message. If I wrap this in a single method, how should I write this method? Should I "block" until the ack is received (I suppose I shouldn't)? Should I return a Task object and let the consumer decide?
  • I'm also wondering if SignalR can help me. With signalR, I think I can use a real "fire and forget" command issuing, and route up to the client to ack message.
  • Am I completely out of subject, and should I take another approach?

In term of implementation details / framework, I think I'll use :

  • Rabbitmq as messaging system
  • Masstransit to abstract the messaging system
  • asp.MVC 4 to build the UI
  • Webapi to isolate command issuing out of UI controllers, and to allow other kind of client to issue commands
2

There are 2 answers

0
Dennis van der Stelt On BEST ANSWER

my web api calls can take some amount of times. How should I design properly the api to support long running operations (some kind of async?).

I'm not 100% sure where you're going. You ask questions about Async but also mention message queuing, by throwing in RabbitMQ and MassTransit. Message queuing is asynchronous by default.

You also mention executing commands. If you're referring to CQRS, you seperate commands and queries. But what I'm not 100% about is what you're referring to when mentioning "long running processes".

  • When you query data, the data should already be present. Preferably in a way that is needed for the question at hand.
  • When you query data, no long-running-process should be started
  • When you execute commands, a long-running-processes can be started. But that's why you should use message queuing. Specify a task to start the long running process, create a message for it, throw it onto the queue, forget about it altogether. Some other process in the background will pick it up.
  • When the command is executed, the long-running-process can be started.
  • When the command is executed, a database can be updated with data
  • This data can be used by the API if someone requests data

When using this model, it doesn't matter that the long-running-process might take up to 10 minutes to complete. I won't go into detail on actually having a single thread take up to 10 minutes to complete, including locks on database, but I hope you get the point. Your API will be free almost instantly after throwing a message onto the queue. No need for Async there.

My calls to the service will consist is publishing a message and wait for the ack message.

I don't get this. The .NET Framework and your queuing platform take care of this for you. Why would you wait on an ack?

In MassTransit

Bus.Instance.Publish(new YourMessage{Text = "Hi"});

In NServiceBus

Bus.Publish(new YourMessage{Text = "Hi"});

I'm also wondering if SignalR can help me.

I should think so! Because of the asynchronous nature of messaging, the user has to 'wait' for updates. If you can provide this data by 'pushing' updates via SignalR to the user, all the better.

Am I completely out of subject, and should I take another approach?

Perhaps, I'm still not sure where you're going. Perhaps read up on the following resources.

Resources:

http://www.udidahan.com/2013/04/28/queries-patterns-and-search-food-for-thought/ http://www.udidahan.com/2011/10/02/why-you-should-be-using-cqrs-almost-everywhere%E2%80%A6/ http://www.udidahan.com/2011/04/22/when-to-avoid-cqrs/ http://www.udidahan.com/2012/12/10/service-oriented-api-implementations/

http://bloggingabout.net/blogs/dennis/archive/2012/04/25/what-is-messaging.aspx http://bloggingabout.net/blogs/dennis/archive/2013/07/30/partitioning-data-through-events.aspx http://bloggingabout.net/blogs/dennis/archive/2013/01/04/databases-and-coupling.aspx

0
stormwild On

my web api calls can take some amount of times. How should I design properly the api to support long running operations (some kind of async?). I've read about the new async keyword, but for the sake of knowledge, I'd like to understand what's behind.

Regarding Async, I saw this link being recommended on another question on stackoverflow:

http://msdn.microsoft.com/en-us/library/ee728598(v=vs.100).aspx

It says that when a request is made to an ASP .NET application, a thread is assigned to process the request from a limited thread pool.

An asynchronous controller action releases the thread back to the thread pool so that it is ready to accept addtitional requests. Within the action the operation which needs to be executed asynchronously is assigned to a callback controller action.

The asynchronous controller action is named using Async as the suffix and the callback action has a Completed suffix.

public void NewsAsync(string city) {}
public ActionResult NewsCompleted(string[] headlines) {}

Regarding when to use Async:

In general, use asynchronous pipelines when the following conditions are true:

  • The operations are network-bound or I/O-bound instead of CPU-bound.
  • Testing shows that the blocking operations are a bottleneck in site performance and that IIS can service more requests by using
    asynchronous action methods for these blocking calls.
  • Parallelism is more important than simplicity of code.
  • You want to provide a mechanism that lets users cancel a long-running request.

I think developing your service using ASP .NET MVC with Web API and using Async controllers where needed would be a good approach to developing a highly available web service.

Using a message based service framework like ServiceStack looks good too:

http://www.servicestack.net/

Additional resources:

http://msdn.microsoft.com/en-us/magazine/cc163725.aspx http://www.codethinked.com/net-40-and-systemthreadingtasks http://dotnet.dzone.com/news/net-zone-evolution http://www.aaronstannard.com/post/2011/01/06/asynchonrous-controllers-ASPNET-mvc.aspx http://channel9.msdn.com/Events/TechDays/Techdays-2012-the-Netherlands/2287 http://www.dotnetcurry.com/ShowArticle.aspx?ID=948 // also shows setup of performance tests http://www.asp.net/mvc/tutorials/mvc-4/using-asynchronous-methods-in-aspnet-mvc-4 http://visualstudiomagazine.com/articles/2013/07/23/async-actions-in-aspnet-mvc-4.aspx http://hanselminutes.com/327/everything-net-programmers-know-about-asynchronous-programming-is-wrong http://www.hanselman.com/blog/TheMagicOfUsingAsynchronousMethodsInASPNET45PlusAnImportantGotcha.aspx