8

I have a WCF hosted on Azure (WebRole). That WCF does a lot of background tasks and replies to some petitions.

The problem is that if the WCF doesn't receive any petition for a long time (10 hours or more) the application pool is recycled on the azure instance and the WCF tasks stops. I did a little investigation an I can enable a AutoStart feature touching the machine.config, but this is not an option with a azure deploy.

Can I enable AutoStart within web.config or deploy config files?

Jordi
  • 2,789
  • 1
  • 20
  • 35

2 Answers2

11

You can add some code in the WebRole.cs to modify the application pool:

public class WebRole : RoleEntryPoint
{
    public override void Run()
    {
        using (var serverManager = new ServerManager())
        {
            var mainSite = serverManager.Sites[RoleEnvironment.CurrentRoleInstance.Id + "_Web"];
            var mainApplication = mainSite.Applications["/"];
            var mainApplicationPool = serverManager.ApplicationPools[mainApplication.ApplicationPoolName];
            mainApplicationPool["autoStart"] = true;
            mainApplicationPool["startMode"] = "AlwaysRunning";

            serverManager.CommitChanges();
        }

        base.Run();
    }

    public override bool OnStart()
    {
        // For information on handling configuration changes
        // see the MSDN topic at http://go.microsoft.com/fwlink/?LinkId=166357.

        return base.OnStart();
    }
}

Note: To use ServerManager you will need to:

  • reference C:\Windows\system32\inetsrv\Microsoft.Web.Administration.dll (or available through NuGet)
  • add <Runtime executionContext="elevated" /> in your Service Definition under the WebRole element
Rob Church
  • 6,783
  • 3
  • 41
  • 46
Sandrino Di Mattia
  • 24,739
  • 2
  • 60
  • 65
  • any chance to do the same with a config file? – Jordi Dec 04 '12 at 13:43
  • I don't have WebRole.cs on my project but I tried to do that on the Application_Start of the global.asax. The code raises an exception: UnauthorizedAccessException was unhandled by user code. Filename: redirection.config. Error: Cannot read configuration file due to insufficient permissions – Jordi Dec 04 '12 at 14:11
  • 3
    Simply add the WebRole.cs file to your web role. Also make sure you add the following element `` in your Service Definition under the WebRole element. Application_Start is part of the web application that runs in IIS, you shouldn't be making changes to IIS from there. – Sandrino Di Mattia Dec 04 '12 at 14:20
  • service re-deployed. I will wait 24 hours before give it the accepted :) – Jordi Dec 04 '12 at 14:50
  • This solution is partial. In order to solve that problem, please check this other question: http://stackoverflow.com/questions/14238569/force-application-start-on-azure-web-role – Jordi Jan 11 '13 at 08:31
  • As the code basically modifies `applicationHost.config`, what's the point putting the code into `Run()` instead of `OnStart()` method? – eXavier May 30 '14 at 15:51
3

While Sandrino's solution might work... here is a solution that does not require the web role to run in elevated security mode, and also will force the application to start when the webrole starts (before the first user visits the site). This solution will also work on older versions of IIS/Windows Server that does not require IIS 8's "Application Initialization" feature.

Just add a WebRole.cs with the following content:

using System;
using System.Net;
using System.Net.Security;
using System.Threading;
using Microsoft.WindowsAzure.ServiceRuntime;

namespace Website
{
    public class WebRole : RoleEntryPoint
    {
        public override bool OnStart()
        {
            WarmUpWebsite("HttpIn");
            return base.OnStart();
        }

        public override void Run()
        {
            while (true)
            {
                WarmUpWebsite("HttpIn");
                Thread.Sleep(TimeSpan.FromMinutes(1));
            }
        }

        public void WarmUpWebsite(string endpointName)
        {
            // Disable check for valid certificate. On som sites live HTTP request are redirected to HTTPS endpoint. And when running on staging SSL the certificate is invalid.
            RemoteCertificateValidationCallback allowAllCertificatesCallback = (sender, certificate, chain, sslPolicyErrors) => true;
            ServicePointManager.ServerCertificateValidationCallback += allowAllCertificatesCallback;
            try
            {
                RoleInstanceEndpoint endpoint = RoleEnvironment.CurrentRoleInstance.InstanceEndpoints[endpointName];

                string address = String.Format("{0}://{1}:{2}", endpoint.Protocol, endpoint.IPEndpoint.Address, endpoint.IPEndpoint.Port);

                //This will cause Application_Start in global.asax to run
                new WebClient().DownloadString(address);
            }
            catch (Exception)
            {
                // intentionally swallow all exceptions here.
            }
            ServicePointManager.ServerCertificateValidationCallback -= allowAllCertificatesCallback;
        }
    }
}

Credits goes to: http://weblogs.thinktecture.com/cweyer/2011/01/poor-mans-approach-to-application-pool-warm-up-for-iis-in-a-windows-azure-web-role.html

The while(true) could be replaced with Sandrino's approach or you could disable application pool idle timeout: http://blog.smarx.com/posts/controlling-application-pool-idle-timeouts-in-windows-azure

Thomas Jespersen
  • 11,493
  • 14
  • 47
  • 55
  • I will try it in the next occasion. Thanks – Jordi Mar 18 '14 at 13:27
  • This seems to help stop my web role going to sleep after 20 minutes of activity, but doesn't seem to help the initial startup, or subsequent restarts when the role is recycled after 29 hours. The first hit then takes about 50 seconds again. – p10ben Dec 11 '16 at 22:27