【发布时间】:2011-05-30 04:43:49
【问题描述】:
使用 Firebug 和 Chrome 开发人员工具,我可以看到通过一个操作加载一些 javascript 和 css 文件在我的开发机器上可能需要额外的 500 毫秒。这发生在不同调用的不同文件上,不管我把它们放在什么顺序。如果我直接链接到这些文件,这 500 毫秒的延迟永远不会发生。我可以一遍又一遍地刷新页面并获得不同的值,但它们看起来总是像请求时间增加了 500 毫秒。如果我不断刷新页面,额外的 500 毫秒会显示在不同的单个文件上,有时会显示在两个文件上,其中一个文件有 1000 毫秒的延迟,如下图所示。
编辑
将 Monitor.Enter 放入我的 HttpModule 的 BeginRequest 和 Monitor.Exit 放入 EndRequest 导致延迟消失,所以我猜它与线程化多个请求有关。
我使用 Evan Nagel here 描述的方法进行缓存,但是当我将链接替换为对我自己的控制器的调用时,会发生同样的事情,该操作只传递一个原始文件:
public FileResult RawFile(string path, string contentType)
{
var server = HttpContext.Server;
string decodedPath = server.UrlDecode(path);
string mappedPath = server.MapPath(decodedPath);
return File(mappedPath, contentType);
}
这是我在我的 html 的 head 部分中的代码:
<link rel="stylesheet" href="@Url.Action("RawFile", new { controller = "Content", path = "~/Content/Site.css", contentType = "text/css" })" type="text/css" />
<script src="@Url.Action("RawFile", new { controller = "Content", path = "~/Scripts/debug/FBINFO.js", contentType = "application/x-javascript" })" type="text/javascript"></script>
<script src="@Url.Action("RawFile", new { controller = "Content", path = "~/Scripts/jquery-1.4.1.min.js", contentType = "application/x-javascript" })" type="text/javascript"></script>
这似乎不会在我的生产服务器上发生,至少不会经常发生,但由于延迟通常较高,所以很难说。这是不用担心的事情吗?什么会导致它? Cassini 和我在 Windows 7 Home Ultimate 64 位上的本地 IIS 服务器都会发生这种情况。
我添加了一个自定义属性来计时调用,并且 OnAction/OnResult Executing 和 Executed 之间的时间通常是亚毫秒。我在 action 方法周围使用了秒表(ZipController 写入响应流并且不返回结果),时间同样总是很小,平均 1.5 毫秒并且总是低于 10 毫秒。
我在 Fiddler 标头中看到的唯一真正区别是 X-AspNetMvc-Version 标头,因此我将其设置为不附加,甚至删除 X-AspNet-Version 标头也无济于事。我已经尝试过启用和禁用压缩以及我能想到的所有其他内容。这是在我添加了我自己的 Cache-Control 和 ETag 标头之后,这些标头没有任何效果。有趣的是,即使在未发送正文的 304 Not Modified 响应的情况下也会发生 500 毫秒的延迟。有时两个文件会有延迟,一个是 500 毫秒,另一个是 1000 毫秒。
直接文件:
HTTP/1.1 200 OK
Content-Type: application/x-javascript
Last-Modified: Sun, 29 May 2011 22:42:27 GMT
Accept-Ranges: bytes
ETag: "b57a84af511ecc1:0"
Server: Microsoft-IIS/7.5
Date: Mon, 30 May 2011 04:38:20 GMT
Content-Length: 1336
原始文件操作:
HTTP/1.1 200 OK
Cache-Control: public
Content-Type: application/x-javascript
ETag: "CD9F383D0537373C6D2DC8F60D6519A6"
Server: Microsoft-IIS/7.5
Date: Mon, 30 May 2011 04:34:37 GMT
Content-Length: 1336
根据 IanT8 的评论,我添加了一个 HttpModule 来跟踪开始/结束请求,并将日志调用添加为我的操作方法的第一个和最后一个语句。长话短说,两个请求同时进来,500ms 的延迟发生在第一个 EndRequest 之后,第二个调用的 action 方法执行之前。这个延迟一般是499ms,但是一次是497ms,一次是498ms,一次是492ms。
2011-05-31 00:55:19.1874|INFO|20110531 00:55:19.196 BeginRequest: http://localhost:51042/Zip/Style?Path=~/Content/Site.css
2011-05-31 00:55:19.1874|INFO|20110531 00:55:19.197 BeginRequest: http://localhost:51042/Zip/Script?Path=~/Scripts/jquery-1.4.1.min.js|~/Scripts/debug/FBINFO.js
2011-05-31 00:55:19.2034|INFO|20110531 00:55:19.203 Style() Start
2011-05-31 00:55:19.2034|INFO|20110531 00:55:19.208 Style() End
2011-05-31 00:55:19.2034|INFO|20110531 00:55:19.212 EndRequest: http://localhost:51042/Zip/Style?Path=~/Content/Site.css
2011-05-31 00:55:19.7044|INFO|20110531 00:55:19.704 Script() Start
2011-05-31 00:55:19.7044|INFO|20110531 00:55:19.712 Script() End
2011-05-31 00:55:19.7044|INFO|20110531 00:55:19.713 EndRequest: http://localhost:51042/Zip/Script?Path=~/Scripts/jquery-1.4.1.min.js|~/Scripts/debug/FBINFO.js
现在是真正有趣的部分。我在 HttpModule 上创建了一个静态对象,并在 BeginRequest 中调用 Monitor.Enter,在 EndRequest 中调用 Monitor.Exit。延迟消失了。 Chrome 显示一个呼叫大约需要 15-20 毫秒,另一个大约需要 30-40 毫秒,因为它必须等待第一个呼叫结束,但 500 毫秒的延迟已经消失。显然这个解决方案不是最优的。
【问题讨论】:
-
你考虑过动作的编译时间吗?您可以通过检查后续调用来对此进行测试。
-
是的,我会在问题中添加注释。
-
这与我在服务器故障中发现的这个限制有什么关系吗? MS 真的想让我们的开发机器对这种测试几乎毫无用处吗?每次调用添加的几乎精确的 500 毫秒让我认为它可能是这样的。 serverfault.com/questions/133772/…
-
我知道在 Firefox 中调试时,我在使用 localhost 查看页面时会遇到高延迟,但是使用 127.0.0.1 时会快得多。 Chrome 也可以这样吗?
-
您是否考虑过通过挂钩开始请求/结束请求事件来添加一个 Http 模块来计时并记录所花费的时间。至少你会知道在 asp.net mvc 中花费了多少时间。