将.NET版本在网站和虚拟目录之间混用,出现“服务器应用程序不可用”错误信息

4

背景
上个月我们的开发团队创建了一个新的asp.net 3.5应用程序,放在我们的生产网站上。完成工作后,我们请求管理服务器的组将应用程序复制到我们的生产网站,并将虚拟目录配置为新的应用程序。

2010年12月27日,选择了两个公共“豚鼠”来使用该应用程序,效果非常好。 2010年12月30日,我们收到内部员工的通知,称当该员工尝试访问应用程序时(这是业务流程所有者),他们收到了“服务器应用程序不可用”的消息。

当我打电话给负责我们服务器支持的组时,我被告知它可能失败了,因为我没有在我的代码中关闭连接。然而,同一组人随后为这个扩展请求应用程序创建了一个单独的应用程序池。从那以后就没有出现任何问题。

我做了一点谷歌搜索,因为我不喜欢被指责为某些事情。我发现,“服务器应用程序不可用”的消息也会出现在您有多个使用不同框架的应用程序,并且您没有将它们放在不同的应用程序池中。

技术细节 - 网站结构树

Main Website <-- ASP Classic
         +-Virtual Directory(ExtensionRequest) <-- ASP 3.5 

来自我们的服务器支持组:

“审核了服务器日志和IIS中的网站设置。由于应用程序池未正常工作,我们不得不重置它。这纠正了网站问题,现在已经恢复在线状态。我们为扩展Web创建了一个应用程序池,以使其与主站点池隔离。过去,当连接被保持打开并且池填满时,我们已经看到其他应用程序会这样做。建议检查站点代码,确保没有留下任何连接。”

真正的问题是: 导致故障的真正原因是什么?连接保持打开问题不是ASP Classic问题吗?ExtensionRequest应用程序必须首先被使用(超过两次)才能保持连接打开吗?更有可能的是,他们一开始就没有费心在自己的应用程序池中设置新应用程序吗?

抱歉,表述有些冗长。


我已经扩展了我的答案,请看最后一部分。 - Kev
2个回答

2

你需要获取并审查服务器的应用程序、系统事件和HTTPERR日志,以了解出现这些错误的时期。

如果没有这些日志,很难推测出问题的根本原因。

更新:

OP错误地标记了他的问题,所以下面这一部分不再适用。但我认为该信息对于那些遇到这些问题并考虑迁移到IIS7.x的人仍然有用,所以我会保留这部分内容。


你是正确的,在同一个应用程序池中运行两个不同的.NET框架版本可能会导致这些错误,但这是你更倾向于在Windows 2003/IIS6上看到的情况,而不是在Windows 2008/IIS7上。

IIS7使用一种稍微不同的方法来指定加载哪个.NET Framework版本,它是由应用程序池的managedRunTimeVersion属性确定的。当通过IIS/ASP.NET处理请求时,站点的处理程序映射使用preCondition属性来确定何时加载必需的处理程序(这有点像之前版本的IIS中的脚本映射)。

这种机制防止了错误的运行时版本被加载到应用程序池的工作进程中。

因此,如果配置了一个应用程序池只运行.NET Framework版本v4.0,即使你的应用程序是针对v2.0构建的,也只会加载该版本。

这里有一篇很棒的文章介绍了这个机制的工作原理:

Achtung! IIS7 Preconditions

中间部分关于处理程序的部分解释了为什么preCondition功能可以缓解错误地加载不正确的.NET版本到池中的风险。

服务器应用程序不可用错误通常意味着发生了某些灾难性的事件(比如将错误的ASP.NET版本的ISAPI过滤器加载到已经运行的工作进程中)。

不关闭SQL连接不太可能导致此类严重错误。如果是这种情况,您更有可能看到黄色屏幕死亡运行时错误。运行出SQL连接通常不会让ASP.NET变得非常失调,以至于整个服务都会停止。

我怀疑问题出在应用程序池标识无法正确访问应用程序文件夹的权限问题上。但这只是一种猜测。

同样,您需要获取应用程序和系统事件日志以及HTTPERR日志(它们位于%systemroot%\System32\LogFiles\HTTPERR)。这将包含有关发生了什么错误的线索和事实。

更新2:

在Windows 2003/IIS6上,如果您有两个运行不同ASP.NET版本的应用程序位于同一个池中,您会遇到此错误。根据我的经验(我在一个Web托管公司工作),这是这个臭名昭著的错误页面的主要原因:

alt text

在应用程序事件日志中也记录了一个显眼的事件:

事件类型:错误
事件来源:ASP.NET 2.0.50727.0
事件类别:无
事件ID:1062
日期:2011年12月01日
时间:12:31:43
用户:N/A
计算机:KK-DEBUG
说明:
不可能在同一IIS进程中运行两个不同版本的ASP.NET。请使用IIS管理工具重新配置您的服务器,以在单独的进程中运行应用程序。

虽然您的根应用程序可能没有使用ASP.NET编写,但很可能有某些东西触发了将不同版本的框架加载到您站点的应用程序池中。

  • 根目录下存在一个不合法的web.config文件...这会触发ASP.NET的加载
  • 网站脚本映射中存在一个通配符映射到ASP.NET 1.1(不太可能,但有可能)

我倾向于认为您的新应用程序肯定会被放置在其他网站或应用程序运行不同框架版本的池中。真正找出原因的唯一方法是获取应用程序事件日志并查找上面显示的事件。


我错误地标记了我的问题。它是服务器2003和IIS6。 - Doug Chamberlain
@Kev / @Doug Chamberlain - Asp.Net 3.5和2.0基于相同的框架(2.0)运行。3.5具有补充/扩展的.dll文件,但是如果两个站点都不使用相同的对象,则3.5应用程序和2.0应用程序应该能够共存。由于这是升级,因此在同一应用程序池中运行的两个应用程序很可能正在加载不同的扩展对象。也许2.0版本将MyClass加载到内存中,然后3.5版本尝试从应用程序对象进行强制转换(并成功)。当2.0版本尝试重新获取其对象时,由于转换不再有效,它将失败。 - Joel Etherton
@Kev / @Doug Chamberlain - 续 - 这通常不会导致服务崩溃,但应用程序池默认具有名为“启用快速故障保护”的设置,该设置将捕获连续发生的错误并使应用程序池崩溃以保护服务器。这将与上述类似地在事件日志中伴随着事件,但错误将更加通用,仅指示w3wp.exe进程意外终止。 - Joel Etherton
@joel - 我非常清楚2.0和3.5都基于同一框架。如果它是一个托管服务,那么很可能,如果原始站点是在2.0之前创建的,它将在1.1应用程序池中运行。我们不会强制所有人升级到新的框架(我们使用2.0安装程序的/noaspupgrade开关),而是提供用户控制面板工具,允许客户选择他们的ASP.NET版本并将站点翻转到兼容的应用程序池中。我倾向于说,管理服务器的人那天有些手误。这确实会发生。 - Kev
@Kev 真是一份好答案。实际上它是 v1.1 和 v3.5。感谢您的详细解释。我会挺起胸膛,知道我与一些“特别”的人共事。(这些人告诉我 xxx.yyy.com 不是 yyy.com 的子域名的同一批人) - Doug Chamberlain
@doug - 是的,有时候我发现最好忍住不说话,偶尔给他们捧捧场 :) - Kev

0

很难说,可能有很多原因(使用了太多资源,调用了 .NET 之外的内容导致崩溃等)。我建议查看事件日志,看看是否能在那里找到一些信息。

如果你运行不同版本的 .NET,你肯定需要分开池。如果可以选择,我建议为每个应用程序单独创建池(即使在相同的 .NET 版本中也是如此)。

至于“关闭连接”(我想你指的是与数据库的连接),如果你正在创建“低级”连接(即 SqlConnection、SqlCommand),则确保将它们包装在“using”语句中,否则你的连接池可能会填满。但根据我的经验,在这种情况下,你应该会收到常规的 .NET 错误。如果你正在使用 ORM,则不应该出现此问题。

编辑:

如果在事件日志中找不到有用的信息,你可以尝试这个:http://learn.iis.net/page.aspx/266/troubleshooting-failed-requests-using-tracing-in-iis-7/


如果没有向应用程序发出请求,那么资源/连接等的数量将为零? - Doug Chamberlain

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接