HTML5技术

ASP.NET Core Web服务器 Kestrel和Http.sys 特性详解 - 行动派Xdpie

字号+ 作者:H5之家 来源:H5之家 2017-09-15 17:05 我要评论( )

1.1. 名词解释 内核态: CPU可以访问内存所有数据, 包括外围设备, 例如硬盘, 网卡. CPU也可以将自己从一个程序切换到另一个程序。 用户态: 只能受限的访问内存, 且不允许访问外围设备. 占用CPU的能力被剥夺, CPU资源可以被其他程序获


1.1. 名词解释

内核态: CPU可以访问内存所有数据, 包括外围设备, 例如硬盘, 网卡. CPU也可以将自己从一个程序切换到另一个程序。

用户态: 只能受限的访问内存, 且不允许访问外围设备. 占用CPU的能力被剥夺, CPU资源可以被其他程序获取。

1.2. Kestrel基本工作原理

Kestrel是进程内服务器,以一个包形式提供,自身不能单独运行,必须HOST在一个.NET的WEB应用程序中。它内部封装了对libuv的调用,但不是libuv库简单的封装库。Kestrel是个精简的,高效的Http Server。

1.2.1. Kestrel的基本架构

Kestrel遵循以下架构原则:

对应的架构图如下:

2017-09-13-23-07-16

  • Libuv

    作为I/O底层,屏蔽各系统底层实现差异,为windows下,通过IOCP实现异步;linux下通过epoll实现异步。提供一个主程序和主循环。

  • I/O事件队列

    对应Libuv的工作队列,为了利用现代服务器的多核处理器,适当的队列数量将提高更大的I/O吞吐能力。Kestrel默认为每两个CPU核心设置一个I/O事件队列,但至少有一个I/O事件队列。每个队列对应一个托管线程,该线程不属于线程池。用户可以设置队列个数,通过设置KestrelServerOptions.ThreadCount即可,最多设置16个。

  • Kestrel线程

    事件队列对应的托管线程,主要控制读取事件的循环机制:每次事件循环处理8个事件,然后等待下一次循环。

  • 非托管内存池

    这是在.net运行环境分配的非托管内存池,申请的比较大块的堆内存,仅在首次请求或者池剩余空间不足时分配,后续请求可以复用,不受GC管理。内存被分为n片,每片大小是128K,每页大小4k,管理内存页的数据结构采用链表方式。以获取大块连续空间的方式增长。遵循读完后立即释放的处理原则。

  • TCP监听器

    这个监听器不同于套接字的监听器,而是Libuv的Socket类型的连接事件监听器。监听TCP连接事件,对每一个TCP请求产生一个连接对象。连接对象包括暂停,继续,终止。

  • 连接管理

    负责异步结束连接对象。

  • HTTP协议模块

    该模块包括HTTP帧的创建工厂,工厂在监听器监听到一个连接时产生一个HTTP帧。一个HTTP帧处理一次HTTP请求和返回。

  • 更为详细的结构视图如下:

    2017-09-13-23-23-55

    1.2.2. Kestrel的工作原理 1.2.2.1. 处理Request和Response

    2017-09-14-21-21-30

    按照请求流转方向会有以下处理过程:

    1. 请求进入libuv

    将请求事件放入事件队列,随后的事件循环中,监听器回调函数执行。

    2. 监听器创建连接

    根据请求信息创建一个连接对象,此时Http帧工厂被调用,产生一个Http帧对象;用于读取Request的SocketInput、用于返回Response的SocketOutput对象被创建,二者会被Http帧使用。

    3. 连接管理监控连接

    连接管理器跟踪连接的状态,收集待关闭连接,然后异步关闭。

    4. Http帧处理

    一个Http负责构建Http上下文的Request对象和Response对象。读取Request数据和返回Response数据都要经过内存池。高效的内存读写和与和Libuv的读写事件协调,确保Request数据到达就能读到内存池,到达内存池就能及时被读;Response数据写入内存池就能被套接字及时发出去,体现了Kestreld强大的异步处理能力。

    1.2.2.2. 内存池读写

    读取内存池数据时可读取后续到达的数据,不需要重新等待事件,此时对应读取Request数据情形:

    2017-09-14-23-42-10

    写数据到内存池时,libuv连续读出并发送数据,也不需要重新等待时间,此时对应发送Response数据情形:

    2017-09-14-23-42-58

    1.2.2.3. Libuv线程和托管线程通信

    二者的通信机制保证Libuv线程永远不会被阻塞:比如libuv线程在通知事件时会很小心尝试获取队线程私有锁,如果成功获取就这在事件队列线程上异步处理,否则这一通信过程在线程池里重复执行直到成功,如图:

    2017-09-14-23-28-33

    1.3. Http.sys基本工作原理 1.3.1. Http.sys基本构成

    2017-09-10-12-25-14

    1. 监听器

    监听TCP请求,允许端口共享。TCP携带的HTTP报文会被Http Parser解析,名称映射首先会根据url确定对应的web app,然后把请求放入该app的消息队列中。

    2. 消息队列

    Http.sys给每个注册的web app一个消息队列。

    3. 响应缓存

    请求的静态资源和GET请求会缓存起来一段时间,如果请求url能匹配这直接返回缓存数据。

    4. 响应模块

    将数据返回给用户代理,如果返回的是可以缓存的资源,则会放入响应缓存中。

    1.3.2. Http.sys工作原理

    下图表示在ASP.NET Core应用中接受一个http请求到返回数据的过程:

    2017-09-10-11-29-05

    1.3.3. 总结

    Kestrel服务器运行在Asp.net core应用程序中,能高效的处理网络请求,且跨平台。Http.sys运行在内核态中,极大减少了系统调用次数,运行效率很高;自带生存环境的安全,鲁棒性等特点;它也可以作为反向代理,因此它的功能更加强大,主要问题是只能运行在windows下。Kestrel应用在生产环境中需要运行在代理服务器后面,以获取安全性,负载均衡等能力。

    功能 Http.sys Kerstrel

    平台支持 Windows Windows/Linux/Mac

    静态文件 Yes Yes

    HTTP访问日志 Yes No

    端口共享/多应用程序 Yes No

    SSL证书 Yes Internal*

    Windows 授权 Yes No

    过滤请求&限制 Yes No

    IP&域名约束 Yes No

    HTTP重定向规则 Yes No

    WebSocket 协议 Yes Middleware

    缓存Response Yes No

    压缩 Yes Yes

    FTP服务器 Yes No

    运行态 内核态 用户态

    * Internal:https通信仅仅工作在反向代理服务器后面与ASP.NET程序之间,如果要想外暴露https服务这需要用到反向代理,比如IIS,nginx,apached。

    参考文章

    https://stackify.com/kestrel-web-server-asp-net-core-kestrel-vs-iis/

    作者:帅虫哥 出处:

     

    1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

    相关文章
    • Entity Framework Core Like 查询揭秘 - Sweet-Tang

      Entity Framework Core Like 查询揭秘 - Sweet-Tang

      2017-09-13 12:05

    • ASP.NET Core 运行原理解剖[5]:Authentication - 雨の夜

      ASP.NET Core 运行原理解剖[5]:Authentication - 雨の夜

      2017-09-11 11:16

    • 【ASP.NET MVC】View与Controller之间传递数据 - Alan_beijing

      【ASP.NET MVC】View与Controller之间传递数据 - Alan_beijing

      2017-09-10 08:02

    • .NET Core多平台开发体验[4]: Docker - Artech

      .NET Core多平台开发体验[4]: Docker - Artech

      2017-09-07 11:57

    网友点评
    h