Sunday, January 6, 2013

Keeping your AppHarbor application pool alive

By default, IIS will shut down your application pool when it has been idle for more than 20 minutes. This is annoying when your website is only visited sporadically; visitors might not have the patience to wait for your application pool to spin up again. When you're running your own machine, you can higher or disable the idle-timeout, but when you're running on a cloud service like AppHarbor you can't.

One solution is to frequently make a request yourself to keep the application pool alive. You can use a third party service (like Pingdom or StillAlive), but chances are you don't want to take an extra dependency for something that trivial.

AppHarbor contains the required infrastructure to do this yourself: background workers and scheduling.

First create a new Quartz job which makes a request to your web application when it's invoked.
public class KeepAliveJob : IJob
{
    public void Execute(IJobExecutionContext context)
    {
        using (WebClient client = new WebClient())
        {
            client.DownloadString("http://your_webapp.com");
        }
    }
}
Then schedule your job to be triggered every 19 minutes or so.
var keepAliveJob = JobBuilder.Create<KeepAliveJob>().Build();
var keepAliveTrigger = TriggerBuilder.Create()
                .WithSimpleSchedule(x => x.WithIntervalInMinutes(19).RepeatForever())
                .Build();

scheduler.ScheduleJob(keepAliveJob, keepAliveTrigger);    
scheduler.Start();   
And that should be it; you're now running your own ping service.

9 comments:

  1. I'm doing something similar with my Azure Websites and it works just great. However, I wonder if MS and AppHarbor could have a problem with this practise because obviously it artifically increases their load and makes it harder for them to move around our applications on their VMs...

    ReplyDelete
    Replies
    1. I wonder how much three extra requests per hour compare to all the other traffic?
      I would imagine they'd set up the second server first, to then switch on NLB, to slowly disallow requests going the first server before turning it off completely. Just a thought, I have no idea how these things work. Interesting though.

      Delete
    2. The problem is not CPU load, it's memory load. Keeping that AppDomain loaded is going take away precious memory from the VM that it's running on. If you're paying for a VM that comes with the memory included, I don't think that should be a problem. On a shared server, though, it may turn into a fight over memory.

      Delete
    3. I had requests to build keep-alive into AppHarbify so you could just toggle it on for your site.

      I declined because of these load issues, lots of people have throw away test projects on AppHarbor and I didn't want people to turn it on just because they can and leave AppHarbor keeping sites alive indefinitely.

      It would be nice if they built it into the platform for any paid account.

      Delete
    4. Chris

      I agree with all of that :)

      Delete
  2. I'm wondering if this isn't something AppHarbour could support on the underlying webserver (whether that's IIS or Apache running Mono, I don't know) using something akin to the IIS Warmup module. Your appdomain may be recycled for other reasons as well, not just your idle time.

    ReplyDelete
  3. I just wanted to let you know that AppHarbor already waives the 20 minutes default apppool timeout for all paying apps.

    Also note that running multiple applications with the intention of avoiding incurring fees is not, strictly speaking, in accordance with the AppHarbor terms (4.4): https://appharbor.com/page/terms

    ReplyDelete
    Replies
    1. I see. I'm paying for my website though, and still noticed the application pool shutting down. Also couldn't find any information on how to higher it?

      Delete
    2. Also, I did find quite some support tickets which advised on doing something similar. For example: http://support.appharbor.com/discussions/problems/2189-time-to-time-apps-stop-been-reachable.

      Delete