24

To prevent AppPool recycling every 20 minutes, I'd like to remove IIS AppPool Idle Timeouts when my Azure Web Role starts. My website is a Web Application Project.

How do I do this?

Albert Bori
  • 9,832
  • 10
  • 51
  • 78

6 Answers6

32

Create a startup task to disable the idle timeout:

  1. In the website project referenced by your web role project, add a file Startup.cmd to the root folder.

  2. In the properties for Startup.cmd, set Copy to Output Directory to Copy if newer.

  3. Add this line to Startup.cmd:

    if exist %windir%\system32\inetsrv\appcmd.exe %windir%\system32\inetsrv\appcmd set config -section:applicationPools -applicationPoolDefaults.processModel.idleTimeout:00:00:00
    

    The if exist %windir%\system32\inetsrv\appcmd.exe qualifier is optional. It lets you use the same code on the Azure Emulator Express, so you don't need IIS installed or need to run Visual Studio as Administrator.

  4. Save the file as UTF-8 without signature. (File > Advanced Save Options in Visual Studio.)

  5. In your web role project, in ServiceDefinition.csdef, add this to the WebRole:

    <Startup>
      <Task commandLine="Startup.cmd" executionContext="elevated" />
    </Startup>
    
DeepSpace101
  • 13,110
  • 9
  • 77
  • 127
Edward Brey
  • 40,302
  • 20
  • 199
  • 253
  • 3
    +1 For very useful answer. But you are missing the 1st parameter -section:applicationPools – huha Apr 30 '14 at 09:13
  • Because the role wasn't starting emulated locally I had to find the reason. I find this article https://azure.microsoft.com/en-us/documentation/articles/cloud-services-startup-tasks-common/ and followed the tips there. Adding `EXIT /B 0` on the second line of command solved the problem. I suspect, that if you run Visual Studio not elevated, the command fails, and prevents the role from beeing started. I rather prefer role started even with timeouts :-). – Zoka May 12 '16 at 20:33
4

Another option is to configure IIS Idle Time-Out Action to 'Suspend'. You can do it as a part of your web role startup script.

Command that you need is on the box as part of IIS setup (note that this will work with Windows Server 2012 R2 and up, with your code targeting .NET 4.5.1 framework and higher).

%windir%\system32\inetsrv\appcmd set config -section:applicationPools -applicationPoolDefaults.processModel.idleTimeoutAction:Suspend

You'll have to update your Azure Cloud Service configuration file (.cscfg) to use OS Family 4, as outlined by scottgu in his blog post.

Since startup actions run when your instances are provisioned and before web application is deployed to IIS, by setting application pool defaults will defacto set your application apppool idel time out action to Suspend.

Sean Feldman
  • 23,443
  • 7
  • 55
  • 80
  • Be careful with this solution, though, as it *suspends* the whole process (unlike Edward Brey's solution?). If you have long running background tasks, they'll be suspended and first execute after a new web request. – Sebastian Krysmanski Sep 01 '14 at 12:28
2

In the root of your Web Application Project, create a file named WebRole.cs with the following code:

public class WebRole : RoleEntryPoint
{
    public override void Run()
    {
        RemoveIISTimeouts();
        base.Run();
    }

    private void RemoveIISTimeouts()
    {
        Process.Start(
            String.Format(@"{0}\system32\inetsrv\appcmd", Environment.GetEnvironmentVariable("windir")),
            "set config -section:applicationPools -applicationPoolDefaults.processModel.idleTimeout:00:00:00");
    }
}
Albert Bori
  • 9,832
  • 10
  • 51
  • 78
  • 1
    You could just as well use a startup task .cmd for that. – sharptooth Aug 07 '13 at 05:00
  • 1
    By putting the config command in a `RoleEntryPoint.Run` override, does that mean you have to mark the web role as requiring elevated permissions? If so that would be an advantage of using a startup task, as @sharptooth suggested. – Edward Brey Dec 11 '13 at 14:39
  • I haven't run into any permissions issues with this approach. No permissions modifications were required. – Albert Bori Dec 11 '13 at 18:25
  • @Albert: Perhaps your web role was already running with elevated privileges? The [Appcmd.exe](http://technet.microsoft.com/en-us/library/cc730918(v=ws.10).aspx) docs say "Appcmd.exe resides in the %windir%\system32\inetsrv directory, which is available only to the Administrator account or to users who are members of the Administrators group on the computer." – Edward Brey Jan 07 '14 at 15:25
  • The startup command is running in elevated context - not the web role. executionContext="elevated" – Software Developer Oct 02 '14 at 19:42
2

Don't bother. You should really have a monitoring solution for your web role anyway. And now that it's built into the Azure dashboard, it's easier to turn on monitoring than to get the idle timeout configuration right (especially if you want to maintain least privilege).

Edward Brey
  • 40,302
  • 20
  • 199
  • 253
  • 3
    I went down the endpoint monitoring route, but what I found was that the problem still occurred when I had several instances, so I guess each instance wasn't being hit often enough by the monitoring. Any way around that? – Ian1971 Dec 09 '14 at 10:53
  • Sorry for the downvote, but the setting exists and is there to be used directly so I see no reason to use endpoint monitoring as a workaround. As demonstrated in Ian's comment the workaround isn't always ideal and there may be other scenario when it doesn't work (e.g. if you're not using round-robin load balancing). – sham Apr 05 '16 at 22:04
  • @sham Keep in mind that this isn't intended as a universal solution, just a viable option for certain scenarios. Since the settings-based approach can be substantial effort to implement, monitoring may even be the "best" solution, if it means no incremental effort and happens to do the job. – Edward Brey Apr 05 '16 at 22:11
1

In addition to @Edward Brey answer, If you want to change other common settings in that startup script, here's how you do that

rem Preload
%windir%\system32\inetsrv\appcmd list app /xml | %windir%\system32\inetsrv\appcmd set site /in -applicationDefaults.preloadEnabled:True

rem Disable idle
%windir%\system32\inetsrv\appcmd set config -section:applicationPools -applicationPoolDefaults.processModel.idleTimeout:00:00:00

rem Auto start
%windir%\system32\inetsrv\appcmd set config -section:applicationPools -applicationPoolDefaults.autoStart:true

rem Always running
%windir%\system32\inetsrv\appcmd set config -section:applicationPools -applicationPoolDefaults.startMode:AlwaysRunning

rem Disable recycling
%windir%\system32\inetsrv\appcmd set config -section:applicationPools -applicationPoolDefaults.recycling.periodicRestart.time:00:00:00

To see a list of available options per section, do

%windir%\system32\inetsrv\appcmd set config -section:applicationPools -?
illegal-immigrant
  • 8,089
  • 9
  • 51
  • 84
0

This is the approach I took:

using (ServerManager iisManager = new ServerManager())
{
    Application app = iisManager.Sites[RoleEnvironment.CurrentRoleInstance.Id + "_Web"].Applications[0];

    TimeSpan ts = new TimeSpan(0, 00, 00);

    iisManager.ApplicationPoolDefaults.ProcessModel.IdleTimeout = ts;

    iisManager.CommitChanges();
}

Requires:

using Microsoft.Web.Administration;
using Microsoft.WindowsAzure.ServiceRuntime;
artfulhacker
  • 4,823
  • 1
  • 37
  • 31