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 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分鐘,可以用以下代碼進行設置:
1 | serverOptions.Limits.KeepAliveTimeout = TimeSpan.FromMinutes(2); |
? 2.?客戶端最大連接數:?MaxConcurrentConnections、 MaxConcurrentUpgradedConnections
??默認情況下,最大連接數不受限制;
??可以通過?MaxConcurrentConnections,設置整個應用設置并發打開的最大 TCP 連接數。
??對于已從 HTTP 或 HTTPS 升級到另一個協議(例如,Websocket 請求)的連接,有一個單獨的限制MaxConcurrentUpgradedConnections。 連接升級后,不會計入 MaxConcurrentConnections 限制。
? 可以用以下代碼進行設置:
1 2 | serverOptions.Limits.MaxConcurrentConnections = 100; serverOptions.Limits.MaxConcurrentUpgradedConnections = 100; |
??3.?請求正文最大大小: MaxRequestBodySize
??默認的請求正文最大大小為 30,000,000 字節,大約 28.6 MB
1 | 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 連接的并發請求流的數量。 拒絕過多的流。? ?
1 | serverOptions.Limits.Http2.MaxStreamsPerConnection = 100; |
7. 標題表大小
? ?HPACK 解碼器解壓縮 HTTP/2 連接的 HTTP 標頭。 Http2.HeaderTableSize 限制 HPACK 解碼器使用的標頭壓縮表的大小。 該值以八位字節提供,且必須大于零 (0)。 ? ?
1 | serverOptions.Limits.Http2.HeaderTableSize = 4096; |
8. 最大幀大小 Http2.MaxFrameSize
? ??Http2.MaxFrameSize?表示服務器接收或發送的 HTTP/2 連接幀有效負載的最大允許大小。?該值以八位字節提供,必須介于 2^14 (16,384) 和 2^24-1 (16,777,215) 之間。??
1 | serverOptions.Limits.Http2.MaxFrameSize = 16384; |
9. 最大請求頭大小 Http2.MaxRequestHeaderFieldSize
? Http2.MaxRequestHeaderFieldSize?表示請求標頭值的允許的最大大小(用八進制表示)。?此限制適用于名稱和值的壓縮和未壓縮表示形式。?該值必須大于零 (0)。?? ??
1 | 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。? ? ?
1 | serverOptions.AllowSynchronousIO =?true; |
以上是ASP.NET Core?Web服務器Kestrel的一些研究和梳理,分享給大家。
總結
以上是生活随笔為你收集整理的ASP.NET Core技术研究-全面认识Web服务器Kestrel的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 用了这么多年的泛型,你对它到底有多了解?
- 下一篇: Blazor WebAssembly 3