打开站点是一张白页,上面只有Service Unavailable一行字,没有堆栈、没有黄屏、也没有异常信息。碰到这种报错别去翻应用自己打的日志,页面什么都不透露,线索全在应用池的状态和两个系统日志里。
先看清是哪个503
IIS把503拆成了几个子状态码,报错页底部那行灰色小字、以及IIS日志的sc-substatus列都能看到:503.0是应用程序池不可用,请求打进了一个已经停掉的池;503.2是并发请求数超过了appConcurrentRequestLimit;503.3是ASP.NET队列满;503.4是FastCGI队列满。绝大多数现场遇到的是503.0,排查方向也就和另外三个完全不同——503.2、503.4要的是扩容和调参,503.0要的是把池重新拉起来并找出它为什么死。
页面上看不到子状态码时,直接查IIS日志的最后几行,第10列是sc-status、第11列是sc-substatus:
cd /d %SystemDrive%\inetpub\logs\LogFiles\W3SVC1 && findstr /C:" 503 " u_ex*.log
应用池是不是被自动停了
这一步决定后面所有动作。进inetsrv目录列出全部应用池的状态:
cd /d %windir%\system32\inetsrv appcmd list apppool
正常是Started,看到Stopped就是它了。顺便看看哪些w3wp进程还活着:
appcmd list wp
池停掉的原因一般在系统日志里,来源是WAS(Windows Process Activation Service)。几个事件ID要认得:5002说明应用池因为连续失败被自动禁用,也就是触发了快速故障防护;5011是工作进程与WAS之间发生致命通信错误;5021是应用池标识的账号密码不对或者已过期;5059是池被正式禁用。用wevtutil直接过滤比开事件查看器快:
wevtutil qe System /q:"*[System[Provider[@Name='Microsoft-Windows-WAS'] and (EventID=5002 or EventID=5011 or EventID=5021)]]" /f:text /c:10
快速故障防护的默认值是5分钟内失败5次就把池停掉,这个设置在应用池的高级设置里能看到。见过不少现场的做法是直接把它关掉,池是起来了,可崩溃循环还在,机器内存被反复吃光,问题反而更难查。改大阈值可以,关掉不行。
这个坑踩过不止一次:周末域密码策略把服务账号密码过期了,周一早上站点全站503,系统日志里清一色5021。处理办法是在应用池高级设置的标识里重新输一遍密码。
顺着时间找到真正的崩溃原因
5002只是结果。往前翻同一时间段的应用程序日志,看来源.NET Runtime的事件1026(异常类型与堆栈)和来源Application Error的事件1000(故障模块名)。实测大部分503都能在这一步直接定位:缺DLL、配置文件格式错、连接字符串指向了已下线的数据源,都会以未处理异常的形式把w3wp进程打挂。
事件日志只给到异常类型、看不出具体位置时,用DebugDiag对w3wp.exe挂一条崩溃规则,复现之后读它生成的分析报告,故障堆栈会点名到具体的原生模块。
httperr.log能确认到底是谁拒的请求
这个文件经常被忽略,位置在:
%SystemDrive%\Windows\System32\LogFiles\HTTPERR\httperr*.log
503那一行末尾有个原因短语:AppOffline表示应用被停用,QueueFull表示请求队列排满,ConnLimit表示撞上了并发连接上限。AppOffline与上面的5002是配套的;QueueFull说明应用是真的慢,不是队列长度配错了——把queueLength从默认的1000调大只是让排队的人多等一会儿,救不了慢本身。
标识权限与Load User Profile
应用池用ApplicationPoolIdentity这种虚拟账号时,站点目录得给它读权限,否则进程一起来就崩:
icacls D:\sites\myapp /grant "IIS AppPool\MyAppPool:(OI)(CI)RX" /T
还有个冷门的:Load User Profile被设成true时,IIS要在C:\Users下给虚拟账号建一个同名目录,虚拟账号的SID都以S-1-5-82-开头。当初碰到过一台机器,管理员手工删过这类目录,注册表ProfileList下的残留项还留着,结果池一启动就崩,系统日志照样是5002。把残留项清掉、或者先把Load User Profile改成false,池立刻就正常了。
并发与队列的两个数
子状态码是503.2的话,改的是serverRuntime的appConcurrentRequestLimit,默认值5000:
appcmd set config -section:system.webServer/serverRuntime /appConcurrentRequestLimit:10000 /commit:apphost
改完不必重启IIS,配置落在applicationHost.config里即刻生效。这个值调大之前先想清楚:并发上去了,下游数据库连接池撑不撑得住,不然只是把503换成超时。
确认恢复
appcmd start apppool /apppool.name:MyAppPool
启动之后盯两分钟IIS日志与httperr.log,看是不是回到200、有没有新的503进账。改完不验证,第二天早上还是同样一张白页,这种事见过太多次。
另外提醒一句,Windows Server 2016、2019、2022与2025带的都是IIS 10.0,2012 R2上是IIS 8.5,2008 R2上是IIS 7.5,应用池相关的配置路径基本一致;不过从2022开始默认不再装IIS管理控制台的部分旧组件,appcmd一律可用,图形界面不一定在。
数据截至2026年10月,涉及的系统版本号为Windows Server build 10.0.14393、10.0.17763、10.0.20348与10.0.26100。