tl; dr
After quite extensive testing and gathering of relevant sources to attempt to resolve the issue, I think that the minimal solution may be (not verified) to add this code to the global.asax:
protected void Application_End()
{
...
HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://web_domain.tld");
using (HttpWebResponse response = (HttpWebResponse)
request.GetResponse())
{
}
...
}
In the time of writing the post, this is used to effectevely maintain the site I worked on 'always-up' - with conjuction of setting the Idle Time-out (minutes)
in IIS to 0 as mentioned in other answers. However I think that changing Idle Time-out (minutes)
may not be necessary (assuming that Application_end
event is raised when the switch of application pool to Idle mode occurs).
How it works (assuming it does):
- There are 2 settings in the IIS application pool settings that affect when the application is suspended or terminated. One of them is
Idle Time-out (minutes)
which defaults to 20 minutes and when the specified time elapses since the last request, the worker process is suspended or terminated. When a next request comes, the worker process is resumed or started again and the Application_start event is raised (and so if the Application_start handler is defined in global.asax, it is executed). In case of the project I worked on, the Application_start took about 17 seconds to complete. So if the site was 'left alone' for 21 minutes and then the new request came, it took about a little more than 17 seconds before the response was sent back (Application_start + page processing). When another request was sent in the window of 20 minutes, the response was sent significantly faster (perhaps less than 1s), since the Application_start has already been processed.
Setting the Idle Time-out (minutes)
value to 0 causes the worker process to never be suspended / terminated (at least due to the idle time - there may be another cause described below).
- Apart from
Idle Time-out (minutes)
, there is also the Regular time interval (minutes)
setting in Recycling
section of the IIS advanced settings. This defaults to 1740 minutes (29 hours) and is a regular scheduled task that causes the Application pool to periodically recycle (the period is fixed). This, I understood, is to prevent the accumulation of possible memory-leaks which, if present, may eventually crash the server by exhasting all the memory. The effect of app-pool recycling is that Application_end event is raised. However, after the application ends it is not automatically started again, so the Application_start event is not raised until an actual request comes (which is similar to the first case). So in the case of the aforementioned web application I worked on, it would again take about 17 seconds to process the first request to arrive after the recycling occured. Changing this value to 0 turns the recycling off, but I suppose that it is reasonable not to turn the recycling completely off due to the possibility of accumuluation of memory leaks over time (which may possibly even be caused by bugs in 3rd party libraries). I understand that the opinions differ on whether to set this value to 0 or not and may change over time.
Posible solution (without changing IIS settings):
If the requests are sent frequently enough, the app-pool may never switch to Idle mode. On the event of recycling, this would also cause to the application to start again. This can be achieved, for example, by using 3rd party service as described by @Rippo.
Proposed solution:
It has been observed that application pool recycling caused Application_end
event to be raised. Assuming that it is also raised upon switching of the application pool to Idle mode, it would seem to be sufficient to create a request in the Application_end
event handler to the website, which in both cases would then cause the application to start again (raising the Application_start event). The code is at the top of the answer.