我有一个 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
将返回相同的图像文件。
然后我执行以下操作:
- 要求
http://myserver/iismodulecachetest/foobar
- 直接修改 C:\testvirtdir\image.png (在paint中改变它的颜色并重新保存)。
- 重复。
在间隔几秒钟重复 1 到 20 次后,返回的图像将是过期的副本。
一旦不高兴,服务器只会在经过未知的时间(从 10 秒到几分钟)后返回当前版本。如果我将步骤 1 中的 URL 替换为http://myserver/iismodulecachetest/virtdir/image.png
,则似乎不会出现问题。但奇怪的是,在使用“foobar” URL 出现问题后,直接 URL也开始返回图像的过期副本。
相关细节:
- 应用程序池的回收解决了该问题。
- 稍等片刻即可解决问题。
- 反复重新保存文件似乎没有效果。我想知道“文件修改”事件是否丢失了,但是一旦卡住,我可以保存六次修改并且 Iis 仍然不会返回新副本。
- 在 web.config 中禁用缓存没有任何区别。
<caching enabled="false" enableKernelCache="false" />
- 这是一个虚拟目录这一事实似乎很重要,我无法复制 image.png 作为应用程序本身内容的一部分的问题。
- 这不是客户端缓存,它肯定是服务器返回一个过时的版本。我已经通过检查请求标头、Ctrl+F5 刷新,甚至使用单独的浏览器来验证这一点。
- 我已经在两台机器上复制了这个问题。Win7 Pro 6.1.7601 SP1 + IIS 7.5.7600.16385 和 Server 2008 R2 6.1.7601 SP1 + IIS 7.5.7600.16385。
编辑 - 更多细节:
- 在服务器级别禁用缓存和内核缓存没有区别。
- 向 URL 添加扩展名没有任何区别
http://myserver/iismodulecachetest/foobar.png
。 - 将调试器附加到 IIS 表明
context_PostAuthenticateRequest
事件处理程序每次都被触发,并且无论缓存是否被卡住,其行为方式都相同。
Edit2 - IIS 日志:
我在 IIS 中启用了“失败的请求跟踪”(有趣的是,如果配置得当,这对于非失败请求也是如何工作的。在步骤 17 之前,管道是相同的,其中返回过期版本的请求清楚地显示了缓存命中。
第一个请求看起来很好,但缓存未命中:
但是一旦卡住,它就会反复显示缓存命中:
可以理解,缓存命中后的事件与缓存未命中情况完全不同。看起来 IIS 完全满足于认为它的文件缓存是最新的,但它绝对不是!:(
再往下一点,我们看到第一个请求:
然后是后续的(错误的)缓存命中请求:
另请注意,根据FileDirmoned="true"
.