在Windows生态的Web服务矩阵中,IIS服务器常常被低估。许多管理员将其视为“点几下鼠标就能跑起来”的默认组件,但当流量洪峰到来时,那些未经调校的默认配置往往会成为性能瓶颈的温床。本文不谈泛泛而谈的理论,直接切入那些能对吞吐量、延迟和资源占用产生立竿见影效果的关键旋钮。
IIS的应用池回收机制本意是防止内存泄漏累积,但默认的“29小时回收”和“特定时间回收”设置,在流量持续高位运行时,会引发周期性的请求排队风暴。每次回收都意味着工作进程(w3wp.exe)的冷启动,包括重新加载托管代码、重建数据库连接池、重新编译ASP.NET视图。这种周期性抖动在监控图上表现为规律的锯齿状延迟尖峰。
深度优化建议:并非取消回收,而是将回收策略从“固定时间间隔”改为“基于虚拟内存/私有内存限制”的触发式回收。同时,启用应用池的“重叠回收”功能(即.NET 4.0+的Startup Time Limit与Shutdown Time Limit),让旧进程处理完存量请求后再优雅退出,新进程并行预热。这能将因回收引发的请求失败率从千分位降至零。
IIS的核心是HTTP.SYS内核驱动,它负责监听TCP端口并管理请求队列。默认的queue length(队列长度)为1000,但若后端应用处理速度跟不上,队列溢出后HTTP.SYS会直接返回503 Service Unavailable。更隐蔽的是,内核队列的HideNonSecureRequests参数以及RequestFilteringModule中URL长度限制、查询字符串长度限制,这些看似安全加固的项,在高并发长URL请求场景下会成为隐形杀手。
实战调整方向:在注册表 HKLM\System\CurrentControlSet\Services\HTTP\Parameters 下,将MaxFieldLength与MaxRequestBytes从默认的16KB提升至32KB或更高(需权衡安全风险)。同时,将应用池的队列长度设置为CPU核心数的16倍左右(例如8核机器设为128),过大的队列反而会导致后端积压,延长客户端等待时间。
很多优化文章强调启用输出缓存,但鲜有人深究IIS的内核缓存(Kernel Cache)。当响应头包含Cache-Control: public且无Vary头时,HTTP.SYS可以直接将静态文件或动态输出的字节流缓存在内核地址空间。这意味着客户端请求不必再切换到用户模式,也不占用工作进程的CPU时间。
关键配置点:在IIS管理器的“输出缓存”功能中,针对动态扩展名(如.aspx或.ashx)添加缓存规则,并设置“如果请求头包含Cookie则跳过缓存”,避免为个性化内容意外提供陈旧数据。对于静态资源(.js/.css/.png),应确保启用“缓存控制头”的公共读取,并配合HTTP压缩静态内容。这里有一个容易被忽略的陷阱:若开启了动态压缩(gzip),内核缓存将失效,因为压缩发生在用户模式。因此,对于极高频的API响应(如JSON),应权衡是压缩省带宽还是内核缓存省CPU。
托管的ASP.NET应用受.NET CLR线程池约束。默认设置下,maxWorkerThreads与maxIoThreads为20/核(.NET 4.5+实际为32767),但minFreeThreads与maxConcurrentRequestsPerCPU(在aspnet.config中)往往保持默认,导致高并发时线程池切换频繁。更隐蔽的是,IIS的appConcurrentRequestLimit(默认5000)若被调低,会直接拒收后续请求。
一个典型优化组合:在aspnet.config中,将minFreeThreads设置为CPU核数的2倍,将maxConcurrentRequestsPerCPU设置为100(对于纯API服务)或5000(对于混合工作负载)。同时,在machine.config中调整processModel autoConfig="true"下的maxWorkerThreads为100/核,并确保enableMinIdleThreads设置为true,让线程池在空闲时保留至少25个工作线程,避免突发流量时线程注入的延迟。
IIS的W3C日志记录如果设置为“每个请求”记录所有字段(包括查询字符串、用户代理、Referer),在高QPS下会显著增加磁盘I/O,甚至导致日志文件锁竞争。建议将日志记录节流为“错误请求”或“状态码大于400”的请求,或者将字段精简为:日期、时间、客户端IP、方法、URI、状态码、时间花费。同时启用“日志文件滚动周期”为每小时,避免单个超大文件。
更高级的优化:使用Failed Request Tracing(FREB)时,默认的跟踪规则会捕获所有请求的完整事件流,这是巨大的性能损耗。务必在traceFailedRequests中设置statusCodes仅为500-599,并限制areas为Authentication或Security,而不是全部。
IIS的性能优化本质上是系统资源、内核机制与托管运行时三者之间的协同。没有一套配置适合所有业务场景。建议在灰度环境使用wrk或Vegeta进行压测,重点观察“排队请求数”(Performance Monitor中的HTTP Service\Request Queues计数器)与“工作进程CPU”的比值。当排队数持续大于0且CPU未满时,问题在HTTP.SYS或应用池回收;当CPU满载时,转向线程池与代码效率优化。这套方法论,远胜于照搬任何“最佳实践”清单。