kestral (红隼)
kestral server
源码 https://github.com/aspnet/KestrelHttpServer
1.微软为啥要做kestral 聊聊微软做kestral的背景和历史
在2000年之前的ASP.NET开发之初,Microsoft创建了容器来托管ASP.NET WebForms应用程序
Cassini,后来成为Visual Studio中的ASP.NET开发服务器。它是一个用C#编写的完全托管的Web服务器HttpListener
IIS上的ASP.NET支持
- iis5 请求模型
-
iis6 请求模型
-
iis7 请求模型
IIS7中对asp.net的请求不再是分两条处理管道,而是将asp.net和IIS集成起来。这样做的好处有很多,包括统一了请求验证工作,加强了asp.net对于请求的控制能力等等。在IIS7中,asp.net不再像IIS6一样只限定于aspnet_isapi.dll中,而是被解放出来,从IIS接收到HTTP请求开始,即进入asp.net的控制范围,as.net可以存在于一个请求在IIS中各个处理阶段。甚至可以为部署在IIS7中的PHP应用提供基于asp.net的验证身份验证功能
发展方向
1 ASP.NET变得更加复杂
2 与IIS集成更加紧密
3 IIS Express(用户模式精简版IIS) 取代了Cassini
Kestrel
2014年11月,ASP.NET 5(后来改名为ASP.NET Core)宣布成为跨平台技术。
显然,微软需要一种新的设计来支持Windows,macOS和Linux。而iis和window的强耦合基本上是无法移植到其他平台上的。
kestral应该说是微软为了托管跨平台的asp.net core定制的一款应用服务器容器。
1. 简介
kestral 是一款进程内web服务器(自托管),不同于asp.net需要把网站托管到iis上才能运行。
kestral 设计上大量“借鉴”了nodejs的设计思想,kestral I/O底层和nodejs 一样使用了Libuv,屏蔽了不通操作系统的I/O差异。nodejs 的中间件也在asp.net mvc core中找得到影子。和nodejs的express服务器一样,kestral也是应用内服务器容器。
kestral运行效率很高,Libuv有很大的功劳!
2.架构
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请求和返回。
Kestrel Web Server的工作原理
通常编写应用程序以响应人类行为。通过事件驱动编程,有一个监听事件的循环。然后它会触发回调函数。要减少SYS调用的数量,所有其他工作都在标准.NET工作线程的托管代码中执行。
Kestrel提供事件循环和基于回调的I / O通知。Libuv负责管理从操作系统收集和监控事件。此外,用户可以在事件发生时注册回调。因此,Kestrel使用libuv进行I / O工作,并支持运行多个事件循环。
由于它非常轻巧,因此Kestrel不允许您进行SSL终止,URL重写或GZip压缩,但相同的轻量级设计可以使其他Web服务器看起来比较慢。它建立得很快; 事实上,对于静态和纯文本操作,它比node.js快六倍。
Kestrel 的优点
Kestrel支持.NET Core支持的所有平台和版本。此外,它默认包含在ASP.NET Core新项目模板中,可以提供更好的请求处理性能。在Visual Studio中创建新项目时,您的项目将自动配置为在Kestrel中运行。
如前所述,它不是一个功能齐全的Web服务器,但这正是它快速的原因。
你要做的就是在一个功能完善的Web服务器比如IIS、Nginx上运行它。你可以在IIS上或者Visual Studio上的IIS Express上通过HttpPlatformHandler类来运行。
现在不仅仅可以跨平台运行,直接通过命令行都可以让ASP.NET在Web服务器上运行。
kestrel+http.sys
nuget包 Microsoft.AspNetCore.Server.HttpSys
HttpSys实现仅适用于Windows平台。
在早期版本的 ASP.NET Core 的中,HTTP.sys 被命名为 [WebListener]
HTTP.sys 是一项成熟的技术,可以抵御多种攻击,并提供可靠、安全、可伸缩的全功能 Web 服务器。 IIS 本身作为 HTTP.sys 之上的 HTTP 侦听器运行。
http.sys和ASP.NET Core Module 不兼容,所以不能和iis express/iis一起使用。
下图是Http.sys 实现端口共享的方式
下图显示了http.sys与应用程序之间的关系。
下图显示的是kestral和http.sys功能对比
3.运行方式
Kestrel直接与Internet通信,无需反向代理服务器
Kestrel通过反向代理服务器(如IIS,Nginx或Apache)间接与Internet通信
4.编码
启用kestral
配置URL
方式1
方式2
方式3
URL前缀
默认情况下,ASP.NET Core项目绑定了http://localhost:5000。通过使用UseUrls扩展方法——编辑urls命令行参数,或者是通过ASP.NET Core配置系统,你可以为Ketrel配置URL前缀和端口号以用来侦听请求。关于这些方法更多的信息,请参考Hosting。有关于当你使用IIS作为反向代理时,URL绑定是如何工作的信息,请参考ASP.NET Core 模块。
Kestrel URL前缀可以是以下格式中的任一种。
· IPv4 地址和端口号
http://65.55.39.10:80/
https://65.55.39.10:443/
· IPv6 地址和端口号
http://[0:0:0:0:0:ffff:4137:270a]:80/
https://[0:0:0:0:0:ffff:4137:270a]:443/
IPv6中的 [::] 等价于 IPv4 0.0.0.0。
· 主机名和端口号
http://*:80/
https://*:443/
主机名称,*,以及+,都不是特殊的。任何没有公认的IP 或是“localhost”的地址将绑定到所有的IPv4和IPv6的IP上。如果你需要为不同的ASP.NET Core应用在同一端口上绑定不同的主机名,请使用WebListener或者诸如IIS,Nginx或Apache这样的反向代理服务器。
* "Localhost" 名称和端口号或回送IP地址和端口号
http://127.0.0.1:5000/
http://[::1]:5000/
当localhost被指定时,Kestrel会尝试去绑定到IPv4和IPv6的环回接口。如果被请求的端口号正在任一环回接口上被其他服务所使用,Kestrel将会启动失败。如果任一环回接口出于各种原因而不可用(最通常的情况是因为IPv6暂不被支持),Kestrel将记录下一个警告信息。
· Unix socket
http://unix:/run/dan-live.sock
如果你指定了端口号0,Kestrel将动态地绑定到合适的端口号。除了localhost名称,绑定到0端口号被其他任何主机名称或IP地址所允许。
当你指定了端口号0,你可以使用IServerAddressesFeature接口去决定运行时Kestrel实际绑定到哪个端口。下列示例用于获取绑定端口并且在console上显示出来。
public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory)
{
loggerFactory.AddConsole();
var serverAddressesFeature = app.ServerFeatures.Get<IServerAddressesFeature>();
app.UseStaticFiles();
app.Run(async (context) =>
{
context.Response.ContentType = "text/html";
await context.Response
.WriteAsync("<p>Hosted by Kestrel</p>");
if (serverAddressesFeature != null)
{
await context.Response
.WriteAsync("<p>Listening on the following addresses: " +
string.Join(", ", serverAddressesFeature.Addresses) +
"</p>");
}
await context.Response.WriteAsync($"<p>Request URL: {context.Request.GetDisplayUrl()}<p>");
});
}
SSL的URL 前缀
如果你调用UseSSL扩展方法,请确保在https:中包含URL前缀,如下所示:
var host = new WebHostBuilder()
.UseKestrel(options =>
{
options.UseHttps("testCert.pfx", "testPassword");
})
.UseUrls("http://localhost:5000", "https://localhost:5001")
.UseContentRoot(Directory.GetCurrentDirectory())
.UseStartup<Startup>()
.Build();
Note
HTTPS和HTTP不能在同一端口上被托管。
正向代理 反向代理
反向代理服务器(Reverse Proxy Server)是通过在WEB服务器和Internet之间增加一个缓冲认证服务器来保障内部服务器的安全和可控访问。