为何Kestrel性能不及IIS?本地.NET性能对比测试疑问
为什么IIS处理请求速度远快于Kestrel?
这事儿确实有点反直觉,毕竟大家都默认Kestrel性能更优,但结合你的测试场景和配置,我梳理了几个可能的原因,帮你排查:
1. 底层HTTP服务的差异:HTTP.sys vs 原生Kestrel
IIS是基于Windows内核级的HTTP.sys驱动运行的,这个组件是系统级的,自带一堆硬核优化:
- 本地回环请求时,能跳过用户态到内核态的多次切换开销
- 内置连接复用、内核级请求队列,TCP/IP栈的优化也更成熟
而你当前的Kestrel是直接用用户态的网络栈(早期版本用libuv,新版本用Windows Sockets)处理请求,在Windows本地回环场景下,完全没有HTTP.sys的内核级优势。如果把Kestrel改成用HTTP.sys模式运行,性能应该会和IIS接近——你可以试试在配置里替换成.UseHttpSys():
public static IWebHost BuildWebHost(string[] args) => WebHost.CreateDefaultBuilder(args) .UseHttpSys(options => { options.MaxConcurrentConnections = 1000; options.Listen(IPAddress.Loopback, 5050); }) .ConfigureLogging((context, logging) => { logging.ClearProviders(); }) .UseStartup<Startup>() .Build();
2. 测试程序的潜在瓶颈
你的测试代码有几个可能拖后腿的地方:
- 每次请求都新建
RestClient:RestClient是线程安全的,频繁创建销毁会带来额外开销,应该复用实例 - 无控制的异步请求:循环里直接发起
ExecuteAsyncGet且不等待回调完成,容易导致客户端侧套接字耗尽、线程池阻塞,反而限制了服务器的表现
建议换专业压测工具(比如k6、wrk)重新测试,避免客户端成为瓶颈。比如用k6写个简单脚本:
import http from 'k6/http'; import { sleep } from 'k6'; export const options = { vus: 20, duration: '30s', }; export default function () { http.get('http://localhost:5050/api/values'); sleep(0.01); }
3. Kestrel的配置未充分优化
你只设置了MaxConcurrentConnections,但还有几个关键配置可能没到位:
- 确认
gcServer是否真生效:检查项目.csproj里有没有加<ServerGarbageCollection>true</ServerGarbageCollection>,光靠配置文件可能不生效,服务器GC对高并发场景的性能提升很明显 - 调整线程池最小线程数:在Program.cs开头加一行
ThreadPool.SetMinThreads(100, 100);(数值根据CPU核心调整),避免线程池冷启动拖慢请求处理 - 启用HTTP/2:在Kestrel配置里加
.UseHttp2(),多路复用能大幅提升并发请求的处理效率
4. .NET Core版本的影响
如果你用的是较老的.NET Core版本(比如2.x),Kestrel的性能优化还没跟上,而.NET Framework 4.6.1的IIS已经是非常成熟的稳定版本。建议升级到.NET 6+这类LTS版本,新版本的Kestrel在Windows上做了大量适配优化,性能会有明显提升。
5. IIS的进程模型优势
IIS默认的应用池可以配置为多进程(Web Garden),能在多核机器上分散负载;而你的Kestrel是单进程运行,即使开了服务器GC,也需要线程池配合才能充分利用多核资源,否则在高并发下可能不如IIS的多进程模式高效。
内容的提问来源于stack exchange,提问作者smoksnes
相关产品推荐
相关产品推荐

