ASP.NET Core的Kestrel服务器(转载)
Kestrel是一个基于libuv的跨平台ASP.NET Core web服务器,libuv是一个跨平台的异步I/O库。ASP.NET Core模板项目使用Kestrel作为默认的web服务器。
Kestrel支持以下功能:
- HTTPS
- 用于启用不透明升级的WebSockets
- 位于Nginx之后的高性能Unix sockets
Kestrel 被.NET Core支持的所有平台和版本所支持
何时使用Kestrel和反向代理服务器
如果你的应用只接收来自内部网络的请求,你可以只使用Kestrel本身。
如果你将你的应用部署在公共网络上,我们建议你使用IIS,Nginx或者Apache作为反向代理服务器。一个反向代理服务器接收来自网络的HTTP请求并且在经过一些初步处理后将请求传递到Kestrel服务器。
出于安全性的理由,反向代理常常被edge deployments所采用。因为Kestrel相对较新,对抵御安全攻击至今还没有一个完整的功能补充。安全性处理包括但不限于适当的超时,大小的限制,以及并发连接限制等问题。
另一个需要反向代理的场景是,你有多个需要在单独的服务器上运行并分享同一端口的应用。因为Kestrel不支持在多进程间分享同一端口,所以应用并不能直接和Kestrel合作。当你在某个端口上配置Kestrel运行侦听时,不算主机头如何标识,Kestrel会为该端口处理所有的流量。反向代理可以为多个应用共享唯一端口并将流量发送给Kestrel。
即使不需要反向代理服务器,使用它也可以简化负载均衡和SSL设置 -- 只要你的反向代理服务器需要SSL证书,并且该服务器可以和你的应用在内部网中通过普通HTTP进行通信。
托管模型
进程内托管模型
使用进程内托管,ASP.NET Core 在与其 IIS 工作进程相同的进程中运行。 这样可消除通过环回适配器代理请求时的进程外性能损失,环回适配器是一个网络接口,用于将传出的网络流量返回给同一计算机。 IIS 使用 Windows 进程激活服务 (WAS) 处理进程管理。
ASP.NET Core 模块:
- 执行应用初始化。
- 加载 CoreCLR。
- 调用 Program.Main。
- 处理 IIS 本机请求的生存期。
下图说明了 IIS、ASP.NET Core 模块和进程内托管的应用之间的关系:
请求从 Web 到达内核模式 HTTP.sys 驱动程序。 驱动程序将本机请求路由到网站的配置端口上的 IIS,通常为 80 (HTTP) 或 443 (HTTPS)。 该模块接收本机请求,并将它传递给 IIS HTTP 服务器 (IISHttpServer)。 IIS HTTP 服务器是将请求从本机转换为托管的 IIS 进程内服务器实现。
IIS HTTP 服务器处理请求之后,请求会被推送到 ASP.NET Core 中间件管道中。 中间件管道处理该请求并将其作为 HttpContext 实例传递给应用的逻辑。 应用的响应传递回 IIS,IIS 将响应推送回发起请求的客户端。
进程内托管选择使用现有应用,但 dotnet new 模板默认使用所有 IIS 和 IIS Express 方案的进程内托管模型。
进程外托管模型
由于 ASP.NET Core 应用在独立于 IIS 工作进程的进程中运行,因此该模块会处理进程管理。 该模块在第一个请求到达时启动 ASP.NET Core 应用的进程,并在应用关闭或崩溃时重新启动该应用。 这基本上与在 Windows 进程激活服务 (WAS) 托管的进程内运行的应用中出现的行为相同。
下图说明了 IIS、ASP.NET Core 模块和进程外托管的应用之间的关系:
请求从 Web 到达内核模式 HTTP.sys 驱动程序。 驱动程序将请求路由到网站的配置端口上的 IIS,通常为 80 (HTTP) 或 443 (HTTPS)。 该模块将该请求转发到应用的随机端口(非端口 80/443)上的 Kestrel。
该模块在启动时通过环境变量指定端口,IIS 集成中间件将服务器配置为侦听 http://localhost:{PORT}。 执行其他检查,拒绝不是来自该模块的请求。 该模块不支持 HTTPS 转发,因此即使请求由 IIS 通过 HTTPS 接收,它们还是通过 HTTP 转发。
Kestrel 从模块获取请求后,请求会被推送到 ASP.NET Core 中间件管道中。 中间件管道处理该请求并将其作为 HttpContext 实例传递给应用的逻辑。 IIS 集成添加的中间件会将方案、远程 IP 和 pathbase 更新到帐户以将请求转发到 Kestrel。 应用的响应传递回 IIS,IIS 将响应推送回发起请求的 HTTP 客户端。
有关 IIS 和 ASP.NET Core 模块的配置指南,请参阅以下主题:
如何在ASP.NET Core应用中使用Kestrel
安装 Microsoft.AspNetCore.Server.Kestrel Nuget包。Microsoft.AspNetCore.App Nuget包中已经包括 Microsoft.AspNetCore.Server.Kestrel 包(ASP.NET Core 2.1 或更高版本)。
在应用的Main方法中调用WebHostBuilder的UseKestrel 扩展方法,指定你需要的Kestrel选项,如以下示例所示:
public static int Main(string[] args) { Console.WriteLine("Running demo with Kestrel."); var config = new ConfigurationBuilder() .AddCommandLine(args) .Build(); var builder = new WebHostBuilder() .UseContentRoot(Directory.GetCurrentDirectory()) .UseConfiguration(config) .UseStartup<Startup>() .UseKestrel(options => { if (config["threadCount"] != null) { options.ThreadCount = int.Parse(config["threadCount"]); } }) .UseUrls("http://localhost:5000"); var host = builder.Build(); host.Run(); return 0; }
默认情况下,ASP.NET Core 项目模板中已经使用了 Kestrel。
在 Program.cs 中,ASP.NET Core 2.X的模板代码调用 CreateDefaultBuilder 方法,CreateDefaultBuilder中又会调用 UseKestrel。
public static void Main(string[] args) { CreateWebHostBuilder(args).Build().Run(); } public static IWebHostBuilder CreateWebHostBuilder(string[] args) => WebHost.CreateDefaultBuilder(args) .UseStartup<Startup>();
在 Program.cs 中,ASP.NET Core 3.X的模板代码调用 ConfigureWebHostDefaults 方法,ConfigureWebHostDefaults中又会调用 UseKestrel。
public static void Main(string[] args) { CreateHostBuilder(args).Build().Run(); } public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args) .ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup<Startup>(); });
若要在调用 CreateDefaultBuilder 后提供其他配置:
在ASP.NET Core 2.X中请使用UseKestrel:
public static IWebHostBuilder CreateWebHostBuilder(string[] args) => WebHost.CreateDefaultBuilder(args) .UseStartup<Startup>() .UseKestrel((context, options) => { // Set properties and call methods on options });
在ASP.NET Core 3.X中,除了使用UseKestrel,还可以使用ConfigureKestrel:
public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args) .ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup<Startup>() .UseKestrel() .ConfigureKestrel((context, options) => { // Set properties and call methods on options }); });
如果程序没有调用 CreateDefaultBuilder 来建立host:
在ASP.NET Core 2.X中,也可以调用UseKestrel:
public static void Main(string[] args) { var host = new WebHostBuilder() .UseContentRoot(Directory.GetCurrentDirectory()) .UseKestrel((context, options) => { // Set properties and call methods on options }) .UseIISIntegration() .UseStartup<Startup>() .Build(); host.Run(); }
在ASP.NET Core 3.X中,在调用 ConfigureKestrel 之前要先调用UseKestrel:
public static void Main(string[] args) { var host = new WebHostBuilder() .UseContentRoot(Directory.GetCurrentDirectory()) .UseKestrel() .UseIISIntegration() .UseStartup<Startup>() .ConfigureKestrel((context, options) => { // Set properties and call methods on options }) .Build(); host.Run(); }
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://contoso.com:80/ http://*:80/ https://contoso.com:443/ https://*:443/
主机名称,*,以及+,都不是特殊的。任何没有公认的IP 或是“localhost”的地址将绑定到所有的IPv4和IPv6的IP上。如果你需要为不同的ASP.NET Core应用在同一端口上绑定不同的主机名,请使用WebListener或者诸如IIS,Nginx或Apache这样的反向代理服务器。
* "Localhost" 名称和端口号或回送IP地址和端口号
http://localhost:5000/ 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前缀,如下所示:
ASP.NET Core 2.X
public static IWebHostBuilder CreateWebHostBuilder(string[] args) => WebHost.CreateDefaultBuilder(args) .UseStartup<Startup>() .UseKestrel((context, options) => { // Set properties and call methods on options options.ConfigureEndpointDefaults(listenOptions => { listenOptions.UseHttps("testCert.pfx", "testPassword"); }); }) .UseUrls("http://localhost:5000", "https://localhost:5001");
ASP.NET Core 3.X
public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args) .ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup<Startup>() .UseKestrel() .ConfigureKestrel((context, options) => { // Set properties and call methods on options options.ConfigureEndpointDefaults(listenOptions => { listenOptions.UseHttps("testCert.pfx", "testPassword"); }); }) .UseUrls("http://localhost:5000", "https://localhost:5001"); });
Note
HTTPS和HTTP不能在同一端口上被托管。
Feature Comparison for Kestrel vs IIS
Here is an IIS vs Kestrel comparison of some key features. This should help you better understand the limitations of Kestrel. You can overcome these limitations by pairing it up with IIS or NGINX.
IIS | Kestrel | |
Platform Support | Windows | Windows/Linux/Mac |
Static Files | Yes | Yes |
HTTP Access Logs | Yes | No |
Port Sharing / Multiple apps* | Yes | No |
SSL Certificates | Yes | Internal** |
Windows Authentication | Yes | No |
Management Console | Yes | No |
Process Activation (start it up) | Yes | No |
Application Initialization (warm it up) | Yes | No |
Configuration API | Yes | No |
Request Filtering & Limits | Yes | No |
IP & Domain Restrictions | Yes | No |
HTTP Redirect Rules | Yes | No |
WebSocket Protocol | Yes | Middleware |
Response Output Caching | Yes | No |
Compression | Optional | Optional |
FTP Server | Yes | No |
本教程在本地仅使用Kestrel,在将该应用部署到Azure之后,它将在Windows上使用IIS作为反向代理服务器。
参考文献:
- Kestrel source code
- Web server implementations in ASP.NET Core
- Kestrel web server implementation in ASP.NET Core
- ASP.NET Core Web Servers: Kestrel vs IIS Feature Comparison and Why You Need Both