全异步链路上进程外Kestrel经IIS反代并发异常问题咨询
进程外Kestrel经IIS反向代理的并发瓶颈排查与优化
问题核心特征锚定
所有排查均基于已验证的确定事实,避免无效跑偏:
- 全链路已完成async/await改造,直连Kestrel部署时完全符合异步模型的扩展特性:并发升高时响应时间稳定维持在单请求实际执行时长(1000ms),无明显吞吐瓶颈
- 仅在IIS作为反向代理承载进程外Kestrel时出现异常:最大稳定吞吐仅为9rps,超过该阈值后响应时间随目标并发呈指数级上涨(15rps目标下响应2200ms,25rps目标下响应4500ms)
- 应用侧线程数始终低于40,不存在应用代码导致的线程饥饿问题
高概率根因与对应排查方法
1. IIS反向代理组件的默认连接数限制
这是该场景下最常见的触发点:
- 原理:IIS实现反向代理依赖
ARR(应用请求路由)模块,ARR默认配置下,每个后端服务器的最大并发连接数仅为5;同时承载ASP.NET Core进程外部署的ANCM(ASP.NET Core模块)也存在默认的单后端进程并发连接节流限制,两层限制叠加后刚好形成个位数并发的吞吐阈值 - 排查动作:
- 检查ARR模块的后端连接池配置,确认默认连接数阈值
- 用
netstat或Get-NetTCPConnection命令统计IIS进程到后端Kestrel进程的活跃TCP连接数,当连接数稳定在9左右、无法继续上升时,即可确认连接池上限 - 开启IIS请求跟踪日志,定位请求处理阶段的耗时占比,若瓶颈阶段出现在代理排队环节而非后端Kestrel处理环节,即可锁定该方向
- 优化方向:
- 调整ARR对每个后端节点的最大并发连接数,匹配服务端可承载的并发能力(如设置为100以上)
- 关闭ANCM默认的并发请求节流配置
2. 单连接复用引发的队头阻塞
- 原理:若ARR与后端Kestrel之间的通信配置为复用少量TCP连接跑HTTP/1.1,长时运行的异步请求(如测试场景中1000ms的存储过程调用)会在单连接上形成串行排队,即使后端Kestrel本身可并行处理请求,代理层的连接复用也会将并发请求强制串行化
- 排查动作:
- 抓包分析IIS与Kestrel之间的TCP流,确认是否存在大量请求串行复用同一TCP连接的现象
- 对比调整连接池大小前后的抓包结果,看并发请求是否被分发到多个独立TCP连接处理
- 优化方向:
- 拉大代理到后端的连接池大小,确保每个并发请求可分配独立连接
- 升级代理与后端之间的通信协议为HTTP/2,消除单连接的队头阻塞
3. 请求队列等待引发的响应时间指数增长
- 原理:当并发请求量超过代理层的最大连接数阈值时,所有超出的请求会进入IIS的内部请求队列排队,队列等待时间会随请求到达速度线性增长,结合单请求1000ms的固定处理时长,最终表现为并发翻倍时响应时间近似翻倍的指数级曲线(与测试观察到的1010ms→2200ms→4500ms的增长规律完全吻合)
- 排查动作:
- 采集IIS请求队列的长度指标,看队列长度是否随目标并发的升高线性增长
- 拆分请求全链路的耗时:代理接收耗时、代理排队耗时、后端处理耗时、响应回传耗时,若排队耗时占总耗时的80%以上,即可确认该机制是响应时间暴涨的直接原因
- 优化方向:
- 放开代理层的连接数上限,减少请求排队等待
- 配置合理的队列长度限制,避免无界排队导致的雪崩
快速根因验证步骤
- 临时放开IIS反代链路的所有默认连接限制,重新执行相同压测脚本,观察吞吐和响应时间是否与直连Kestrel的表现一致
- 分别在IIS侧、Kestrel侧采集运行指标:活跃连接数、请求队列长度、CPU使用率、请求各阶段耗时,定位瓶颈的准确位置
- 若调整连接限制后瓶颈消失,即可确认根因为IIS反代组件的默认配置阈值过低
内容的提问来源于stack exchange,提问作者Adrian Alexandru
相关产品推荐
相关产品推荐

