Kestrel是aspnetcore中的web服务器之一,其本身有跨平台,轻量级,高性能的特点
在 ryzen 1600 12核cpu 测试环境中,瞬间每秒处理请求数能达到2w5以上,与netty不相上下,相当于同样环境下iis ASP.NET处理能力的3倍左右
为了了解Kestrel为什么如此强劲,我从github上下载了源代码进行分析,地址是:
Kestrel端口监听参数使用的是 EndPoint ,包含了需要监听的IP和端口信息
对于每一个 EndPoint ,使用一个 ITransport 实例进行监听, ITransport 由 ITransportFactory 工厂创建
ITransportFactory 为单实例,默认为 SocketTransportFactory ,该工厂由 UseKestrel 的启动参数设置
Kestrel的有两种TransportFactory的实现
在启动时,首先从 ServiceCollection 中获取到 ITransportFactory ,使用工厂再创建一个 ITransport
SocketTransport 在初始化时创建一个调度器数组 _schedulers = PipeScheduler[]
数组大小为 ioQueueCount , ioQueueCount 从配置中读取,默认数量为cpu线程数,线程数不足16的情况下为16
如果指定了 ioQueueCount 的情况下,并且值为0,将会抛出异常
在 SocketTransport 中调度器使用的是 IOQueue 实现,其具体实现是通过 ThreadPool.QueueUserWorkItem 往线程池中工作队列添加工作任务
SocketTransport 启动后,将会运行一个循环任务,每次循环会循环所有调度器,通过 awit AcceptAsync 获取请求信息,然后交给调度器执行连接
对于Socket数据处理部分,使用的是异步Socket,Scoket不同平台的实现是不一样的
在Windows下,Scoket是对windows socket2的简单封装,windows socket2是一套支持阻塞/无阻塞的win32api
对于linux下的实现,我目前还在研究中,对其理解还不够深入
一般情况下,调度器的数量对Kestrel的处理能力影响不是很大,Kestrel对于请求的处理,都是通过往线程池添加工作任务来完成,其处理速度由线程池中的线程数量决定
总的来说,Kestrel是对异步Socket的简单封装,并利用线程池,内存池,实现了Actor模型,所有的请求都是无阻塞处理的,所以在处理能力上提升很大
当然,aspnetcore中间件管道模式也是其性能好的原因之一