In order to speed up reaction time of our ASP.NET MVC application, we'd like to "warm up" the application after it has been installed (or after the app pool has been recycled). Some frequently used lookup data should be fetched from the SQL Server database, and stored into the global System.Runtime.Caching.MemoryCache object that .NET provides.
For a situation where you have a dedicated VM with a dedicated IIS for your ASP.NET app, I first of all set the app pool to be "Always Running" - that's step #1.
Given this situation, there are two options I see:
Application warmup as described in this blog post by Scott Gu based on the System.Web.Hosting.IProcessHostPreloadClient interface. If I understand correctly, this code runs when the app pool is started, and before the first request is accepted into the application
Use the Application_Start event in global.asax.cs. If I understand correctly, this event is called only once, when the application is started for the first time (which would happen automatically after installation, since the app pool is set to be "Always Running" - right?)
So - given this setup - which is the preferred way of "pre-warming" your application? Are there any significant differences between these two approaches? What do I need to be aware of when going with one approach over the other?
Thanks for any inputs, hints, warnings, or further links explaining this in more detail!
The short answer, use IProcessHostPreloadClient -- it will run immediately on startup.
Application_Start is a bit of a misnomer, it actually fires on the first request. That means the site might recycle/restart and be sitting idle, where it could be warming.
If your site is on IIS 7 or above I'm not aware of a reason to use Application_Start.
Related
I am working on an ASP.NET MVC web application (C#) that is a module of a larger application as a whole (mostly desktop/win service based - VB.NET). Currently the application makes HTTP calls to a web service (provided as an API) which is it's own independent application (also using MVC, VB.NET). Possibly not how I would design it, but it is what I have inherited.
My issue is this: If I host the MVC app in local IIS and run the API project in IIS Express, all is good. If I split the two projects up to run in separate Application Pools in local IIS, all is good. However, if I run both apps out of the same pool in IIS, I run into a lot of issues. Namely, timeouts when I make the call to HttpClient.GetAsync(url) - especially on a page that is calling this 9 times to dynamically retrieve different images based on ID (each call is made to MVC app which then makes the call to the API). Some calls make it through, most do not.
The exceptions relate to cancelled tasks (timeout = 100s) - but the actions require a fraction of a second so there is no need to timeout. Execution never even makes it into the functions in the API side when it fails - like the HTTP client has given up offering any more connections, or the task is waiting for HTTP to send the request and it never does.
I have tried making it Async all the way through, tried making the HttpClient static, etc. But no joy. Is this simply something that just shouldn't be done - allowing the two apps to share an app pool? If so, I can live with that. But if there is something I can do to handle it more efficiently, that'd be very useful. Any information/resources on this would be very much appreciated. Ta!
We recently ran into the same issue, it took quite a bit of debugging to work out that using the same applciation pool was the cause of the problem.
I also found this could work if you increase the number of Maximum Worker Processes in the advanced settings for the the application pool.
I'm not sure why this is, but i'm guessing all of the requests are being dealt with by one process and this is causing a backlog and ultimately there are too many resulting in timeouts. (I'd be happy for someone more knowledgeable in IIS to correct me though)
HTH
Edit: On further reading here Carmelo Pulvirenti's Blog it seems as though the garbage collector could be to be blame. The blog states that multiple applications running on the same pool share memory, the side effects are;
It means that GC runs a lot of time per second in order to provide
clean memory to your app. What is the side effect? In server mode,
garbage collector requires to stop all threads activities to clean up
the memory (this was improved on .NET Fx 4.5, where the collation does
not require to stop all threads). What is the side effect?
Slow performance of your web application
High impact on CPU time due to GC’s activity.
I have a web app that I'm writing right now that is supposed to have "periodical events". For instance, at midnight, the web app should calculate "scores" for all users. I want this done only once during the day.
Is there a way that I can automate this, so it runs automatically at midnight (or whatever hour I choose)?
I don't like the idea of creating a separate script (VBS) to do this, as the calculation would depend on a lot of business logic of the app. I was thinking to put it into a separate Class Library, so it can use the web app logic (which is also in a class library), but is this the best way to go about it?
I also don't like the idea of using the Session_Start() event in the Global.asax to trigger the event by checking the hour manually. There must be some easier way - especially because down the road I expect there will be a lot more of periodical events - some may have to be triggered every fifteen minutes, for example ...
Thanks a lot for any help you can give me.
You should not do this in the web app itself. You are correct to put the business logic in a separate library. Once you have done this, you can use the business logic from anywhere, and therefore, a good solution would be to create a console application that does the nightly jobs, and invoke the console application from Windows Task Scheduler. IIS is not suitable as a host for periodical events.
I guess you are missing the point of separation of concern. Whatever you are asking is a job of a service. You need to develop a separate application as Windows Service that will do all your calculation and to be triggered by any scheduler even Windows Task Scheduler would do. This is what basically done on large scale applications.
Yeah... again awesome "change your architecture and hosting environment so that my answer can be relevant" responses.
Doing what you ask is actually quite easy, take a look at this article: http://www.codeproject.com/Articles/12117/Simulate-a-Windows-Service-using-ASP-NET-to-run-sc
This is a job for a windows service or scheduled task. A web application responds to HTTP requests. Essentially the service's job would be to wake up, run the appropriate calculations and write back to the database. Once in the database, your web application can use the newly calculated values.
Here is some information on windows services: http://msdn.microsoft.com/en-us/library/d56de412.aspx
I am wondering if a static class in an ASP.NET MVC app could be initialized more than once. I initially designed my app so that a static component would fetch some stuff from the database and serve as a cache, and I added a refresh method to the class which was called from the constructor. The refresh method was also made available through the administration portion of the app. At some point I noticed that the data was updated without requiring this manual trigger, which implies that the static constructor run more than once.
There are several scenarios where I could reasonably see this happen, such as an unhandled Exception causing re-initialization. But I am having trouble reproducing this, so I would like to know for sure.
The most usual scenarios would be:
a reload of the web application
touched Web.config
touched binaries
abnormal termination (out-of-memory, permission errors)
a reload of the Application Pool
a restart of IIS
a restart of w3wp.exe (at least once in 29 hours!)
The app-domain will get reloaded (recompiling the dynamic parts as necessary) and this would void any statically initialized data.
You can get around that by persisting the static data somewhere if creating it is expensive, or avoid reloading the AppDomain, the Application Pool or the IIS server.
Update: Phil Haack just published a relevant blog entry here: http://haacked.com/archive/2011/10/16/the-dangers-of-implementing-recurring-background-tasks-in-asp-net.aspx
Bye Bye App Domain
it does a better job at explaining the above. Notable, IIS will recycle it's worker process very 29 hours at minimum and shared hosters will recycle AppDomain much more often (perhaps in 20 minutes of idle time)
So tell ASP.NET, “Hey, I’m working here!”
outlines techniques you can apply to get notified of an AppDomain take down - you could use this to get your Singleton instance behaving 'correctly'
Recommendation
I suggest you read it :)
static classes are initialized once per AppDomain.
If IIS recycles your AppDomain, everything will re-initialize.
I am building a Web application using MVC3 .NET
The app should somehow keep a weekly todo list for each user. On Fridays, all todo lists must be reset.
Can someone help with that.
thanks
You may take a look at Quartz.NET. This being said, the culprit of handling scheduled jobs by a web application is that the web server could unload this ASP.NET application under some circumstances (memory or CPU threshold is hit, the application is not used for a long time, ...). For this reason it is recommended to develop a separate process that will perform those tasks. This process could be hosted for example in a Windows Service which is guaranteed to run all the time.
Another possibility is to simply use the Windows Scheduler in order to launch some custom made executable on a weekly basis which will take care of performing the necessary tasks.
If this is some database-level task, then perhaps a scheduled-task (or crontab on nix). There is no need for MVC to do that. If you really want, the scheduled-task could just hit a route on the web-site.
However, personally I'd simply partition the data with a week-number (or a start date), so that when I get the data, I'm getting the data for the week starting (your date). Then:
there is nothing to do
you have access to history as needed
i.e. add StartDate (or similar) as a column on your existing storage, and use that to select the most timely data. You will get calls about "I need the data from last week" - you might as well built it in from the outset. Besides... if something isn't done on Friday, that doesn't mean it ceases to exist...
do you expect the application to always be up and running? what if nobody is using it on midnight between Thursday and Friday? How can you then execute those jobs?
in general since a web application is not surely running at any given time, you cannot rely on timers inside the web application.
I think best solutions in this case would be to either create a windows service which will be installed on the server and will be always running by definition... a bit like reinventing same things again and again...
or you could also set a scheduled task in windows to call your web application, creating a request to a specific page every Friday, then the web application gets invoked with some parameters and you can do what you need.
I need a method to run every so often that does some database processing. However, I may need it to be triggerable by an admin on the site. But I don't want this method being run more than once at the same time, as this could cause issues with the way it hits the database.
For example, could I...
Create a singleton class that runs the method on a timer, and instantiate it in the global.asax file. Then, since it's a singleton, I can call it from my normal .aspx pages and call the method whenever I want. I would probably need to use that "lock" feature of C# to check to see if the method is already running.
I heard some talk lately that Singletons are "evil", but this seems like the perfect fit for it. What do you think? Thanks in advance.
Timers and locks (that are intended to synchronize access to the database) are a bad idea on the web; you may have zero, one or many app-pools on different servers. They may recycle at any time, and won't be spun up until needed. Basically, this won't prevent you hammering the db from multiple sources.
Personally, I'd be tempted to either write a service to do this work (either db-polling, or via WCF etc), or use the db (a SP or similar) - set a flag in a table-row to say "in progress", do the work at the db, and clear the flag (duplicate attempts exit immediately while in progress).
I would do it this way
Build a normal ASP.NET page which does the processing
StealBorrow LFSR Consultings idea for a flag in the DB which does the work of checking if the process is currently running
Use normal cronjob or windows task scheduler to call the web page on a regular basis.
And Singletons aren't evil they just get abused easily.
Another option which Joel Spolsky mentioned in one of the SO Podcasts, i believe it was #20 something. Is to set an empty Cache object on application start with a certain expiration date, and in the CacheItemRemovedCallback make a call out to page or do some work and then reset the empty cache object.
I'm probably horribly mis-quoting him, so I recommend you listen or look through the transcripts for yourself.
What about just setting up a flag in the database and checking that to determine if the job is running or not? Seems simpler IMO.
The canonical way to write a singleton ends up not being thread safe. Especially in a webby environment, where threads needn't even be on the same machine!
If you really want to do a "singleton", think of it as a service that you only ever deploy to one machine. Then use the transactional semantics of your database like Marc Gravell suggests to synchronize the locks.
We've done similar things by using a Web Service to do the backend processing, then writing a Desktop App to call it on whatever schedule we need. We can then run that app on a server, or an admin can run it directly from their PC to trigger the job.
Edit: After I saw your revision that you don't want them to run simulatenously, we have usually just controlled that with a database flag like a few others have said, nothing fancy but it gets the job done
Set an Application wide variable to denote that the process is running. That should be a little easier than storing the variable in the database, right?