概述

<cpu>集合中 <applicationPools> 元素的 <add> 元素配置将在应用程序池中使用的 CPU 使用率参数和 CPU 操作的值。

NUMA 支持

非统一内存访问 (NUMA) 是基于硬件的方法,用于将处理器与其自己的专用内存相关联。 NUMA 用于提高处理器速度,作为传统对称多处理器 (SMP) 模型的替代方法,以支持多处理器。 可以设置 IIS 8 及更高版本,以在 NUMA 上分发和关联其进程。 NUMA 的使用在 CPU 元素中由 numaNodeAssignment 属性配置,该属性允许 IIS 在 IIS 工作进程即将启动时标识最佳 NUMA 节点,numaNodeAffinityMode 属性确定 IIS 工作进程中的线程如何关联到 NUMA 节点。 NUMA 还使用 processModel 元素的 MaxProcesses 属性进行配置,如果设置为 0 ,则指定 IIS 自动运行与 NUMA 节点相同的工作进程数。 有关详细信息,请参阅 NUMA 硬件上的 IIS 8.0 多核缩放。

仅当 IIS 在 NUMA 硬件上运行时,才能在 “高级设置” 对话框中设置 NUMA 选择逻辑和关联类型。

兼容性

版本备注
IIS 10.0未 <cpu> 在 IIS 10.0 中修改元素。
IIS 8.5未 <cpu> 在 IIS 8.5 中修改 元素。
IIS 8.0向 属性添加了 action 两个枚举值来定义限制行为。 processorGroup添加了 属性以定义使用的处理器组数。 numaNodeAssignment添加了 和 numaNodeAffinityMode 属性以指定 NUMA 节点的行为。
IIS 7.5未 <cpu> 在 IIS 7.5 中修改元素。
IIS 7.0元素 <cpu> 是在 IIS 7.0 中引入的。
IIS 6.0元素 <cpu> 替换 IIS 6.0 IIsApplicationPools 元数据库属性的一部分。

设置

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

操作方式

如何编辑 CPU 配置设置

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

    • 在任务栏上,单击“开始”,然后单击“控制面板”。

    • 双击“ 管理工具”,然后双击“ Internet Information Services (IIS) 管理器”。

    • 在任务栏上,单击“ 开始”,指向 “管理工具”,然后单击“ Internet Information Services (IIS) 管理器”。

    • 按住 Windows 键,按字母 X,然后单击“控制面板”。

    • 单击 “管理工具”,然后双击“ Internet Information Services (IIS) 管理器”。

    • 在任务栏上,依次单击“服务器管理器”、“工具”和“Internet Information Services (IIS) 管理器”。

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

    • 如果你使用的是 Windows 8 或 Windows 8.1:

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

    • 如果你使用的是 Windows Vista 或 Windows 7:

    • 在“ 连接 ”窗格中,展开服务器名称,单击“ 应用程序池”,然后单击要编辑的应用程序池。
      从“连接”窗格填充的“应用程序池”屏幕的屏幕截图。

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

    • 在 “高级设置” 对话框中,单击要编辑的 CPU 属性,然后编辑对话框的“属性值”部分中的值,然后单击“ 确定”。 例如,可以将 限制操作 更改为 NoAction、 KillW3wp、 Throttle 或 ThrottleUnderLoad
      “高级设置”对话框的“负载下限制”部分的屏幕截图。

    如何配置 IIS 以用于非统一内存访问 (NUMA) 硬件

    1. 在任务栏上,依次单击“服务器管理器”、“工具”和“Internet Information Services (IIS) 管理器”。

    2. 在“ 连接 ”窗格中,展开服务器名称,然后单击“ 应用程序池”。

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

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

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

      “进程模型”部分的屏幕截图,其中“最大工作进程数”字段设置为 0。

    6. 在 “CPU”下,设置 processorGroup、 numaNodeAffinityMode 和 numaNodeAssignment

    7. 单击 “确定” 。

    配置

    属性

    属性说明
    action可选的枚举属性。 配置 IIS 在工作进程超出其配置的 CPU 限制时执行的操作。 操作属性基于每个应用程序池进行配置。

    操作属性可以是以下可能的值之一。 默认值为 NoAction

    值说明NoAction超过 CPU 限制时不执行任何操作。 警告将写入事件日志。数值为 0。KillW3wp超过其 CPU 限制的应用程序池工作进程将被强制关闭。数值为 1。ThrottleCPU 消耗限制为“限制”中设置的值。 不使用限制间隔,并生成事件日志条目。数值为 2。ThrottleUnderLoad仅当 CPU 上存在争用时,CPU 消耗才受到限制。 不使用限制间隔,并生成事件日志条目。数值为 3。
    limit可选 uint 属性。 配置允许应用程序池中的工作进程在一段时间内使用的最大 CPU 时间百分比, (百分比(百分之一)) ,如 resetInterval 属性所示。 如果超出由 limit 属性设置的限制,则会将事件写入事件日志,并可以触发一组可选的事件。 这些可选事件由操作属性确定。

    注意: 在 IIS 8.5 及更高版本中,在 IIS 管理器的 CPU 窗格中设置百分比 限制 。 在 IIS 8.0 中,在 IIS 管理器的 CPU 窗格中将 限制 设置为百分之一的 1/1000。 在这两种情况下, limit applicationHost.config 中的 属性均为百分之一的 1/1000。

    默认值 0为 ,这会禁用 CPU 限制。
    numaNodeAffinityMode可选的枚举属性。 指定如何在节点的核心上计划与 NUMA 节点关联的进程的线程。

    numaNodeAffinityMode 属性可以是以下可能的值之一。 默认值为 Soft

    值说明Soft只要进程关联到的 NUMA 节点中的核心可用,进程的所有线程都将在这些核心上计划。 但是,如果计划程序不能在关联到的节点的核心上计划进程,则可以在另一个 NUMA 节点的核心上计划进程。数值为 0。Hard与 NUMA 节点关联的进程的任何线程都将在节点的核心(仅这些核心)上进行计划。 进程不会在另一个 NUMA 节点的核心上计划该进程的线程。数值为 1。
    numaNodeAssignment可选的枚举属性。 指定 IIS 如何确定哪个 NUMA (非统一内存访问) 节点将进程关联到。 NUMA 节点包含共享单个内存库的核心群集。 仅当 NUMA 节点可用时,此属性才在 CPU 高级设置中可用。

    numaNodeAssignment 属性可以是以下可能的值之一。 默认值为 Most Available Memory

    值说明Most Available Memory进程将分配给内存可用空间最大的 NUMA 节点。数值为 0。Windows SchedulingWindows 计划将确定进程分配到的 NUMA 节点。数值为 1。
    processorGroup可选 int 属性。 (从零开始的) 使用的处理器组数。 一个处理器组包含多个核心。 仅当服务器具有多个处理器组时,CPU 高级设置中才提供“处理器组”属性。

    默认值 0为 ,这意味着使用单个处理器组。
    resetInterval可选的 timeSpan 属性。 为应用程序池的 CPU 监视和限制指定重置周期 (分钟) 。 当自上次进程记帐重置以来经过的分钟数等于此属性指定的数时,IIS 将重置日志记录间隔和限制间隔的 CPU 计时器。

    重要说明: resetInterval 值必须大于日志记录操作之间的时间,否则 IIS 将在日志记录发生之前重置计数器,并且不会进行进程记帐。

    注意: 由于 IIS 中的进程记帐使用 Windows 作业对象监视整个进程的 CPU 时间,因此进程计帐只会记录和限制在与 IIS 隔离的单独进程中的应用程序。

    默认值为 00:05:00
    smpAffinitized可选布尔属性。 指定是否还应将分配给应用程序池的特定工作进程分配给给定的 CPU。 此属性与 smpProcessorAffinityMask 和 smpProcessorAffinityMask2 属性一起使用。

    默认值为 false
    smpProcessorAffinityMask可选 uint 属性。 指定多处理器计算机的十六进制处理器掩码,该掩码指示应用程序池中的工作进程应绑定到哪个 CPU。 在此属性生效之前,必须将应用程序池的 smpAffinitized 属性设置为 true 。

    注意: 在 64 位计算机上, smpProcessorAffinityMask 属性包含处理器掩码的低阶 DWORD, 而 smpProcessorAffinityMask2 属性包含处理器掩码的高阶 DWORD。 在 32 位计算机上, smpProcessorAffinityMask2 属性不起作用。

    如果将值设置为 1 (对应于二进制) 中的00000000000000001,则应用程序池中的工作进程仅在第一个处理器上运行。 如果将值设置为 2 (对应于二进制) 中的0000000000000010,则工作进程仅在第二个处理器上运行。 如果将值设置为 3 (对应于二进制) 0000000000000011,则工作进程在第一个和第二个处理器上运行。

    注意: 不要将此属性设置为 0。 这样做会禁用对称多处理 (SMP) 相关性,并创建错误条件。 这意味着在一个 CPU 上运行的进程在其生存期内不会与该 CPU 保持关联。

    默认值为 4294967295
    smpProcessorAffinityMask2可选 uint 属性。 为 64 位多处理器计算机指定高阶 DWORD 十六进制处理器掩码,该掩码指示应用程序池中的工作进程应绑定到哪个 CPU。 在此属性生效之前,必须将应用程序池的 smpAffinitized 属性设置为 true 。

    注意: 在 64 位计算机上, smpProcessorAffinityMask 属性包含处理器掩码的低阶 DWORD, 而 smpProcessorAffinityMask2 属性包含处理器掩码的高阶 DWORD。 在 32 位计算机上, smpProcessorAffinityMask2 属性不起作用。

    默认值为 4294967295

    子元素

    无。

    配置示例

    以下配置示例配置名为 DefaultAppPool 的单个应用程序池,并将 CPU 设置为 50%,并执行一个操作,以终止重置间隔为 10 分钟的工作进程。

    XML
    <applicationPools>    <add name="DefaultAppPool">      <cpu limit="50000" action="KillW3wp" resetInterval="00:10:00" />    </add>    <applicationPoolDefaults>      <processModel identityType="NetworkService" />    </applicationPoolDefaults> </applicationPools>

    代码示例

    以下代码示例将默认应用程序池配置为在超出 CPU 限制时终止工作进程,并将重置间隔配置为四分钟。

    AppCmd.exe

    控制台
    appcmd.exe set config -section:system.applicationHost/applicationPools /[name='DefaultAppPool'].cpu.action:"KillW3wp" /commit:apphost appcmd.exe set config -section:system.applicationHost/applicationPools /[name='DefaultAppPool'].cpu.resetInterval:"00:04:00" /commit:apphost

     备注

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

    C#

    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", @"DefaultAppPool");          if (addElement == null) throw new InvalidOperationException("Element not found!");          ConfigurationElement cpuElement = addElement.GetChildElement("cpu");          cpuElement["action"] = @"KillW3wp";          cpuElement["resetInterval"] = TimeSpan.Parse("00:04:00");          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

    VB
    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", "DefaultAppPool")       If (addElement Is Nothing) Then          Throw New InvalidOperationException("Element not found!")       End If       Dim cpuElement As ConfigurationElement = addElement.GetChildElement("cpu")       cpuElement("action") = "KillW3wp"       cpuElement("resetInterval") = TimeSpan.Parse("00:04:00")       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

    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", "DefaultAppPool"]); if (addElementPos == -1) throw "Element not found!"; var addElement = applicationPoolsCollection.Item(addElementPos); var cpuElement = addElement.ChildElements.Item("cpu"); cpuElement.Properties.Item("action").Value = "KillW3wp"; cpuElement.Properties.Item("resetInterval").Value = "00:04:00"; 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

    VB
    Set adminManager = WScript.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", "DefaultAppPool")) If (siteElementPos = -1) Then    WScript.Echo "Element not found!"    WScript.Quit End If Set addElement = applicationPoolsCollection.Item(addElementPos) Set cpuElement = addElement.ChildElements.Item("cpu") cpuElement.Properties.Item("action").Value = "KillW3wp" cpuElement.Properties.Item("resetInterval").Value = "00:04:00" 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