【问题标题】:ASP.NET HttpModule RewritePath virtual directory cache not refreshingASP.NET HttpModule RewritePath 虚拟目录缓存不刷新
【发布时间】:2013-01-22 12:00:44
【问题描述】:

我有一个 ASP.NET IHttpModule 实现,旨在重写服务文件的路径。该模块只处理一个事件,PostAuthenticateRequest,如下:

void context_PostAuthenticateRequest(object sender, EventArgs e)
{
    if (HttpContext.Current.Request.Path.ToLower().Contains("foobar"))
    {
        HttpContext.Current.RewritePath("virtdir/image.png");
    }
}

路径“virtdir”是应用程序的虚拟目录子目录。应用程序本身运行在一个典型位置:C:\inetpub\wwwroot\IisModuleCacheTest\ 虚拟目录“virtdir”映射到 C:\TestVirtDir\

http://myserver/iismodulecachetest/foobar 的请求将如预期的那样从虚拟目录返回 image.png。同样,对http://myserver/iismodulecachetest/virtdir/image.png 的请求将返回相同的图像文件。

然后我执行以下操作:

  1. 请求http://myserver/iismodulecachetest/foobar
  2. 直接修改C:\testvirtdir\image.png(在paint中更改颜色并重新保存)。
  3. 重复。

在间隔几秒钟重复 1 到 20 次后,返回的图像将是过期的副本。

一旦出现异常,服务器只会在经过未知时间(从 10 秒到几分钟)后返回当前版本。如果我将步骤 1 中的 URL 替换为 http://myserver/iismodulecachetest/virtdir/image.png,则似乎不会出现问题。但奇怪的是,在使用“foobar”网址出现问题后,直接网址开始返回图像的过期副本。

相关细节:

  1. 应用程序池的回收解决了该问题。
  2. 稍等片刻即可解决问题。
  3. 反复重新保存文件似乎没有效果。我想知道“文件修改”事件是否丢失了,但一旦卡住,我可以保存六次修改并且 Iis 仍然不会返回新副本。
  4. 在 web.config 中禁用缓存没有任何区别。 <caching enabled="false" enableKernelCache="false" />
  5. 这是一个虚拟目录这一事实似乎很重要,我无法复制 image.png 作为应用程序本身内容的一部分的问题。
  6. 不是客户端缓存,它肯定是服务器返回一个过时的版本。我已经通过检查请求标头、Ctrl+F5 刷新,甚至使用单独的浏览器验证了这一点。
  7. 我已经在两台机器上复制了这个问题。 Win7 Pro 6.1.7601 SP1 + IIS 7.5.7600.16385 和 Server 2008 R2 6.1.7601 SP1 + IIS 7.5.7600.16385。

编辑 - 更多详情:

  1. 在服务器级别禁用缓存和内核缓存没有区别。
  2. 向 URL 添加扩展名没有区别 http://myserver/iismodulecachetest/foobar.png
  3. 将调试器附加到 IIS 显示每次都会触发 context_PostAuthenticateRequest 事件处理程序,并且无论缓存是否卡住,其行为方式都相同。

Edit2 - IIS 日志:

我在 IIS 中启用了“失败的请求跟踪”(如果配置得当,这对于 non 失败的请求也很有趣。管道是相同的,直到第 17 步返回过期的请求版本清楚地显示缓存命中。

第一个请求看起来很好,但缓存未命中:

但是一旦卡住,就反复显示缓存命中:

可以理解,缓存命中后的事件与缓存未命中情况完全不同。看起来 IIS 完全满足于认为它的文件缓存是最新的,但它绝对不是! :(

我们看到第一个请求的堆栈再往下一点:

然后是后续(错误的)缓存命中请求:

另请注意,根据FileDirmoned="true",该目录显然受到监控。

【问题讨论】:

  • 你能确认文件上的修改日期确实改变了吗?
  • 是的,现在刚刚测试。 Windows 资源管理器清楚地显示文件的新修改日期,但 IIS 仍返回旧版本。 Http 标头“Last-Modified”也返回 old 修改日期。
  • 我会向 Microsoft 开一张支持票。这显然是一个错误,所以它应该是 100% 免费的。
  • MS 支持票。 -sigh- 每次我举起其中的一个,我都会得到另一根白发。
  • 不开玩笑,我也是。 8 年前,我第一次白发苍苍,处理虚拟路径提供程序实现中的 ASP.NET 内存泄漏......在那场惨败中认识了整个 ASP.NET 团队。不过,他们很快就修复了它。

标签: asp.net caching url-rewriting iis-7.5


【解决方案1】:

您可以执行以下操作。

void context_PostAuthenticateRequest(object sender, EventArgs e)
{
    if (HttpContext.Current.Request.Path.ToLower().Contains("foobar"))
    {
        Random rnd = new Random();
        int randomNumber = rnd.Next(int.MinValue, int.MaxValue);
        HttpContext.Current.RewritePath("virtdir/image.png?"+randomNumber);
    }
}

【讨论】:

  • 原则上我认为这会破坏缓存并因此绕过问题,但实际上Random 的实例需要被视为单例以避免重复值。
【解决方案2】:

我使用RewritePath 方法来处理虚拟目录中的静态资源时遇到了同样的问题。 我没有使用这种方法的解决方案,但最后我选择使用方法Server.TransferRequest,这表明没有缓存问题。

HttpContext.Current.Server.TransferRequest(newUrl);

请求传输由IHttpModule再次处理,因此您需要注意不要产生循环。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-29
    • 2010-09-16
    • 2017-06-24
    相关资源
    最近更新 更多