Should We use a Windows Service or Thread Pool?
We're developing a web application in Asp.Net MVC 4 intended for hundreds of users.
We need to have a background service per user to work in an interval of a few minutes.
We are not sure whether to use Windows Services (multiple windows services) or to use a Thread Pool of processes. We think of Windows Services cause they're maintainable easily via windows server and that approach can save the overhead of programming a UI and manage threads. It also can easily run in an interval of time.
Is it possible for a Windows Service to automatically initiate a new instance for a new user who has just signed up (so we have multiple background windows services instances, one for each user)? if not the Windows Services option falls.
If the upper is possible, should We choose Windows Services approach or make our own managed Thread Pool of processes?
Certainly, starting a process per user guarantees you high memory overhead and non-scalability when you get into the 1000s. I don't see what starting a process (as opposed to a thread) could possibly save because the new process will contain at least one thread. Also, Windows Services have nothing to do with "logged in users". They are not made for multi-instancing.
You seem to want to run background work in ASP.NET MVC. Be aware, that this is hard. Using one Windows Service can make sense here.
The hard thing about background work is that worker processes can exit for many reasons. You must tolerate this. A service has the same problem: You need to deploy new versions and restart the server regularly. You also need an HA strategy so you need multiple servers.
I'm not convinced that a Windows Service would be a better choice even for long-running background work.
With 100s of concurrent background workers you should probably use async IO to not have 100s of threads dedicated.
I assume your background work waits most of the time. You can make the waiting async (using a timer) and all the rest synchronous. That gives you a simple implementation and vast savings in memory usage.
We wrote a open-source project, Revalee, to handle this type of workload. It uses a Windows Service to manage the task scheduling, but leverages your existing ASP.NET MVC application to handle the action out-of-band. Tasks can be in the hundreds of thousands and are persisted until successfully dispatched.
Here is a simple workflow diagram:
user initiated action | | ...................... | : future callback : V V : ====================== =========================== | Your web app | | Revalee Windows Service | | | | | ====================== =========================== | ^ | registers a callback now | |________________________________|
Using a separate service to perform background tasks might introduce additional burden:
Having two separate apps will certainly increase complexity of your project: if you need any communication between the web app and the service, it will be more complex (and slower) than having the whole thing inside the web app. You also need to deploy two separate projects, so there some plumbing overhead that will double this way.
Performance wise, there is nothing you gain from this approach. On the contrary, having your own managed pool inside the web app will allow better scheduling of these threads and quite possibly allow you to run them more efficiently than simply letting Windows take care of this. You really don't want to spawn hundreds of processes (or threads) which would compete for resources simultaneously on the same machine.
If nothing else, keeping the whole functionality inside the web app app might simplify your hosting options. Installing and managing a Windows service might require more privileges than a cheap hosting provider is prepared to give you.
Having said that, running background tasks in ASP.NET means that you need to be prepared to have your threads aborted abruptly, due to exceptions, recycling or any other reason IIS can think of. Running these background tasks in a separate process will certainly be less susceptible to these ASP.NET quirks, so it ultimately boils down to a compromise: how important it is for you to make sure these tasks are never interrupted, and does it justify additional programming and maintenance effort?
If your concern is how to schedule these tasks inside the service, take a look at some scheduling libraries for .NET, like Quartz. It allows better control over scheduling than simply using a timer and (should you ever need them) provides some advanced features like persisting jobs (useful if you want to make sure your jobs will finish after restarts) and clustering for large scale applications.
Using a simple timer will work, but make sure that you understand how each of .NET timers dispatches its events.