我有一个使用Nhibernate和Linq2SQL的复杂服务器应用程序。每天大约3次Linq2sql代码会生成“值不能为空”异常。一旦发生这种情况,代码将始终生成异常。诊断和解决根本原因将是漫长的,并且会导致不稳定。
当前的“解决方案”是每小时重新使用应用程序池。但是,该服务从问题发生直到停止回收为止。我希望Web服务捕获异常并回收它自己的应用程序池。我希望所有其他Web请求都能够兑现,直到完成。
Edit:故障是在负载平衡Web场的两台服务器上。客户端不会仅因为此代码崩溃而从一台服务器切换到另一台服务器。
以下代码将回收当前站点的应用程序池。您需要添加对Microsoft.Web.Administration的引用
using (ServerManager iisManager = new ServerManager())
{
SiteCollection sites = iisManager.Sites;
foreach (Site site in sites)
{
if (site.Name == HostingEnvironment.SiteName)
{
iisManager.ApplicationPools[site.Applications["/"].ApplicationPoolName].Recycle();
break;
}
}
}
使ASP.NET辅助进程“进入”应用程序池的最简单方法是以某种方式修改web.config文件。此更改由文件系统监视程序拾取,并导致ASP.NET回收以便加载新配置。
文件的内容不必以任何实际的方式进行更改;仅添加或删除空格字符就足够了。
编辑:
如果此功能不足以解决您的问题,则可以花大量精力并使用Directory Services手动回收应用程序池。
// Set up the path identifying your application pool.
var path = "IIS://YOURSERVERNAME/W3SVC/AppPools/YourAppPoolName";
// Create the directory entry to control the app pool
var appPool = new DirectoryEntry(path);
// Invoke the recycle action.
appPool.Invoke("Recycle", null);
基于Code Project: Recycling IIS 6.0 application pools programmatically。
我以前有完全相同的问题;我本该在博客上写这本书,因为现在我已经不记得根本原因了。
我的肠子告诉我,这是以下之一:
或类似的东西。只要确保您正确使用了Linq2Sql。
我最终选择的解决方案是为appPool允许消耗的内存量设置一个最大值。然后,代码只是吞噬了内存,直到asp.net决定回收appPool。
在应用程序池高级设置中,我将专用内存限制设置为800,000 Kb。
在Linq代码失败的Catch部分中,我分配的内存超出了限制:
List<string> listOfMemory = new List<string>();
// in the app pool, you need to set the virtual memory limit to 800,000kb
log.Error("Allocating so much memory that the app pool will be forced to recycle... ");
for (int intCount = 1; intCount < 10000000; intCount++)
{
listOfMemory.Add("new string " + intCount.ToString());
}
这现在意味着在产生新的w3wp进程之前,只有大约4个线程失败。在此解决方案之前,线程将一直失败,直到有人手动回收应用程序池为止。不幸的是,如果将应用程序池设置为以固定的分钟数进行回收,则分钟数越小,崩溃越频繁。分钟数越大,更多线程将失败。
此创造性的解决方法可以限制损坏。