天天看点

ASP.NET Core技术研究-全面认识Web服务器Kestrel

ASP.NET Core技术研究-全面认识Web服务器Kestrel

因为IIS不支持跨平台的原因,我们在升级到ASP.NET Core后,会接触到一个新的Web服务器Kestrel。相信大家刚接触这个Kestrel时,会有各种各样的疑问。

今天我们全面认识一下ASP.NET Core的默认Web服务器Kestrel。

一、初识Kestrel

首先,Kestrel是一个跨平台的Web服务器,支持运行在Windows、macOS、Linux等操作系统中。Kestrel支持一下使用场景:

HTTPS

Opaque upgrade used to enable WebSockets(启用WebSocket情况下的不透明升级)

Unix sockets for high performance behind Nginx(Nginx高性能模式下的Unix套接字)

HTTP2(不支持macOS)

Kestrel支持运行在所有.NET 支持的平台和版本之上。

二、Kestrel主要应用场景

   Kestrel主要有两种使用模式:

   1. Kestrel直接作为Web服务器,直接接收并处理各类Http请求:

   2. 与各类反向代理服务器(例如Nginx、Apache、IIS)配合使用,反向代理服务器接收Http请求,将这些请求转发到Kestrel Web服务器

   使用反向代理服务器的好处有哪些呢?

   对外暴露有限的HTTP服务

   更加安全,反向代理服务器做了一层过滤、防护和转发

   通过反向代理服务器实现负载均衡和动态请求分发路由

   减少域名使用,降低WAF防火墙防护成本

   安全通信 (HTTPS) 配置,HTTPS转HTTP,仅反向代理服务器需要 X.509 证书,并且该服务器可使用普通 HTTP 协议与内部网络的应用服务器通信。

 三、Kestrel支持特性之-HTTP/2

Kestrel在以下操作系统和.NET Core版本下支持HTTP/2

  操作系统:

Windows Server 2016/Windows 10 或更高版本

具有 OpenSSL 1.0.2 或更高版本的 Linux(例如,Ubuntu 16.04 或更高版本)

macOS 的未来版本将支持 HTTP/2

macOS 的未来版本将支持 †HTTP/2。 ‡Kestrel 在 Windows Server 2012 R2 和 Windows 8.1 上对 HTTP/2 的支持有限。

目标框架:.NET Core 2.2 或更高版本

关于HTTP/2 可以参考一下超链接:

https://http2.github.io/ 关于HTTP/2和HTTP/1.1的全方位对比,可以参考这个超链接: https://cheapsslsecurity.com/p/http2-vs-http1/

 四、在ASP.NET Core中使用Kestrel

在ASP.NET Core的框架Microsoft.AspNetCore.App内置了package:Microsoft.AspNetCore.Server.Kestrel ,即原生对Kestrel的支持:

大家可以找到ASP.NET Core 3.1的本地目录:C:Program FilesdotnetpacksMicrosoft.AspNetCore.App.Ref3.1.0refnetcoreapp3.1 中找到Kestrel相关的dll:

当我们新建一个ASP.NET Core Project,在Program.cs类中有以下代码,

1

2

3

4

5

6

7

8

9

10

11

12

13

14

public class Program

{

        public static void Main(string[] args)

        {

            CreateHostBuilder(args).Build().Run();

        }

        public static IHostBuilder CreateHostBuilder(string[] args) =>

            Host.CreateDefaultBuilder(args)

                .ConfigureWebHostDefaults(webBuilder =>

                {

                    webBuilder.UseStartup();

                });

}  

我们通过查看ConfigureWebDefaults的实现源码可以发现,在其内部调用了UseKestrel()方法,即ASP.NET Core默认使用Kestrel Web服务器!

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

internal static void ConfigureWebDefaults(IWebHostBuilder builder)

       {

           builder.ConfigureAppConfiguration((ctx, cb) =>

           {

               if (ctx.HostingEnvironment.IsDevelopment())

               {

                   StaticWebAssetsLoader.UseStaticWebAssets(ctx.HostingEnvironment, ctx.Configuration);

               }

           });

           builder.UseKestrel((builderContext, options) =>

               options.Configure(builderContext.Configuration.GetSection("Kestrel"));

           })

           .ConfigureServices((hostingContext, services) =>

               // Fallback

               services.PostConfigure(options =>

                   if (options.AllowedHosts == null || options.AllowedHosts.Count == 0)

                   {

                       // "AllowedHosts": "localhost;127.0.0.1;[::1]"

                       var hosts = hostingContext.Configuration["AllowedHosts"]?.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries);

                       // Fall back to "*" to disable.

                       options.AllowedHosts = (hosts?.Length > 0 ? hosts : new[] { "*" });

                   }

               });

               // Change notification

               services.AddSingleton>(

                           new ConfigurationChangeTokenSource(hostingContext.Configuration));

               services.AddTransient();

               if (string.Equals("true", hostingContext.Configuration["ForwardedHeaders_Enabled"], StringComparison.OrdinalIgnoreCase))

                   services.Configure(options =>

                       options.ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;

                       // Only loopback proxies are allowed by default. Clear that restriction because forwarders are

                       // being enabled by explicit configuration.

                       options.KnownNetworks.Clear();

                       options.KnownProxies.Clear();

                   });

                   services.AddTransient();

               services.AddRouting();

           .UseIIS()

           .UseIISIntegration();

       }

以上详细的代码可以参考,上一篇博文:.NET Core技术研究-主机Host

五、Kestrel的配置选项

我们可以使用 webBuilder.ConfigureKestrel设置Kestrel的一些选项:

接下来,我们看一下Kestrel Web服务器提供了哪些选项设置:

  1. KeepAliveTimeout:保持活动会话超时时间

默认2分钟,可以用以下代码进行设置:

serverOptions.Limits.KeepAliveTimeout = TimeSpan.FromMinutes(2);

  2. 客户端最大连接数: MaxConcurrentConnections、 MaxConcurrentUpgradedConnections

默认情况下,最大连接数不受限制;

可以通过 MaxConcurrentConnections,设置整个应用设置并发打开的最大 TCP 连接数。

对于已从 HTTP 或 HTTPS 升级到另一个协议(例如,Websocket 请求)的连接,有一个单独的限制MaxConcurrentUpgradedConnections。 连接升级后,不会计入 MaxConcurrentConnections 限制。

可以用以下代码进行设置:

serverOptions.Limits.MaxConcurrentConnections = 100;

serverOptions.Limits.MaxConcurrentUpgradedConnections = 100;

3. 请求正文最大大小: MaxRequestBodySize

默认的请求正文最大大小为 30,000,000 字节,大约 28.6 MB

serverOptions.Limits.MaxRequestBodySize = 10 * 1024;

在 ASP.NET Core MVC 应用中替代限制的推荐方法是在操作方法上使用 RequestSizeLimitAttribute 属性:

[RequestSizeLimit(100000000)]

public IActionResult MyActionMethod()  

   4. 请求正文最小数据速率 MinRequestBodyDataRate MinResponseDataRate

Kestrel 每秒检查一次数据是否以指定的速率(字节/秒)传入。 如果速率低于最小值,则连接超时。

宽限期是 Kestrel 提供给客户端用于将其发送速率提升到最小值的时间量;在此期间不会检查速率。 宽限期可以尽可能地避免最初由于 TCP 慢启动而以较慢速率发送数据的连接中断。

默认的最小速率为 240 字节/秒,包含 5 秒的宽限期。

最小速率也适用于HttpResponse响应。 除了属性和接口名称中具有 RequestBody 或 Response 以外,用于设置请求限制和响应限制的代码相同。

serverOptions.Limits.MinRequestBodyDataRate = new MinDataRate(bytesPerSecond: 100, gracePeriod: TimeSpan.FromSeconds(10));

serverOptions.Limits.MinResponseDataRate = new MinDataRate(bytesPerSecond: 100, gracePeriod: TimeSpan.FromSeconds(10));

  5. 请求Header超时 RequestHeadersTimeout

获取或设置服务器接收请求标头所花费的最大时间量。 默认值为 30 秒。

serverOptions.Limits.RequestHeadersTimeout = TimeSpan.FromMinutes(1);

   6. 每个连接的最大的请求流的数量 MaxStreamsPerConnection

Http2.MaxStreamsPerConnection 限制每个 HTTP/2 连接的并发请求流的数量。 拒绝过多的流。

serverOptions.Limits.Http2.MaxStreamsPerConnection = 100;

 7. 标题表大小

HPACK 解码器解压缩 HTTP/2 连接的 HTTP 标头。 Http2.HeaderTableSize 限制 HPACK 解码器使用的标头压缩表的大小。 该值以八位字节提供,且必须大于零 (0)。

serverOptions.Limits.Http2.HeaderTableSize = 4096;

 8. 最大帧大小 Http2.MaxFrameSize

Http2.MaxFrameSize 表示服务器接收或发送的 HTTP/2 连接帧有效负载的最大允许大小。 该值以八位字节提供,必须介于 2^14 (16,384) 和 2^24-1 (16,777,215) 之间。  

serverOptions.Limits.Http2.MaxFrameSize = 16384;

  1. 最大请求头大小 Http2.MaxRequestHeaderFieldSize

  Http2.MaxRequestHeaderFieldSize 表示请求标头值的允许的最大大小(用八进制表示)。 此限制适用于名称和值的压缩和未压缩表示形式。 该值必须大于零 (0)。     

serverOptions.Limits.Http2.MaxRequestHeaderFieldSize = 8192;

  1. 初始连接窗口大小  Http2.InitialConnectionWindowSize 

Http2.InitialConnectionWindowSize 表示服务器一次性缓存的最大请求主体数据大小(每次连接时在所有请求(流)中汇总,以字节为单位)。 请求也受 Http2.InitialStreamWindowSize 限制。 该值必须大于或等于 65,535,并小于 2^31 (2,147,483,648)。   

    默认值为 128 KB (131,072)

serverOptions.Limits.Http2.InitialConnectionWindowSize = 131072;

 11. 初始流窗口大小 Http2.InitialStreamWindowSize

Http2.InitialStreamWindowSize 表示服务器针对每个请求(流)的一次性缓存的最大请求主体数据大小(以字节为单位)。 请求也受 Http2.InitialConnectionWindowSize 限制。 该值必须大于或等于 65,535,并小于 2^31 (2,147,483,648)。

    默认值为 96 KB (98,304)    

serverOptions.Limits.Http2.InitialStreamWindowSize = 98304;

 12. 同步IO  AllowSynchronousIO 

AllowSynchronousIO 控制是否允许对请求和响应使用同步 IO。 默认值为 false。这个设置需要注意一下:

大量的阻止同步 IO 操作可能会导致线程池资源不足,进而导致应用无响应。 仅在使用不支持异步 IO 的库时,才启用 AllowSynchronousIO。

serverOptions.AllowSynchronousIO = true;

以上是ASP.NET Core Web服务器Kestrel的一些研究和梳理,分享给大家。

原文地址

https://www.cnblogs.com/tianqing/p/12764404.html

继续阅读