【Azure 云服务】在Cloud Service的代码中如何修改IIS Application Pool的配置呢? 比如IdleTimeout, startMode, Recycling.PeriodicRestart.Time等

什么是 PaaS?Platform as a Service 

平台即服务 (PaaS) 是云中的完整开发和部署环境,你可以使用其中资源交付内容,从基于云的简单应用到启用云的复杂企业应用程序皆可。你以即用即付的方式从云服务提供商处购买所需资源,并通过安全的 Internet 连接访问这些资源。

 

类似 IaaS,PaaS 也包括服务器、存储空间和网络等基础结构,但它还包括中间件、开发工具、商业智能 (BI) 服务和数据库管理系统等。PaaS 旨在支持 Web 应用程序的完整生命周期:生成、测试、部署、管理和更新。

 

PaaS 让你无需购买和管理软件许可证、底层应用程序基础结构和中间件、容器业务流程协调程序(如 Kubernetes)或开发工具及其他资源,从而避免了开支和复杂操作。你管理自己开发的应用程序和服务,剩余事项一般由云服务提供商负责。

 

来源://azure.microsoft.com/en-us/overview/what-is-paas/

问题描述

Azure Cloud Service: 是平台即服务 (PaaS) 的一个示例,是一项基于 HTTP 的服务,用于托管 Web 应用程序、REST API 和移动后端 。它托管在虚拟机 (VM) 上,通过 IIS 自动部署和托管应用。

所以,当我们想要修改IIS的一些默认的配置时,如何操作呢?

  • IdleTimeout: 默认值为20分钟,如果在20分钟Site不活动的情况下(没有新请求进入),IIS将终止工作进程以释放资源。
  • Start Mode:工作进程启动模式, AlwaysRunning(一直运行:如果Application Pool正在运行,请立即启动w3wp.exe进程。)  OnDemand(按需启动:如果Application Pool正在运行,则在有第一个入站应用程序请求时启动w3wp.exe进程)
  • Recycling.PeriodicRestart.Time(Regular Time Interval):默认值为1740分钟,29小时。当Application Pool每运行29小时后,会自动回收。然后重启Application Pool。

在部署云服务(Cloud Service)时,有多种方式实现以上的修改。如添加启动任务通过CMD命令修改IIS配置(见文末附件部分),或通过代码修改,在WebRole的OnStart()方法中实现(本文就介绍代码如何实现)。

 

实现代码

准备条件:参考官方快速入门,使用VS 2019快速创建Cloud Service项目(Azure 云服务(经典)和 ASP.NET 入门

第一步:在WebRole.cs文件 OnStart()方法中加入对Servicer Manager的修改代码。在使用时候,需要引用Microsoft.Web.Administration.dll。文件路径为:C:\Windows\System32\inetsrv\Microsoft.Web.Administration.dll

 

第二步:修改IIS Application Pool

  1. preloadEnabled:设置为ture,当Application Pool启动时,会自动想站点发送一个假请求。使得W3WP.EXE进程启动,当真实的第一个请求进入时马上进入业务处理,而避免为启动站点而消耗的时间。它与startMode=”AlwaysRunning”配合
  2. startMode:设置为AlwaysRunning
  3. IdleTimeout:设置为0,表示没有闲置时间,W3WP.EXE进程不会自动终止
  4. PeriodicRestart Time:设置为0,表示Applicaiton Pool不进行回收。
  5. periodicRestart schedule:设置为05:00:00, 表示每天早上5点计划重启Application Pool。
        public override bool OnStart()
        {
            ServicePointManager.DefaultConnectionLimit = 12;
            if (!RoleEnvironment.IsEmulated)
            {
                using (ServerManager serverManager = new ServerManager())
                {
                    // 1.参照https://stackoverflow.com/questions/24676194/azure-web-role-warm-up-strategies
                    foreach (var app in serverManager.Sites.SelectMany(x => x.Applications))
                    {
                        app["preloadEnabled"] = true;
                    }
                    foreach (var appPool in serverManager.ApplicationPools)
                    {
                        appPool.AutoStart = true;
                        appPool["startMode"] = "AlwaysRunning";
                        appPool.ProcessModel.IdleTimeout = TimeSpan.Zero;
                        appPool.Recycling.PeriodicRestart.Time = TimeSpan.Zero;

                        //// 2.参照//docs.microsoft.com/en-us/iis/configuration/system.applicationhost/applicationpools/add/recycling/periodicrestart/
                        //// < recycling logEventOnRecycle = "Schedule" >
                        ////  < periodicRestart >
                        ////   < schedule >
                        ////     < add value = "03:00:00" />
                        ////   </ schedule >
                        ////  </ periodicRestart >
                        //// </ recycling >
                        ConfigurationElement periodicRestartElement = appPool.Recycling.GetChildElement("periodicRestart");
                        ConfigurationElementCollection scheduleCollection = periodicRestartElement.GetCollection("schedule");
                        ConfigurationElement addElement1 = scheduleCollection.CreateElement("add");
                        addElement1["value"] = TimeSpan.Parse("05:00:00");
                        scheduleCollection.Add(addElement1);
                    }
                    serverManager.CommitChanges();
                }
            }
            // For information on handling configuration changes
            // see the MSDN topic at //go.microsoft.com/fwlink/?LinkId=166357.
            return base.OnStart();
        }

 

第三步:提交修改 ( serverManager.CommitChanges();)

 

第四步:在部署的时候,由于修改IIS配置需要提升权限,所以在发布时候需要在WebRole的配置文件(ServiceDefinition.csdef)中设置 <Runtime executionContext=”elevated” />

  

发布后RDP到示例中验证

 

附录一:使用启动任务方式修改IIS配置

(引用://blog.nilayparikh.com/azure/development/using-startup-task-to-manage-application-pool-settings-in-azure-web-role/

Follow the simple steps to gain granular control over Web Role process.

  1. Create Startup.cmd to the project root folder referenced by your web role project.

  2. Change content properties to Copy if newer for Startup.cmd

  3. Add following code to Startup.cmd – as needed.

    Disable idle

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

    Auto start

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

    Always running

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

    Disable recycling

      %windir%\system32\inetsrv\appcmd set config -section:applicationPools -applicationPoolDefaults.recycling.periodicRestart.time:00:00:00
    
  4. Save the file as UTF-8 without a signature. (Tip: File Menu > Advanced Save Options in Visual Studio.)

  5. Test the same in Azure Emulator Express – making sure that the code is not breaking anything.

  6. Modify ServiceDefinition.csdef to add the task and elevated attribute.

    <ServiceDefinition name="NilayCornerService" xmlns="//schemas.microsoft.com/ServiceHosting/2008/10/ServiceDefinition">
        <WorkerRole name="NilayCornerWorkerRole1">
            ...
            <Startup>
                <Task commandLine="Startup.cmd" executionContext="elevated" taskType="simple" />
            </Startup>
        </WorkerRole>
    </ServiceDefinition>
    

Tip for advanced usage

To see a list of available options per section, try the following command

%windir%\system32\inetsrv\appcmd set config -section:applicationPools -?

附录二:部署时遇见的错误

Unhandled Exception: Filename: Error: Unrecognized element ‘recycling’ at Microsoft.Web.Administration.Interop.IAppHostElement.GetElementByName(String bstrSubName) at Microsoft.Web.Administration.ConfigurationElement.GetChildElement(String elementName) at WebRole1.WebRole.OnStart() in C:\Users\bulu\source\repos\AzureCloudService3\WebRole1\WebRole.cs:line 43 at Microsoft.WindowsAzure.ServiceRuntime.RoleEnvironment.InitializeRoleInternal(RoleType roleTypeEnum) at Microsoft.WindowsAzure.ServiceRuntime.Implementation.Loader.RoleRuntimeBridge.<InitializeRole>b__0() at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx) at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx) at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state) at System.Threading.ThreadHelper.ThreadStart() ‘ [2021-03-25T08:47:15Z] Last exit time: [2021/03/25, 08:47:15.149]. Last exit code: 0.

代码中出现重复获取Recycling节点

ConfigurationElement periodicRestartElement = appPool.Recycling.GetChildElement(“recycling”).GetChildElement(“periodicRestart”);

修改为

ConfigurationElement periodicRestartElement = appPool.Recycling.GetChildElement(“periodicRestart”); 

修改后,问题消失。

 

参考资料

IIS: Idle Timeout vs Recycle//stackoverflow.com/questions/19985710/iis-idle-timeout-vs-recycle

Azure Web Role “warm up” strategies [closed]//stackoverflow.com/questions/24676194/azure-web-role-warm-up-strategies

Periodic Restart Settings for Application Pool Recycling <periodicRestart>//docs.microsoft.com/en-us/iis/configuration/system.applicationhost/applicationpools/add/recycling/periodicrestart/

Azure 云服务(经典)和 ASP.NET 入门//docs.azure.cn/zh-cn/cloud-services/cloud-services-dotnet-get-started