|
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
语言是不是不是最重要的?当你会见博客园,呈现“ServerErrorin/Application.RuntimeError.”的毛病时,你晓得这个毛病的面前是甚么吗?你大概会想,博客园怎样不计划个定制毛病页面?如许的毛病页面让会见者手足无措,只能埋怨“服务器出成绩了”。当呈现这个成绩时,我急啊!
真想站到互联网上,拿着年夜喇叭对人人喊,我刚更新了程序大概修正了web.config的设置,asp.net在举行初次编译,在编译的同时还要处置大批的哀求,忙不外来,只能回绝哀求,实践的毛病信息是"ServerTooBusy",毛病来自HttRuntime的RejectRequestInternal办法。你大概会说用customErrors页面处置一下啊!但是HttRuntime已回绝了这个哀求,重定向到defaultRedirect定制毛病页面,仍是被回绝,了局就呈现“ServerErrorin/Application.RuntimeError.”毛病。这个成绩困扰我很长工夫,当更新程序(大概修正web.config的设置、使用程序池接纳、IIS重启)时,就会呈现这个成绩,特别是会见岑岭期,要几分种才干恢复一般,忧郁!如果在这时候显现一个友爱的毛病显现页面,那该多好啊!明天早晨更新程序时,又碰到这个成绩。我再次下决计要办理这个成绩。
要办理成绩,起首要剖析出为何会呈现成绩。既然是HttRuntime抛出的非常,那就从HttRuntime动手。怎样动手呢?用壮大的Reflector工具,微软这点做的不错,良多.NET类库都能够经由过程Reflector工具检察源代码。经由过程剖析HttRuntime的源代码,我找到了成绩的缘故原由,这里我复杂地形貌了一下:
当哀求被发送到ASP.NETWorkerProcess时,先是由HttpRuntime的ProcessRequest办法处置,在ProcessRequest办法中,先从哀求行列(RequestQueue)中猎取无效的哀求(GetRequestToExecute),假如有无效的哀求,就挪用HttpRuntime.ProcessRequestNow举行进一步的处置。而"ServerTooBusy"的非常就是在GetRequestToExecute中发生的,GetRequestToExecute办法代码以下:
internalHttpWorkerRequestGetRequestToExecute(HttpWorkerRequestwr)
{
intnum1;
intnum2;
ThreadPool.GetAvailableThreads(outnum1,outnum2);
intnum3=(num2>num1)?num1:num2;
if((num3<this._minExternFreeThreads)||(this._count!=0))
{
boolflag1=RequestQueue.IsLocal(wr);
if((flag1&&(num3>=this._minLocalFreeThreads))&&(this._count==0))
{
returnwr;
}
if(this._count>=this._queueLimit)
{
HttpRuntime.RejectRequestNow(wr);
returnnull;
}
this.QueueRequest(wr,flag1);
if(num3>=this._minExternFreeThreads)
{
wr=this.DequeueRequest(false);
returnwr;
}
if(num3>=this._minLocalFreeThreads)
{
wr=this.DequeueRequest(true);
returnwr;
}
wr=null;
this.ScheduleMoreWorkIfNeeded();
}
returnwr;
}
我们剖析一下下面的代码:程序先从办理线程中猎取无效线程的数量(num3)。如是num3年夜于minFreeThreads(该值对应于machine.config大概web.config中HttpRuntime段的minFreeThreads属性,即便实行新哀求所必要的最小余暇线程数)而且哀求行列中没有哀求,则间接处置以后哀求;假如num3小于minFreeThreads大概以后哀求行列不为空("ServerTooBusy"的哀求就是这类情形),从下面的代码中我们会发明当哀求行列(RequestQueue)中哀求数年夜于
_queueLimit(该值对应于machine.config大概web.config中HttpRuntime段的appRequestQueueLimit属性)时,HttpRumtime就会回绝以后哀求(RejectRequestNow),RejectRequestNow中间接挪用RejectRequestInternal(HttpWorkerRequestwr),在RejectRequestInternal中抛出了"Server_too_busy",抛出非常后,当即捕捉非常,你说怪吧,为何不间接处置?为何要在抛出非常后又捕捉?有点画蛇添足?大概计划者另有其他思索吧,好比为了代码更好的重用。
try
{
thrownewHttpException(0x1f7,HttpRuntime.FormatResourceString("Server_too_busy"));
}
catch(Exceptionexception1)
{
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累的不可时,就任意抛出一个其他非常:),也就是“ServerErrorin/Application.RuntimeError.”,这个非常我没找到在哪抛出的。岂非在初次编译时,CPU占用很高与这个也有干系。我更新博客园服务器上的程序时,要几分钟才干恢复一般,而这时候CPU基础是满负荷事情,岂非也是这个成绩引发,我想今天在会见岑岭期测试一下就可以失掉证明。这仿佛是计划者的一个忽略,准确的做法应当是关于"Server_too_busy"非常,不论用户是不是设置了defaultRedirect,都不该该往重定向到defaultRedirect,而是间接向客户端发送非常信息,这是一个很特别的情形,计划者在计划时大概没思索到。
在写文章之前,我并没有觉察这个成绩云云严峻。但我想到了一个另类的办理办法,既然产生"Server_too_busy"时,HttpRuntime不会处置任何哀求,那该Web使用程序中再怎样处置也是杯水车薪的,我们从其他中央找冲破口,产生"Server_too_busy"非常时,重定向到defaultRedirect会带来严峻的成绩,但却能够使用这一点把成绩化解为办理办法,这个办理办法就是:将defaultRedirect设置为别的一个网站的地点,既然这个网站回绝处置哀求,那我把哀求转给别的一个网站,总能够吧,由别的一个网站来显现友爱的毛病信息,如许不但办理了定制“ServerTooBusy”毛病信息的成绩,并且能够削减对主网站的哀求,让主网站有更多的工夫处置以后的义务。好比:博客园如今就创建了一个sorry.cnblogs.com的站点,将defaultRedirect设置为这个站点。这个办法另类吧!
有了这个办法,我们今后就不怕"Server_too_busy"了,能够轻松更新程序、修正web.config,只需将defaultRedirect的页面计划得让人人以为等几分钟也不舒服就好了。好比:放一段美好的音乐、笑话、弄笑图片、***,固然过份的网站大概会放告白。
也不知道,我同学昨天说数据挖掘很好。 |
|