首頁>技術>

因為IIS不支援跨平臺的原因,我們在升級到ASP.NET Core後,會接觸到一個新的Web伺服器Kestrel。相信大家剛接觸這個Kestrel時,會有各種各樣的疑問。

今天我們全面認識一下ASP.NET Core的預設Web伺服器Kestrel。

一、初識Kestrel

首先,Kestrel是一個跨平臺的Web伺服器,支援執行在Windows、macOS、Linux等作業系統中。Kestrel支援一下使用場景:

HTTPSOpaque 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 Files\\dotnet\\packs\\Microsoft.AspNetCore.App.Ref\\3.1.0\\ref\\netcoreapp3.1 中找到Kestrel相關的dll:

當我們新建一個ASP.NET Core Project,在Program.cs類中有以下程式碼,

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<Startup>();                });}

我們通過檢視ConfigureWebDefaults的實現原始碼可以發現,在其內部呼叫了UseKestrel()方法,即ASP.NET Core預設使用Kestrel Web伺服器!

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<HostFilteringOptions>(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<IOptionsChangeTokenSource<HostFilteringOptions>>(                           new ConfigurationChangeTokenSource<HostFilteringOptions>(hostingContext.Configuration));                  services.AddTransient<IStartupFilter, HostFilteringStartupFilter>();                  if (string.Equals("true", hostingContext.Configuration["ForwardedHeaders_Enabled"], StringComparison.OrdinalIgnoreCase))               {                   services.Configure<ForwardedHeadersOptions>(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<IStartupFilter, ForwardedHeadersStartupFilter>();               }                  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;

9. 最大請求頭大小 Http2.MaxRequestHeaderFieldSize

Http2.MaxRequestHeaderFieldSize 表示請求標頭值的允許的最大大小(用八進位制表示)。 此限制適用於名稱和值的壓縮和未壓縮表示形式。 該值必須大於零 (0)。

serverOptions.Limits.Http2.MaxRequestHeaderFieldSize = 8192;

10. 初始連線視窗大小 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的一些研究和梳理,分享給大家。

最新評論
  • BSA-TRITC(10mg/ml) TRITC-BSA 牛血清白蛋白改性標記羅丹明
  • 效能是Flask的3倍!比PHP7還快!這個Python框架你值得擁有!