我更新网站有时会出现Server Too Busy,我看看cpu 的确用了 100%。
我一定认为网站,网站重新编译需要一定的时间。
错误来自HttRuntime的RejectRequestInternal方法。
近来看到 dudu 的文章,
http://www.cnblogs.com/dudu/archive/2005/10/19/257479.html
发现可能其中一个原因是:
定义了一些错误页面是:aspx的,他在这里loop 死了。
当请求被发送到ASP.NET Worker Process时,先是由HttpRuntime的ProcessRequest方法处理,在ProcessRequest方法中,先从请求队列(RequestQueue)中获取有效的请求(GetRequestToExecute),如果有有效的请求,就调用HttpRuntime.ProcessRequestNow进行进一步的处理。而"Server Too Busy"的异常就是在GetRequestToExecute中产生的,GetRequestToExecute方法代码如下:
{
int num1;
int num2;
ThreadPool.GetAvailableThreads(out num1, out num2);
int num3 = (num2 > num1) ? num1 : num2;
if ((num3 < this._minExternFreeThreads) || (this._count != 0))
{
bool flag1 = RequestQueue.IsLocal(wr);
if ((flag1 && (num3 >= this._minLocalFreeThreads)) && (this._count == 0))
{
return wr;
}
if (this._count >= this._queueLimit)
{
HttpRuntime.RejectRequestNow(wr);
return null;
}
this.QueueRequest(wr, flag1);
if (num3 >= this._minExternFreeThreads)
{
wr = this.DequeueRequest(false);
return wr;
}
if (num3 >= this._minLocalFreeThreads)
{
wr = this.DequeueRequest(true);
return wr;
}
wr = null;
this.ScheduleMoreWorkIfNeeded();
}
return wr;
}
我们分析一下上面的代码:程序先从管理线程中获取有效线程的数目(num3)。如是num3大于minFreeThreads(该值对应于machine.config或者web.config中HttpRuntime段的minFreeThreads属性,即使执行新请求所需要的最小空闲线程数)并且请求队列中没有请求,则直接处理当前请求;如果num3小于minFreeThreads或者当前请求队列不为空("Server Too Busy"的请求就是这种情况), 从上面的代码中我们会发现当请求队列(RequestQueue)中请求数大于
_queueLimit(该值对应于machine.config或者web.config中HttpRuntime段的appRequestQueueLimit属性)时,HttpRumtime就会拒绝当前请求(RejectRequestNow),RejectRequestNow中直接调用RejectRequestInternal(HttpWorkerRequest wr), 在RejectRequestInternal中抛出了"Server_too_busy", 抛出异常后,立即捕获异常,你说怪吧,为什么不直接处理?为什么要在抛出异常后又捕获?有点多此一举?可能设计者还有其他考虑吧,比如为了代码更好的重用。
{
throw new HttpException(0x1f7, HttpRuntime.FormatResourceString("Server_too_busy"));
}
catch (Exception exception1)
{
context1.Response.InitResponseWriter();
this.FinishRequest(wr, context1, exception1);
return;
}
接着就是异常的处理,向客户端浏览器显示异常信息,调用FinishRequest, 在Finish中调用context.Response.ReportRuntimeError(e, true)显示异常信息,ReportRuntimeError会根据web.config中的CustomErrors设置决定是否重定向到defaultRedirect。
当你设置CustomErrors的defaultRedirect来定制处理异常信息时,如果遇到"Server_too_busy"就麻烦了,重定向到错误处理页面后,又被HttpRuntime拒绝,拒绝后又被重定向到defaultRedirect页面,HttpRuntime《———》HttpRuntime.....,似乎进入了一种恶性循环。原来问题有这么严重,写文章之前我还没想到,写到这我才发现。这样不停的来回,CPU岂不累死,当CPU累的不行时,就随便抛出一个其他异常:),也就是“Server Error in '/' Application.Runtime Error.”,这个异常我没找到在哪抛出的。难道在首次编译时,CPU占用很高与这个也有关系。我更新博客园服务器上的程序时,要几分钟才能恢复正常,而这时CPU基本是满负荷工作,难道也是这个问题引起,我想明天在访问高峰期测试一下就能得到证实。这似乎是设计者的一个疏忽,正确的做法应该是对于"Server_too_busy"异常,不管用户是否设置了defaultRedirect, 都不应该去重定向到defaultRedirect,而是直接向客户端发送异常信息,这是一个很特殊的情况,设计者在设计时可能没考虑到。