1

对冲 - 这可能最终成为一个“愚蠢的新手”问题,但如果不是,它可能是今天更有趣的帖子之一。

基本上,我看到仅将 Global.asax 组件添加到 Web 应用程序会导致运行时串行执行页面请求,而没有 Global.asax 的 Web 应用程序按预期并行处理请求。如果您使用 Global.asax,影响将是可扩展性消失了——我怀疑事实是否如此,但目前无法提供更好的解释。

这是场景:

  1. 创建一个新的空白 Web 应用程序。
  2. 添加一个需要 5 秒左右才能完成的页面。我使用了以下方法,但延迟的确切方法似乎并不重要:

    DateTime PageStartTime = DateTime.Now;

    而(DateTime.Now < PageStartTime.AddMilliseconds(5000)) { System.Threading.Thread.Sleep(0); }

  3. 添加另一个页面以用作重置应用程序域的实用程序。这对于查看问题行为并不是绝对必要的,但有助于重复测试:

    HttpRuntime.UnloadAppDomain();

  4. 构建后,启动一个浏览器,其中一个选项卡(或窗口)用于重置应用程序域,3 个选项卡(或窗口)用于长时间运行的页面。

  5. F5 'reset' 页面,稍等片刻,然后 F5 3 'delay page' 选项卡。您会看到(如预期的那样)这 3 页几乎同时结束,即它们显然是并行运行的。运行所有你想要的 F5,它们仍然会像预期的那样平行,大概直到奶牛回家。

  6. 回到项目,添加一个“全局应用程序类”(Gloabl.asax)组件。无需添加任何代码——组件的存在就是测试的基础。

  7. 构建后,返回浏览器并快速 F5 4 个选项卡。同样,长时间运行的页面按预期并行,至少如果您相当快地点击 3 个选项卡。现在是好的部分 - 等待一秒钟,直到所有完成,然后(不使用重置选项卡)再次 F5 3“延迟”页面 - 你会看到:

    一种。所有 3 个运行的总时间约为 15 秒 - 比预期长 3 倍。这些页面似乎是按顺序处理的,即一个接一个。

    湾。第二个和第三个选项卡的完成顺序是随机的,这表明 ASP 甚至在第一个请求完成之前还没有决定哪个应该先运行。

    C。如果您重置(卸载)应用程序域,您将有另一个机会让页面并行,但在它们完成第一个周期后,它们会立即返回串行执行。

  8. 回到项目,删除 Global.asax 组件,构建并重新测试 - 页面请求再次并行,如预期的那样长期。

酷,嗯?

我试过的东西:

  1. 各种 .Net 版本 - 3.5 和 4,
  2. 各种 Web 服务器 - WebDev、UltiDev、IIS、
  3. 延迟页面的不同方式 - 实际工作,有和没有产量等,
  4. 浏览器使用 - 一个带有多个选项卡的浏览器窗口,而不是专用浏览器窗口,
  5. 代码放置 - 为延迟代码尝试了页面“加载”和“预渲染”事件,~。其他东西现在已经从白发苍苍的记忆中滚落了……

显然,以上不是一个具有代表性或有用的项目,但我偶然发现这样做既有意长时间运行页面又实际需要 Global.asax - 主要用于全局静态变量。我想大多数“正常”的网络应用程序会运行得足够快,以至于如果它们恢复到顺序请求执行,很少有人会注意到,但是这种行为确实打破了我的 - 已经锤了三天,所以任何想法都非常感谢!

谢谢,大卫

4

3 回答 3

6

罪魁祸首是Session_Start默认添加到 Global.asax.cs 的事件处理程序:

protected void Session_Start(object sender, EventArgs e)
{

}

此事件处理程序的存在会导致 ASP.NET 创建一个实际会话并将其与会话 cookie 相关联,即使您从未在会话状态中存储任何内容。一旦有一个实际的会话,请求就会被序列化

在您的场景中,只需删除空Session_State事件处理程序,请求将再次并行执行。

(Global.asax.cs 中还有一个空的Session_End事件处理函数,但不影响请求是否被序列化。)

于 2013-09-29T22:06:59.190 回答
1

我的猜测是,由于某种原因,您为您的请求分配了一个会话,并且不同的浏览器选项卡/窗口共享同一个会话。如果是这样,运行时将按顺序执行请求。

ASP.net 会话请求队列

ASP.NET MVC 和 Ajax,并发请求?

如果您使用 http 调试器嗅探流量,您可以轻松验证这一点。

于 2013-09-29T20:27:54.997 回答
0

ASP.NET 会话可能正在等待您的请求...

试试下面的代码。页面中提供了更多信息

[SessionState(System.Web.SessionState.SessionStateBehavior.ReadOnly)]
public class HomeController : Controller
{
}
于 2017-02-28T17:40:05.820 回答