7

这可能需要一些时间来解释,但我走了:)。

我创建了两个 Visual Studio 2012 项目:

  1. 在 Visual Studio 的“添加项目”对话框中使用(Web -> ASP.NET MVC 4 Web 应用程序)模板的项目。我没有添加单元测试项目。
  2. 使用 Azure 云服务模板(云 -> Windows Azure 云服务)的项目。我添加了一个角色,一个 ASP.NET MVC 4 Web 角色,并且再次没有添加单元测试项目。

我让这两个项目完全不受 Visual Studio 为我创建它们的方式所影响。

对于每个项目,然后我去上课并在每个和操作方法HomeController中设置一个断点(仅返回一个视图的无聊操作)。例如,我在方法中的唯一行设置了一个断点:AboutContact

public ActionResult About()
{
     return View();
}

然后我开始调试第一个项目(非 Azure 项目)。一切都如预期 - 即当我使用浏览器在 About 和 Contact 页面之间导航时,各个操作方法中的断点将在每个请求上被命中一次。对我来说似乎很好。

然后我开始调试 Azure 项目。我遵循了在 About 和 Contact 页面之间导航的相同程序。这次我发现了有趣的非确定性行为。在某些请求中,action 方法中的断点会在页面呈现之前被多次(有时超过两次)命中。有时请求会挂起并且页面不会呈现(即使在等待几分钟后)。

我想知道为什么会发生这种情况,因为它会影响我们正在处理的另一个 Azure MVC 应用程序中更复杂的事情(例如,由于这个问题,应用程序可能会尝试在我的数据库用于一个请求)。

我在以下环境中:

  • 视窗 8 专业版 (x64)
  • Visual Studio 2012 终极版
  • 适用于 Visual Studio 2012 的 Windows Azure SDK
  • IIS 8 速成版
  • 带有 Firebug 的 Firefox 浏览器(也确认了使用 IE 的行为)
  • SQL Server 2012(我猜不是很相关)

我注意到的唯一有趣的事情是,每当我调试 Azure 项目时,Visual Studio的“输出”窗口中都会出现以下警告消息:

将角色“My_Web_Role_Name”中的专用端口 80 重新映射到 81,以避免在模拟期间发生冲突。

也许这种重新映射与它有关。再一次,在做了之后,netstat -ano我看到 Azure Development Fabric 进程正在侦听端口 80,所以也许这就是它需要重新映射的原因......听起来很公平。

无论如何,我希望有人可能对导致这种行为的原因有所了解。以下是我尝试的一些额外要点和方法:

  • 重置 IIS,重启 Azure Compute/Storage 模拟器,重启整个机器
  • 剥离所有脚本的视图(即,如果页面上只有一个基本的 HTML 段落,行为仍然存在)
  • 我试图找到相关的 IIS Express 日志文件,但似乎 Azure 项目不像其他项目那样通过 IIS Express 运行(对吗?)。
  • 我监控了 Azure Compute Emulator 控制台……那里没什么有趣的。

所以......最后,一些问题:

  • 其他人可以重现这种行为吗?
  • Azure 模拟器生成的其他日志是否可以帮助我?

我真的很感激在这里朝着正确的方向前进:)。

干杯!

编辑

这里有一些更多信息(我正在更新这个问题,因为我继续调试这个问题):

About我决定在不调试的情况下运行该解决方案,并在 the和action 方法中放入了一些简单的调试消息Contact,例如:

public ActionResult About()
{
     System.IO.File.AppendAllText(@"c:\Logs\azure.log", DateTime.Now + ": Contact, thread " + System.Threading.Thread.CurrentThread.ManagedThreadId + "\r\n");
     return View();
}

我将Tail附加到该文件,并启动了Fiddler以查看 HTTP 上发生了什么。再次在两者AboutContact链接之间导航,我看到了以下输出:

从尾巴:

  • ...
  • 2012 年 9 月 12 日下午 12:14:07:关于,线程 7
  • 2012 年 9 月 12 日下午 12:14:08:联系,线程 7
  • 2012 年 9 月 12 日下午 12:14:09:关于,线程 7
  • 2012 年 9 月 12 日下午 12:14:10:联系,线程 7
  • 2012 年 9 月 12 日下午 12:14:11:关于,线程 6
  • 2012 年 9 月 12 日下午 12:14:12:联系,线程 8
  • 2012 年 9 月 12 日下午 12:14:31:联系,线程 7
  • 2012 年 9 月 12 日下午 12:14:50:联系,线程 7
  • 2012 年 9 月 12 日下午 12:15:03:关于,线程 7
  • 2012 年 9 月 12 日下午 12:15:05:联系,线程 8
  • 2012 年 9 月 12 日下午 12:15:23:关于,线程 6
  • 2012 年 9 月 12 日下午 12:15:42:关于,线程 14
  • 2012 年 9 月 12 日下午 12:16:01:关于,线程 6
  • 2012 年 9 月 12 日下午 12:16:31:联系,线程 7
  • 2012 年 9 月 12 日下午 12:16:33:关于,线程 14
  • ...
  • 2012 年 9 月 12 日下午 12:17:08:联系,线程 12
  • 2012 年 9 月 12 日下午 12:17:09:关于,线程 12
  • 2012 年 9 月 12 日下午 12:17:28:关于,线程 5
  • ...

来自 Fiddler 的相同请求(请注意,我也一直在玩弄我的角色端点设置,但无济于事):

显示 HTTP 流量的 Fiddler 屏幕截图

所以......这里的带回家的信息是:

  • HTTP 流量看起来很正常(Fiddler 没有显示任何重复的请求)
  • 有时,对于同一个请求,动作方法会被调用两次或三次,看起来是不确定的(即上面描述的原始问题)
  • 有趣的是,在我的情况下,似乎恰好19 秒后发生另一个“命中”动作方法(即,当动作方法被多次命中时,命中之间的时间差是确定性的)
  • 每当多次点击操作方法时,每次点击的线程 ID 通常都不同

我会继续深入挖掘......也许有人会根据这个更新的信息提供建议:)。

编辑 2 我决定在每种情况下都打印出进程 ID 以及 action 方法中的线程 ID。对于每个请求,进程 ID 都是对应于 IIS Express 工作进程的 ID。因此,似乎 IIS Express 工作进程有时会产生多个线程来处理请求,每个线程相隔 19 秒。

...而且我更深入... :)

编辑 3

我想我离问题越来越近了……我查看了 IIS Express 托盘,在启动应用程序后看到了以下内容(没有调试):

IIS Express 窗口显示在 Web 角色下运行的 IIS 应用程序

我决定直接使用这个 URL(而不是上面 Fiddler 中显示的 127.0.0.2:8888),问题似乎消失了。这现在开始变得有意义了……如果我直接通过端口 8889 调用 IIS 应用程序,那么一切都可以正常工作,就像它在原始非 Azure 项目中所做的那样。如果我通过端口 8888 调用 Web 角色(即特定于 Azure 的部分),有时它似乎会多次调用 IIS 应用程序。

所以我现在开始缩小对网络角色的关注。我会尝试看看是否可以找到一些相关的网络角色日志...

编辑 4

我确保在应用程序上正确设置了诊断并在调试模式下运行它。然后我转到 Azure Compute Emulator UI,右键单击我的 Web 角色实例,然后选择“打开本地存储”。这把我带到了资源管理器,在那里我能够找到一个子文件夹“temp\temp\RoleTemp\iisexpress”,其中有一个日志文件,其内容看起来像这样(请注意,我已将端点更改回端口 80 ,所以 IIS Express 应用程序现在回到端口 81):

  • 请求开始:“GET”127.0.0.1:81/Home/About
  • 请求结束:127.0.0.1:81/Home/About,HTTP 状态为 200.0
  • 请求开始:“GET”127.0.0.1:81/Home/Contact
  • 请求结束:127.0.0.1:81/Home/Contact,HTTP 状态为 200.0
  • 请求开始:“GET”127.0.0.1:81/Home/Contact
  • 请求结束:127.0.0.1:81/Home/Contact,HTTP 状态为 200.0
  • 请求开始:“GET”127.0.0.1:81/Home/Contact
  • 请求结束:127.0.0.1:81/Home/Contact,HTTP 状态为 200.0
  • 请求开始:“GET”127.0.0.1:81/Home/About
  • 请求结束:127.0.0.1:81/Home/About,HTTP 状态为 200.0
  • 请求开始:“GET”127.0.0.1:81/Home/About
  • 请求结束:127.0.0.1:81/Home/About,HTTP 状态为 200.0
  • 请求开始:“GET”127.0.0.1:81/Home/About
  • 请求结束:127.0.0.1:81/Home/About,HTTP 状态为 200.0
  • 请求开始:“GET”127.0.0.1:81/Home/Contact
  • 请求结束:127.0.0.1:81/Home/Contact,HTTP 状态为 200.0
  • 请求开始:“GET”127.0.0.1:81/Home/Contact
  • 请求结束:127.0.0.1:81/Home/Contact,HTTP 状态为 200.0
  • 请求开始:“GET”127.0.0.1:81/Home/Contact
  • 请求结束:127.0.0.1:81/Home/Contact,HTTP 状态为 200.0
  • 请求开始:“GET”127.0.0.1:81/Home/About
  • 请求结束:127.0.0.1:81/Home/About,HTTP 状态为 200.0
  • 请求开始:“GET”127.0.0.1:81/Home/Contact
  • 请求结束:127.0.0.1:81/Home/Contact,HTTP 状态为 200.0

同样,我只是在 About 和 Contact 页面之间切换,因此从日志中可以看到单个 Web 角色端点请求有时会导致 Web 角色多次调用 IIS 应用程序。现在搜索一些更高级别的网络角色日志,以找出它为什么这样做:)!

4

1 回答 1

1

因此,根据我在原始帖子的各种编辑中所写的内容:

  • 至少在我的机器上,DevFC.exe 进程(开发结构,Azure 计算模拟器)有时会从 IIS Express 生成多个对所请求资源的请求。也就是说,它会在模拟器端点上接受一个请求,有时会一个接一个地向底层 IIS Express 应用程序产生多个请求,即使它们都以 HTTP 状态代码 200 成功。这些产生的请求之间的时间差似乎保持不变,但除此之外,行为似乎是不确定的(即,并非对模拟器端点的每个请求都发生这种情况)。
  • 为了调试它,我需要访问 Azure 计算模拟器的源代码,我猜我无法获得。

现在,我的理论(和希望)是这种行为在某种程度上特定于我的开发环境,并且不会在真正的 Azure 基础架构上重现。也就是说,我想出了一个解决方法......

我为 Firefox 创建了一个简单的代理文件,以将所有流向本地 Azure 模拟器端口的流量重定向到 IIS Express 应用程序端口。这解决了这个问题,但是我知道我现在基本上绕过了 Azure 模拟器,而且我猜我将来可能会遇到问题,因为我正在这样做(例如,如果我决定使用 AppFabric 缓存? )!

同时,我将继续使用此解决方法进行开发,并定期部署到我的 Azure 暂存环境进行测试。

无论如何,如果有人知道我如何解决基本问题,请告诉我!:)

编辑:我不再能够使用 Azure SDK 工具 2.2 版重现该问题。如果您仍然看到此行为,请尝试升级!

于 2012-12-09T05:24:23.127 回答