ASP.NET Core的Kestrel服务器(转载)

摘要:
ASP.NETCore模板项目使用Kestrel作为默认的web服务器。一个反向代理服务器接收来自网络的HTTP请求并且在经过一些初步处理后将请求传递到Kestrel服务器。因为Kestrel相对较新,对抵御安全攻击至今还没有一个完整的功能补充。下图说明了IIS、ASP.NETCore模块和进程内托管的应用之间的关系:请求从Web到达内核模式HTTP.sys驱动程序。IISHTTP服务器处理请求之后,请求会被推送到ASP.NETCore中间件管道中。该模块在第一个请求到达时启动ASP.NETCore应用的进程,并在应用关闭或崩溃时重新启动该应用。

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本身。

ASP.NET Core的Kestrel服务器(转载)第1张

如果你将你的应用部署在公共网络上,我们建议你使用IIS,Nginx或者Apache作为反向代理服务器。一个反向代理服务器接收来自网络的HTTP请求并且在经过一些初步处理后将请求传递到Kestrel服务器。

ASP.NET Core的Kestrel服务器(转载)第2张

出于安全性的理由,反向代理常常被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 模块和进程内托管的应用之间的关系:

ASP.NET Core的Kestrel服务器(转载)第3张

请求从 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 模块和进程外托管的应用之间的关系:

ASP.NET Core的Kestrel服务器(转载)第4张

请求从 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方法中调用WebHostBuilderUseKestrel扩展方法,指定你需要的Kestrel选项,如以下示例所示:

public static int Main(string[] args)
{
    Console.WriteLine("Running demo with Kestrel.");

    var config = newConfigurationBuilder()
        .AddCommandLine(args)
        .Build();

    var builder = newWebHostBuilder()
        .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 = newWebHostBuilder()
        .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 = newWebHostBuilder()
        .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 voidConfigure(IApplicationBuilder app, ILoggerFactory loggerFactory)
{
    loggerFactory.AddConsole();

    var serverAddressesFeature = app.ServerFeatures.Get<IServerAddressesFeature>();

    app.UseStaticFiles();

    app.Run(async (context) =>{
        context.Response.ContentType = "text/html";
        awaitcontext.Response
            .WriteAsync("<p>Hosted by Kestrel</p>");

        if (serverAddressesFeature != null)
        {
            awaitcontext.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.

IISKestrel
Platform SupportWindowsWindows/Linux/Mac
Static FilesYesYes
HTTP Access LogsYesNo
Port Sharing / Multiple apps*YesNo
SSL CertificatesYesInternal**
Windows AuthenticationYesNo
Management ConsoleYesNo
Process Activation (start it up)YesNo
Application Initialization (warm it up)YesNo
Configuration APIYesNo
Request Filtering & LimitsYesNo
IP & Domain RestrictionsYesNo
HTTP Redirect RulesYesNo
WebSocket ProtocolYesMiddleware
Response Output CachingYesNo
CompressionOptionalOptional
FTP ServerYesNo

本教程在本地仅使用Kestrel,在将该应用部署到Azure之后,它将在Windows上使用IIS作为反向代理服务器。

参考文献:

原文链接

免责声明:文章转载自《ASP.NET Core的Kestrel服务器(转载)》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇03-HTML常用标签Promise.resolve解析下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

curl检测https证书有效期命令

curl检测https证书有效期命令 curl -vvI https://域名 例如: [root@st-01 cert]# curl -vvI https://www.baidu.com * About to connect() to www.baidu.com port 443 (#0) * Trying 110.242.68.4... * Con...

使用 C++ 处理 JSON 数据交换格式 .

使用C++ 处理JSON 数据交换格式 一、摘要 JSON 的全称为:JavaScript Object Notation,顾名思义,JSON 是用于标记Javascript 对象的,JSON 官方的解释为:JSON 是一种轻量级的数据传输格式。 本文并不详细介绍JSON 本身的细节,旨在讨论如何使用C++ 语言来处理JSON。关于JSON 更具体的信息,...

替换SQL Server字段中的换行符,回车符

replace(string_expression , string_pattern , string_replacement) 第一个参数:要查找的字段。 第二个参数:要查找的字符。 第三个参数:要替换成的字符。 char(9) 水平制表符 char(10)换行键 char(13)回车键 SELECT REPLACE(detail, CHAR(13) +...

delphi 多线程 数据库

// 线程类unit Unit2; interface uses Classes; type TMyThread = class(TThread) private FUserName: string; FPassWord: string; FFlag: Boolean; procedure GetUserName(const Value: string);...

JAVA获取文件本身所在的磁盘位置

我们在做java开发(纯java程序,或者java web开发)时,经常会遇到需要读取配置文件的需求,如果我们将文件所在位置的信息直接写到程序中,例如:E:\workspace\JavaGUI\bin\com\util这个目录,这样虽然可行,但是,却产生了很大的局限性,因为读取的文件必须要要满足在E:\workspace\JavaGUI\bin\com\u...

IDEA使用switch传入String编译不通过

今天在使用IDEA的时候,用到switch分支语句,传入String参数的时候一直报错,下面是源码报错截图: 看错误提示并没有提到switch支持String类型,不过ava1.7之后就支持String类型才对呀,于是想到了会不会是JDK问题,但是JDK用的是1.8呀!网上搜索才发现,会不会是编译环境版本过低的原因呢?于是查看对IDEA的ProjectS...