应用程序池的进程模型设置 <processModel>

概述

通过使用 <processModel> 元素,可以在 IIS 7 及更高版本上配置应用程序池的许多安全性、性能、运行状况和可靠性功能。 包括以下这些功能:

  • 应用程序池标识,它是运行应用程序池工作进程的服务或用户帐户的名称。 由 identityType 属性定义。 默认情况下,从 IIS 7.5 开始,应用程序池在内置的 ApplicationPoolIdentity 帐户下运行,该帐户是由 Windows Process Activation Service (WAS) 动态创建的。 (在 IIS 7.0 中,默认标识为 NetworkService 帐户。)可以将 identityType 属性值更改为内置 NetworkService 帐户、LocalService 帐户、内置 LocalSystem 帐户或创建的自定义帐户。 如果选择自定义帐户,请使用 userName 和 password 属性定义帐户凭据。 但请注意,NetworkService、LocalService 和 LocalSystem 帐户的用户权限比 ApplicationPoolIdentity 帐户多。 (警告:使用高级用户权限运行应用程序池存在严重安全风险。)此外,可以使用 logonType 属性指定进程标识应以批处理用户还是服务身份进行登录。 (有关登录类型的其他信息,请参阅 LogonUser 函数一文。)
  • Web 园艺和使用非一致性内存访问 (NUMA) 硬件,可以通过设置 maxProcesses 属性进行配置。 对于 Web 园艺,请将 maxProcesses 设置为大于 1 的值。 要使用 NUMA 硬件,请将 maxProcesses 设置为值“0”,以指定 IIS 运行与 NUMA 节点数量相同的工作进程
  • 空闲超时设置,用于设置工作进程在关闭之前保持空闲状态的时间。 编辑 idleTimeout 属性可配置此设置
  • 运行状况监视,通过启用针对工作进程的 ping,工作进程响应 ping 的最长时间,以及发送到工作进程以监视其运行状况的 ping 的频率,从而进行运行状况监视。 编辑 pingingEnabled、pingInterval 和 pingResponseTime 属性可配置这些设置
  • 工作进程关闭和启动时间限制。 第一个限制由 shutdownTimeLimit 属性设置,可确定 IIS 7 及更高版本在 WWW 服务终止工作进程之前提供给工作进程完成所有请求的时间间隔。 第二个限制由 startupTimeLimit 属性设置,可指定 IIS 7 及更高版本允许应用程序池启动的时间

兼容性

版本 说明
IIS 10.0 <processModel> 元素在 IIS 10.0 中未进行修改。
IIS 8.5 由于添加了 idleTimeoutAction 属性,因此可选择终止或暂停在 idleTimeout 属性持续时间内处于空闲状态的工作进程,而不仅仅是终止。
IIS 8.0 由于添加了 setProfileEnvironment 属性,因此可基于新进程的用户配置文件设置环境。 为 maxProcesses 属性添加了值,包括对非一致性内存访问 (NUMA) 的支持。 添加了 logEventOnProcessModel 属性,可指定在记录进程时执行的操作。
IIS 7.5 IIS 7.5 中更新了 <add> 元素的 <processModel> 元素,以包含允许使用新的 ApplicationPoolIdentity 运行应用程序的设置,并指定进程标识的登录类型
IIS 7.0 <processModel> 元素是在 IIS 7.0 中引入的。
IIS 6.0 <processModel> 元素替换了 IIS 6.0 IIsApplicationPools 元数据库对象中的一些设置

安装

<applicationPools> 集合包含在 IIS 7 及更高版本的默认安装中。

操作方式

如何编辑进程模型配置设置

  1. 打开“Internet Information Services (IIS)管理器”:

    • 如果使用的是 Windows Server 2012 或 Windows Server 2012 R2:

      • 在任务栏上,单击“服务器管理器”,单击“工具”,然后单击“Internet Information Services (IIS)管理器”
    • 如果使用的是 Windows 8 或 Windows 8.1:

      • 按住 Windows 徽标键,按字母 X,然后单击“控制面板”
      • 单击“管理工具”,然后双击“Internet Information Services (IIS)管理器”
    • 如果使用的是 Windows Server 2008 或 Windows Server 2008 R2:

      • 在任务栏上,单击“开始”,指向“管理工具”,然后单击“Internet Information Services (IIS)管理器”
    • 如果使用的是 Windows Vista 或 Windows 7:

      • 在任务栏上,单击“开始”,然后单击“控制面板”
      • 双击“管理工具”,然后双击“Internet Information Services (IIS)管理器”
  2. 在“连接”窗格中,展开服务器名称,单击“应用程序池”,然后单击要编辑的应用程序池Screenshot of the I I S Manager window displaying the Application Pools page.

  3. 在“操作”窗格中,单击“高级设置...”

  4. 在“高级设置”对话框中,单击要编辑的进程模型属性,然后在对话框的“属性值”部分进行编辑,然后单击“确定”。 例如,将“关闭时间限制(秒)”和“启动时间限制(秒)”更改为“30”
    Screenshot of the Advanced Settings dialog box. Process Model is highlighted.

如何配置 IIS 以使用非一致性内存访问 (NUMA) 硬件

  1. 打开“Internet Information Services (IIS)管理器”:

    • 如果使用的是 Windows Server 2012 或更高版本:

      • 在任务栏上,单击“服务器管理器”,单击“工具”,然后单击“Internet Information Services (IIS)管理器”
    • 如果使用的是 Windows 8 或更高版本:

      • 按住 Windows 徽标键,按字母 X,然后单击“控制面板”
      • 单击“管理工具”,然后双击“Internet Information Services (IIS)管理器”
  2. 在“连接”窗格中,展开服务器名称,然后单击“应用程序池”

  3. 在“应用程序池”窗格中,选择要为 NUMA 配置的池

  4. 在“操作”窗格中,选择“高级设置”

  5. 在“进程模型”窗格中,将“最大工作进程数”设置为 0

    Screenshot of the Advanced Settings pane. Maximum Worker Processes is highlighted in the list.

如何配置空闲超时操作

  1. 打开“Internet Information Services (IIS)管理器”:

    • 如果使用的是 Windows Server 2012 R2:

      • 在任务栏上,单击“服务器管理器”,单击“工具”,然后单击“Internet Information Services (IIS)管理器”
    • 如果使用的是 Windows 8.1:

      • 按住 Windows 徽标键,按字母 X,然后单击“控制面板”
      • 单击“管理工具”,然后双击“Internet Information Services (IIS)管理器”
  2. 在“连接”窗格中,双击服务器名称,双击“应用程序池”,然后选择要配置的应用程序池

  3. 在“操作”窗格中,单击“高级设置”

  4. 在“高级设置”对话框的“进程模型”部分中,对于“idleTimeoutAction”,请选择“终止”或“暂停”

  5. 单击“确定”。

    Screenshot of the Advanced Settings dialog box. Idle Time out-Action is highlighted and Terminate is selected in the drop down menu.

配置

可以在 ApplicationHost.config 文件中的服务器级别配置 <processModel> 元素。

特性

属性 说明
identityType 可选枚举属性。

指定运行应用程序池的帐户标识。

注意:从 IIS 7.5 开始,默认值为 ApplicationPoolIdentity。 (在 IIS 7.0 中,默认值为 NetworkService。)

identityType 属性可以是下列可能值之一;默认值为 NetworkService

说明
ApplicationPoolIdentity 指定应用程序池在动态创建的应用程序池标识帐户下运行。 从 IIS 7.5 开始,ApplicationPoolIdentity 是运行应用程序池的默认标识。 (在 IIS 7.0 中,默认标识为 NetworkService。)

当应用程序池在 ApplicationPoolIdentity 帐户下运行时,应用程序池将以“IIS AppPool<AppPool>”标识访问资源。 例如,对于“DefaultAppPool”,标识为“IIS AppPool\DefaultAppPool”。 此标识允许管理员指定仅与运行应用程序池的标识相关的权限,从而提高服务器的安全性。

数值为 4
LocalService 指定应用程序池在内置 LocalService 帐户下运行,该帐户的用户权限与 NetworkService 相同

当应用程序池在 LocalService 帐户下运行时,应用程序池会在网络上显示匿名凭据

注意:在具有高级用户权限的帐户下运行应用程序池存在严重安全风险。

数值为 1
LocalSystem 指定应用程序池在内置 LocalSystem 帐户下运行,该帐户在本地计算机上具有广泛的特权,并充当网络上的计算机

注意:在具有高级用户权限的帐户下运行应用程序池存在严重安全风险。

数值为 0
NetworkService 指定应用程序池在内置 NetworkService 帐户下运行。 在 IIS 7.0 中,这是运行应用程序池时的默认标识;IIS 7.5 中的默认值已更改为 ApplicationPoolIdentity

当应用程序池在 NetworkService 帐户下运行时,应用程序池将以计算机帐户访问网络资源

数值为 2
SpecificUser 指定应用程序池在自定义标识下运行,该标识使用 userName 和 password 属性进行配置

注意:为避免在配置文件中存储未加密的密码字符串,请始终使用 AppCmd.exe 或 IIS 管理器输入密码。 如果使用这些管理工具,密码字符串将在写入 XML 配置文件之前自动进行加密。 与存储未加密的密码相比,这种方式提供的密码安全性更高。

注意:托管服务帐户可用于让服务和任务共享自己的域帐户,并启用自动密码管理,无需管理员手动管理密码。 有关详细信息,请参阅托管服务帐户的新增功能

数值为 3
idleTimeout 可选的 timeSpan 属性。

指定在未收到新请求且工作进程未处理请求时,工作进程应空闲运行的时间(以分钟为单位)。 在分配的时间过后,工作进程应请求 WWW 服务将其关闭。

默认值为 00:20:00

若要禁用空闲超时功能,请将此值设置为 00:00:00
idleTimeoutAction 可选枚举属性。

指定达到空闲超时持续时间时要执行的操作。 在 IIS 8.5 之前,在 idleTimeout 属性持续时间内处于空闲状态的工作进程将被终止。 在 IIS 8.5 之后,可以选择终止达到 idleTimeout 限制的工作进程,或将其从内存移到磁盘从而将其暂停。 与终止进程相比,暂停进程所需的时间和消耗的内存可能更少。

可以使用应用程序初始化的虚假请求配置暂停的空闲超时操作(请参阅 applicationInitialization)。

idleTimeoutAction 属性可能具有以下值。 默认值为 Terminate
说明
Terminate 终止空闲工作进程。 这将导致在用户随后访问站点并启动工作进程时需要更长的启动时间。

数值为 0
Suspend 暂停空闲工作进程。 这样做会让工作进程保持活动状态,但已从内存移动到磁盘,从而减少了系统资源消耗。 当请求随后传入时,内存管理器会将请求所需的页面文件从磁盘加载到内存中,很可能会使工作进程比之前终止的进程更快可用。

数值为 1
loadUserProfile 可选布尔属性。

指定 IIS 是否加载应用程序池标识的用户配置文件。 将此值设置为 false 会导致 IIS 还原为 IIS 6.0 行为。 IIS 6.0 不会加载应用程序池标识的用户配置文件。

默认值为 false
logEventOnProcessModel 可选标志属性。

指定进程中采取的哪些操作会被记录到事件查看器中。 在 IIS 8.0 中,应用的唯一操作是空闲超时操作,在该操作中,进程因在 idleTimeout 期间处于空闲状态而终止。

标志名称等于 IdleTimeout。 值为 1

默认值为 IdleTimeout
logonType 可选枚举属性。

指定进程标识的登录类型。 (有关登录类型的其他信息,请参阅 LogonUser 函数一文。)

注意:此属性是在 IIS 7.5 中引入的。

logonType 属性可以是下列可能值之一;默认值为 LogonBatch
说明
LogonBatch 指定应用程序池标识应以批处理用户身份登录。

数值为 0
LogonService 指定应用程序池标识应以服务身份登录。

数值为 1
manualGroupMembership 可选布尔属性。

指定是否将 IIS_IUSRS 组安全标识符 (SID) 添加到工作进程令牌。 如果为 false,IIS 会自动使用应用程序池标识,就像它是内置 IIS_IUSRS 组的成员一样,该组有权访问必要的文件和系统资源。 如果为 true,必须将应用程序池标识显式添加到工作进程在运行时所需的所有资源中

默认值为 false
maxProcesses 可选 uint 属性。

指示应用程序池使用的工作进程的最大数目。
  • 值为“1”表示应用程序池最多只有一个工作进程。 这将是在没有 NUMA 节点的服务器上的设置。
  • 值为“2”或更大表示 Web 园可在应用程序池中使用多个工作进程(如有必要)。
  • 值为“0”指定 IIS 运行的工作进程数与非一致性内存访问 (NUMA) 节点的数量相同。 IIS 标识硬件上可用的 NUMA 节点数,并启动相同数量的工作进程。 例如,如果有四个 NUMA 节点,那么该应用程序池最多只能使用四个工作进程。 在此示例中,将 maxProcesses 设置为值“0”或“4”会产生相同的结果。
默认值为 1
password 可选的字符串属性。

指定与 userName 属性关联的密码。 仅当 identityType 的值为 SpecificUser 时,才需要此属性

注意:为避免在配置文件中存储未加密的密码字符串,请始终使用 AppCmd.exe 或 IIS 管理器输入密码。 如果使用这些管理工具,密码字符串将在写入 XML 配置文件之前自动进行加密。 与存储未加密的密码相比,这种方式提供的密码安全性更高。
pingingEnabled 可选布尔属性。

指定是否为工作进程启用 ping。

默认值为 true
pingInterval 可选的 timeSpan 属性。

指定 WWW 服务向工作进程发送运行状况监视 ping 的间隔时间。

默认值为 00:00:30(30 秒)。
pingResponseTime 可选的 timeSpan 属性。

指定工作进程响应运行状况监视 ping 的时间。 超过时间限制后,WWW 服务将终止工作进程。

默认值为 00:01:30(1 分 30 秒)。
requestQueueDelegatorIdentity 可选的 String 属性。

指定有权将 HTTP 请求委托给应用程序池的帐户标识。

注意:此属性在 Internet Information Services (IIS) 管理器 UI 中不可用。
setProfileEnvironment 可选布尔属性。

当 setProfileEnvironment 设置为 True 时,WAS 将创建一个环境块,以便在创建工作进程时传递给 CreateProcessAsUser。 这可确保根据新进程的用户配置文件设置环境。

默认值为 True
shutdownTimeLimit 可选的 timeSpan 属性。

指定 W3SVC 服务在启动回收后等待的时间。 如果工作进程未在 shutdownTimeLimit 内关闭,则 W3SVC 服务将终止该进程

默认值为 00:01:30(1 分 30 秒)。
startupTimeLimit 可选的 timeSpan 属性。

指定 IIS 等待应用程序池启动的时间。 如果应用程序池未在 startupTimeLimit 内启动,则会终止工作进程,并递增快速失败保护计数

默认值为 00:01:30(1 分 30 秒)。
userName 可选的字符串属性。

指定在 identityType 为 SpecificUser 时应用程序池的运行标识

子元素

无。

配置示例

以下配置示例使用应用程序池 <add> 元素创建名为 Contoso 的新应用程序池。 <recycling> 元素配置应用程序池重启的日志记录,<periodicRestart> 元素配置应用程序池重启的时间,<processModel> 配置用于关闭和启动应用程序池中的工作进程的 shutdownTimeLimit 和 startupTimeLimit 属性,每个属性都配置为 30 秒。 如果超出这些时间限制,IIS 将终止工作进程。

<add name="Contoso">
   <recycling logEventOnRecycle="Schedule">
      <periodicRestart>
         <schedule>
            <clear />
            <add value="03:00:00" />
         </schedule>
      </periodicRestart>
   </recycling>
   <processModel identityType="NetworkService" shutdownTimeLimit="00:00:30" startupTimeLimit="00:00:30" />
</add>

代码示例

以下示例将名为 Contoso 的应用程序池的 processModel.shutdownTimeLimit 和 processModule.startupTimeLimit 属性值分别更改为 30 秒

AppCmd.exe

appcmd.exe set apppool "Contoso" /processModel.shutdownTimeLimit:00:00:30

appcmd.exe set apppool "Contoso" /processModel.startupTimeLimit:00:00:30

还可以使用以下语法:

appcmd.exe set config -section:system.applicationHost/applicationPools /[name='Contoso'].processModel.shutdownTimeLimit:"00:00:30" /commit:apphost

appcmd.exe set config -section:system.applicationHost/applicationPools /[name='Contoso'].processModel.startupTimeLimit:"00:00:30" /commit:apphost

注意

使用 AppCmd.exe 配置这些设置时,必须确保将 commit 参数设置为 apphost。 这会将配置设置提交到 ApplicationHost.config 文件中的相应位置部分。

C#

using System;
using System.Text;
using Microsoft.Web.Administration;

internal static class Sample
{
   private static void Main()
   {
      using (ServerManager serverManager = new ServerManager())
      {
         Configuration config = serverManager.GetApplicationHostConfiguration();
         ConfigurationSection applicationPoolsSection = config.GetSection("system.applicationHost/applicationPools");
         ConfigurationElementCollection applicationPoolsCollection = applicationPoolsSection.GetCollection();

         ConfigurationElement addElement = FindElement(applicationPoolsCollection, "add", "name", @"Contoso");
         if (addElement == null) throw new InvalidOperationException("Element not found!");

         ConfigurationElement processModelElement = addElement.GetChildElement("processModel");
         processModelElement["shutdownTimeLimit"] = TimeSpan.Parse("00:00:30");
         processModelElement["startupTimeLimit"] = TimeSpan.Parse("00:00:30");

         serverManager.CommitChanges();
      }
   }

   private static ConfigurationElement FindElement(ConfigurationElementCollection collection, string elementTagName, params string[] keyValues)
   {
      foreach (ConfigurationElement element in collection)
      {
         if (String.Equals(element.ElementTagName, elementTagName, StringComparison.OrdinalIgnoreCase))
         {
            bool matches = true;
            for (int i = 0; i < keyValues.Length; i += 2)
            {
               object o = element.GetAttributeValue(keyValues[i]);
               string value = null;
               if (o != null)
               {
                  value = o.ToString();
               }
               if (!String.Equals(value, keyValues[i + 1], StringComparison.OrdinalIgnoreCase))
               {
                  matches = false;
                  break;
               }
            }
            if (matches)
            {
               return element;
            }
         }
      }
      return null;
   }
}

VB.NET

Imports System
Imports System.Text
Imports Microsoft.Web.Administration

Module Sample
   Sub Main()
      Dim serverManager As ServerManager = New ServerManager
      Dim config As Configuration = serverManager.GetApplicationHostConfiguration
      Dim applicationPoolsSection As ConfigurationSection = config.GetSection("system.applicationHost/applicationPools")
      Dim applicationPoolsCollection As ConfigurationElementCollection = applicationPoolsSection.GetCollection
      Dim addElement As ConfigurationElement = FindElement(applicationPoolsCollection, "add", "name", "Contoso")

      If (addElement Is Nothing) Then
         Throw New InvalidOperationException("Element not found!")
      End If

      Dim processModelElement As ConfigurationElement = addElement.GetChildElement("processModel")
      processModelElement("shutdownTimeLimit") = TimeSpan.Parse("00:00:30")
      processModelElement("startupTimeLimit") = TimeSpan.Parse("00:00:30")
      serverManager.CommitChanges()
   End Sub

   Private Function FindElement(ByVal collection As ConfigurationElementCollection, ByVal elementTagName As String, ByVal ParamArray keyValues() As String) As ConfigurationElement
      For Each element As ConfigurationElement In collection
         If String.Equals(element.ElementTagName, elementTagName, StringComparison.OrdinalIgnoreCase) Then
            Dim matches As Boolean = True
            Dim i As Integer
            For i = 0 To keyValues.Length - 1 Step 2
               Dim o As Object = element.GetAttributeValue(keyValues(i))
               Dim value As String = Nothing
               If (Not (o) Is Nothing) Then
                  value = o.ToString
               End If
               If Not String.Equals(value, keyValues((i + 1)), StringComparison.OrdinalIgnoreCase) Then
                  matches = False
                  Exit For
               End If
            Next
            If matches Then
               Return element
            End If
         End If
      Next
      Return Nothing
   End Function


End Module

JavaScript

var adminManager = new ActiveXObject('Microsoft.ApplicationHost.WritableAdminManager');
adminManager.CommitPath = "MACHINE/WEBROOT/APPHOST";
var applicationPoolsSection = adminManager.GetAdminSection("system.applicationHost/applicationPools", "MACHINE/WEBROOT/APPHOST");
var applicationPoolsCollection = applicationPoolsSection.Collection;

var addElementPos = FindElement(applicationPoolsCollection, "add", ["name", "Contoso"]);
if (addElementPos == -1) throw "Element not found!";

var addElement = applicationPoolsCollection.Item(addElementPos);
var processModelElement = addElement.ChildElements.Item("processModel");
processModelElement.Properties.Item("shutdownTimeLimit").Value = "00:00:30";
processModelElement.Properties.Item("startupTimeLimit").Value = "00:00:30";

adminManager.CommitChanges();

function FindElement(collection, elementTagName, valuesToMatch) {
   for (var i = 0; i < collection.Count; i++) {
      var element = collection.Item(i);
      if (element.Name == elementTagName) {
         var matches = true;
         for (var iVal = 0; iVal < valuesToMatch.length; iVal += 2) {
            var property = element.GetPropertyByName(valuesToMatch[iVal]);
            var value = property.Value;
            if (value != null) {
               value = value.toString();
            }
            if (value != valuesToMatch[iVal + 1]) {
               matches = false;
               break;
            }
         }
         if (matches) {
            return i;
         }
      }
   }
   return -1;
}

VBScript

Set adminManager = createObject("Microsoft.ApplicationHost.WritableAdminManager")
adminManager.CommitPath = "MACHINE/WEBROOT/APPHOST"
Set applicationPoolsSection = adminManager.GetAdminSection("system.applicationHost/applicationPools", "MACHINE/WEBROOT/APPHOST")
Set applicationPoolsCollection = applicationPoolsSection.Collection

addElementPos = FindElement(applicationPoolsCollection, "add", Array("name", "Contoso"))
If siteElementPos = -1 Then
   WScript.Echo "Element not found!"
   WScript.Quit
End If

Set addElement = applicationPoolsCollection.Item(addElementPos)
Set processModelElement = addElement.ChildElements.Item("processModel")
processModelElement.Properties.Item("shutdownTimeLimit").Value = "00:00:30"
processModelElement.Properties.Item("startupTimeLimit").Value = "00:00:30"

adminManager.CommitChanges()

Function FindElement(collection, elementTagName, valuesToMatch)
   For i = 0 To CInt(collection.Count) - 1
      Set element = collection.Item(i)
      If element.Name = elementTagName Then
         matches = True
         For iVal = 0 To UBound(valuesToMatch) Step 2
            Set property = element.GetPropertyByName(valuesToMatch(iVal))
            value = property.Value
            If Not IsNull(value) Then
               value = CStr(value)
            End If
            If Not value = CStr(valuesToMatch(iVal + 1)) Then
               matches = False
               Exit For
            End If
         Next
         If matches Then
            Exit For
         End If
      End If
   Next
   If matches Then
      FindElement = i
   Else
      FindElement = -1
   End If
End Function