ASP.NET Core 负载测试高错误率问题排查
你基于ASP.NET Core 8搭建的Hello World应用,在4000并发负载测试时出现80%的“Connection refused”错误,而同逻辑的Spring Boot应用仅7%错误,调整MaxConcurrentConnections和AllowSynchronousIO无效,以下是核心原因排查和解决方案:
1. Kestrel监听队列(Backlog)容量不足
TCP连接建立阶段,系统会维护一个监听队列存放待处理的SYN请求,当并发请求量超过队列长度,新连接会直接被拒绝。Kestrel默认使用操作系统的默认Backlog值(Windows默认200、Linux默认128),远低于Tomcat的并发处理配置阈值。
解决方法:在Program.cs中显式增大Backlog:
builder.WebHost.ConfigureKestrel(serverOptions => { serverOptions.ListenAnyIP(7271, listenOptions => { listenOptions.Backlog = 4096; // 可根据服务器配置调整至2048-8192 }); });
2. .NET线程池最小线程数不足
ASP.NET Core依赖.NET线程池处理请求,默认的线程池最小工作线程/IO线程数(通常为CPU核心数*2)无法应对4000并发的突发请求,导致请求处理滞后,连接堆积被拒绝。
解决方法:在应用启动时设置线程池最小线程数(需结合服务器CPU/内存配置,避免过度占用资源):
// 在builder.Build()之前添加 ThreadPool.SetMinThreads(1000, 1000); // 建议值:工作线程数 = CPU核心数 * 10~20,IO线程数可与工作线程数一致
3. 操作系统TCP参数限制
短时间内大量新建连接会触发操作系统的TCP限制,比如动态端口耗尽、TIME_WAIT队列堆积等,这是高并发短连接场景下的常见问题。
Windows系统调整:
以管理员身份打开命令提示符,执行以下命令:
# 扩大动态端口范围(从1024到65535,共64511个端口) netsh int ipv4 set dynamicport tcp start=1024 num=64511 # 启用TIME_WAIT连接重用,减少连接资源占用 netsh int tcp set global timestamps=enabled netsh int tcp set global tcp1323opts=enabled netsh int tcp set global fastopen=enabled
Linux系统调整:
编辑/etc/sysctl.conf文件,添加以下配置:
# 允许重用TIME_WAIT状态的连接 net.ipv4.tcp_tw_reuse = 1 # 快速回收TIME_WAIT连接 net.ipv4.tcp_tw_recycle = 1 # 扩大本地端口范围 net.ipv4.ip_local_port_range = 1024 65535 # 增大监听队列长度 net.core.somaxconn = 4096 # 增大SYN请求队列长度 net.ipv4.tcp_max_syn_backlog = 4096
执行sysctl -p使配置生效。
4. 负载测试工具连接复用配置问题
如果负载测试工具(如JMeter)禁用了HTTP Keep-Alive,每个请求都会新建TCP连接,短时间内会耗尽端口或触发监听队列限制。Spring Boot的Tomcat对短连接的默认优化更友好,因此错误率更低。
解决方法:在负载测试工具中启用HTTP Keep-Alive,让同一用户的请求复用TCP连接,大幅减少新建连接的数量。
5. 强制启用HTTP2多路复用
HTTP2支持单个TCP连接处理多个请求,能有效降低并发连接数压力。Kestrel默认支持HTTP1.1和HTTP2,但需确保配置正确。
解决方法:在Kestrel配置中明确启用HTTP1和HTTP2:
builder.WebHost.ConfigureKestrel(serverOptions => { serverOptions.ListenAnyIP(7271, listenOptions => { listenOptions.Protocols = HttpProtocols.Http1AndHttp2; // 若使用HTTP2明文传输(h2c),需确保负载测试工具支持 }); });
排查验证步骤
- 用
netstat -ano | findstr 7271(Windows)或ss -tulpn | grep 7271(Linux)查看连接状态,确认是否有大量TIME_WAIT或SYN_RECV状态的连接堆积。 - 查看应用日志,检查Kestrel是否输出监听队列满的警告信息。
- 对比Spring Boot的Tomcat配置(如
acceptCount、maxConnections),对齐核心参数进行测试。
内容的提问来源于stack exchange,提问作者망명 학살자

