IIS8 RewriteModule / URLRewrite 极慢

IIS8 RewriteModule / URLRewrite Extremely Slow

我是 运行 一个在 Windows Server 2012 上安装 IIS8 的网站。我正在尝试确定导致 IIS CPU 使用率高的原因(通常是 50% 或更多 CPU IIS 使用)。服务器全天每秒接收大约 40 个请求,但每秒可能只有 1-2 URL 需要处理。

我启用了请求跟踪,发现某些 RewriteModule 请求需要 100 多秒 (!) 才能完成。我无法确定这在硬件足够多的机器上如何实现。完全相同的 URL 结构在不到一秒的时间内通过 Apache 上的 mod_rewrite 处理。

一个例子 URL 是这样的:

http://<domain-name>/Product/<Parent-Category>/<Child-Category1>/<Child-Category2>/<Child-Category3>/<Product-Name>

附带的重写规则是:

<rule name="Rule" stopProcessing="true">
      <match url="^Product/([^/\?]+)/?([^/\?]+)?/?([^/\?]+)?/?([^/\?]+)?/?([^/\?]+)?/?([^/\?]+)?/?[\?]?(.+)?$"/>
      <conditions logicalGrouping="MatchAll" trackAllCaptures="false">
        <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true"/>
        <add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true"/>
      </conditions>
      <action type="Rewrite" url="/Product/index.php?a={R:1}&amp;b={R:2}&amp;c={R:3}&amp;d={R:4}&amp;e={R:5}&amp;f={R:6}&amp;{R:7}" appendQueryString="true"/>
    </rule>

我定义匹配项 URL 的方式是否导致处理时间过长?如果某些匹配网址使用许多 parent/child 类别(最多 5 个,通常为 3-4 个),则它们包含大量字符。

问题肯定出在您的正则表达式中。最好的方法是尝试将其拆分为不同的更具体的模式。

如果不是这种情况,此规则应保持相同的功能并运行得更快:

<rule name="Rule" stopProcessing="true">
  <match url="^Product/([^/]+)/?([^/]+)?/?([^/]+)?/?([^/]+)?/?([^/]+)?/?([^/]+)?"/>
  <conditions logicalGrouping="MatchAll" trackAllCaptures="false">
    <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true"/>
    <add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true"/>
  </conditions>
  <action type="Rewrite" url="/Product/index.php?a={R:1}&amp;b={R:2}&amp;c={R:3}&amp;d={R:4}&amp;e={R:5}&amp;f={R:6}" appendQueryString="true"/>
</rule>

我在你的正则表达式中删除了不必要的 \? 检查,因为 <match url 中的模式正在检查 URL 没有查询字符串,所以 ? 检查是多余的在你的正则表达式中。

我检查了我的 PC,它确实运行得更快,但你需要仔细检查它是否保持相同的功能

我进行了大量测试并将规则更改为以下内容。这导致 CPU 下降到 1%,之前的 100 秒完成时间下降到大约 50 毫秒。

我仍然不明白这是怎么可能的 - 这是一台 4 CPU/8-core 机器,有 48GB 内存,IIS8 花了 100 秒来分离一个 70 个字符的字符串并将它与之前的正则表达式进行比较.除非前面的示例以某种方式创建了一个近乎无限的循环,否则我不明白它怎么可能这么慢。

新规则:

<rule name="Rule" stopProcessing="true">
      <match url="^Product/([^/]+)/([^/]+)/([^/]+)/([^/]+)/([^/]+)/([^/]+)?[/]?(.+)?$"/>
      <conditions logicalGrouping="MatchAll" trackAllCaptures="false">
        <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true"/>
        <add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true"/>
      </conditions>
      <action type="Rewrite" url="/Product/index.php?a={R:1}&amp;b={R:2}&amp;c={R:3}&amp;d={R:4}&amp;e={R:5}&amp;f={R:6}&amp;{R:7}" appendQueryString="true"/>
    </rule>