.NET Core 3.0之深入源码理解Kestrel的集成与应用(一)
寫在前面
ASP.NET Core 的 Web 服務(wù)器默認(rèn)采用Kestrel,這是一個(gè)基于libuv(一個(gè)跨平臺(tái)的基于Node.js的異步I/O庫(kù))的跨平臺(tái)、輕量級(jí)的Web服務(wù)器。
在開始之前,先回顧一下.NET Core 3.0默認(rèn)的main()方法模板中,我們會(huì)調(diào)用Host.CreateDefaultBuilder方法,該方法的主要功能是配置應(yīng)用主機(jī)及設(shè)置主機(jī)的屬性,設(shè)置Kestrel?服務(wù)器配置為 Web 服務(wù)器,另外還包括日志功能、應(yīng)用配置加載等等,此處不做展開。
作為一個(gè)輕量級(jí)的Web Server,它并沒(méi)有IIS、Apache那些大而全的功能,但它依然可以單獨(dú)運(yùn)行,也可以搭配IIS、Apache等反向代理服務(wù)器結(jié)合使用。
本文將從源碼角度討論ASP.NET Core應(yīng)用在Kestrel的相關(guān)知識(shí)點(diǎn)。
Kestrel
Kestrel的存在意義
了解這個(gè)問(wèn)題,首先需要強(qiáng)調(diào)的是.NET Core應(yīng)用的目標(biāo)就是跨平臺(tái),既然要跨平臺(tái)那么就需要適用各個(gè)平臺(tái)上的Web服務(wù)器,各個(gè)服務(wù)器的啟動(dòng)、配置等等都是不盡相同的,如果每個(gè)服務(wù)器提供一套實(shí)現(xiàn)出來(lái),如果未來(lái)出現(xiàn)了一個(gè)新的Web Server,然后又要增加新的實(shí)現(xiàn),這會(huì)導(dǎo)致.NET Core應(yīng)用的適用性滯后,也會(huì)很消耗人力,無(wú)法很好的達(dá)到跨平臺(tái)的目標(biāo)。
我們可以把Kestrel視作一個(gè)中間件,一個(gè)適配的功能,它抽象了各個(gè)服務(wù)器的特性,使得各個(gè)應(yīng)用只需要調(diào)用同樣的接口,即可最大限度的在各個(gè)平臺(tái)上運(yùn)行。
運(yùn)行方式
.NET Core 3.0下,Kestrel的集成已經(jīng)相當(dāng)成熟了,也提供了相應(yīng)的自定義配置,以使得Kestrel的使用更加具有靈活性和可配性。它可以獨(dú)立運(yùn)行,也可以與反向代理服務(wù)器結(jié)合使用。
Kestrel本身是不支持多個(gè)應(yīng)用共享同一個(gè)端口的,但是我們可以通過(guò)反向代理服務(wù)器來(lái)實(shí)現(xiàn)統(tǒng)一對(duì)外的相同的端口的共享。
以下是其單獨(dú)運(yùn)行示意圖:
以下是其結(jié)合反向代理使用示意圖:
?
Microsoft.AspNetCore.Server.Kestrel.Core
該類庫(kù)是Kestrel的核心類庫(kù),里面包含了該功能的多個(gè)邏輯實(shí)現(xiàn),以下簡(jiǎn)稱改類庫(kù)為Kestrel.Core。
Kestrel適配邏輯
如前文所說(shuō),Kestrel起到了抽象服務(wù)器的功能,那么在適配其他服務(wù)器的過(guò)程中,必然涉及到的是,輸入、輸出、數(shù)據(jù)交互方式以及Trace功能。在Kestrel.Core中,該功能主要由AdaptedPipeline類來(lái)實(shí)現(xiàn),該類繼承自IDuplexPipe,并通過(guò)構(gòu)造函數(shù)獲取到了Pipe對(duì)象。IDuplexPipe和Pipe均位于System.IO.Pipelines命名空間下,詳細(xì)信息可以點(diǎn)擊查看。
AdaptedPipeline有兩個(gè)公共方法:
RunAsync():用于讀取(讀取后會(huì)有Flush操作)和寫入數(shù)據(jù),并分別裝載到Task中
CompleteAsync():完成讀取和寫入操作,并取消基礎(chǔ)流的讀取
另外還包括四個(gè)公共屬性,如下所示:
?
它定義了可從中讀取并寫入數(shù)據(jù)的雙工管道的對(duì)象。IDuplexPipe有兩個(gè)屬性,System.IO.Pipelines.PipeReader Input { get; }和System.IO.Pipelines.PipeReader Output { get; }。AdaptedPipeline還通過(guò)構(gòu)造函數(shù)獲取到了Pipe對(duì)象。
RawStream類繼承自Stream,并重寫了Stream的關(guān)鍵屬性及方法,主要目標(biāo)是提供適合于Kestrel讀寫數(shù)據(jù)方式的內(nèi)部封裝。
LoggingStream類也同樣繼承自Stream,和RawStream不同的是,里面增加操作過(guò)程的日志記錄,主要用于記錄在連接適配過(guò)程中的信息,不過(guò)需要啟用日志才能把日志信息記錄下來(lái),以下是其對(duì)外的使用方式:
Kestrel特性抽象
該模塊下的 Kestrel特性,比較重要的有連接超時(shí)設(shè)置(包括設(shè)置超時(shí)時(shí)間、重置超時(shí)時(shí)間以及取消超時(shí)限制。這個(gè)特性使得我們的連接變得更加可控,比如,在某些特殊場(chǎng)景下,特性條件下,我們需要取消超時(shí)限制或者動(dòng)態(tài)重置超時(shí)時(shí)間),TLS應(yīng)用程序協(xié)議功能,基于Http2.0的StreamId記錄功能,用于停止連接計(jì)數(shù)的功能。
以下是連接超時(shí)接口的源代碼:
Kestrel選項(xiàng)及限制功能
Kestrel的選項(xiàng)控制包括監(jiān)聽、Kestrel服務(wù)器、HTTPS連接適配。
1、監(jiān)聽選項(xiàng)功能在ListenOptions中實(shí)現(xiàn),該類繼承自IConnectionBuilder,ListenOptions的主要作用是描述Kestrel中已經(jīng)打開的套接字,包括Unix域套接字路徑、文件描述符、ipendpoint。ListenOptions內(nèi)部會(huì)維護(hù)一個(gè)只讀的List<Func<ConnectionDelegate, ConnectionDelegate>>()對(duì)象,并通過(guò)Use()方法加載新的Func<ConnectionDelegate, ConnectionDelegate>對(duì)象,然后通過(guò)Build方式返回最后加入的Func<ConnectionDelegate, ConnectionDelegate對(duì)象,源碼如下所示:
需要注意的是ListenOptions在該類庫(kù)內(nèi)部還有兩個(gè)子類,AnyIPListenOptions和LocalhostListenOptions,以用于特定場(chǎng)景的監(jiān)聽使用。
2、Kestrel服務(wù)器選項(xiàng)是在KestrelServerOptions中實(shí)現(xiàn)的,該類用于提供Kestrel特定功能的編程級(jí)別配置,該類內(nèi)部會(huì)維護(hù)ListenOptions的列表對(duì)象,該類將ListenOptions的功能進(jìn)一步展開,并加入了HTTPS、證書的默認(rèn)配置與應(yīng)用,這個(gè)類比較大,這里就不貼出源碼了,有興趣的同學(xué)可以自己去翻閱。
3、HTTPS連接適配選項(xiàng)在HttpsConnectionAdapterOptions實(shí)現(xiàn),這個(gè)類用于設(shè)置Kestrel如何處理HTTPS連接,這里引入了證書功能、SSL協(xié)議、HTTP協(xié)議、超時(shí)功能,同時(shí)還可以自定義HTTPS連接時(shí)的證書處理模式(AllowCertificate、RequireCertificate等),以下是HttpsConnectionAdapterOptions的構(gòu)造函數(shù):
可以看到,在默認(rèn)情況下,是無(wú)證書模式,其SSL協(xié)議包括Tls12 和Tls11以及指定允許進(jìn)行TLS/SSL握手的最大時(shí)間是十秒鐘。
4、Kestrel的限制功能在KestrelServerLimits實(shí)現(xiàn),主要包括:
保持活動(dòng)狀態(tài)超時(shí)
客戶端最大連接數(shù)(默認(rèn)情況下,最大連接數(shù)不受限制 (NULL))
請(qǐng)求正文最大大小(默認(rèn)的請(qǐng)求正文最大大小為 30,000,000 字節(jié),大約 28.6 MB)
請(qǐng)求正文最小數(shù)據(jù)速率(默認(rèn)的最小速率為 240 字節(jié)/秒,包含 5 秒的寬限期)
請(qǐng)求標(biāo)頭超時(shí)(默認(rèn)值為 30 秒)
每個(gè)連接的最大流(默認(rèn)值為 100)
標(biāo)題表大小(默認(rèn)值為 4096)
最大幀大小(默認(rèn)值為 2^14)
最大請(qǐng)求標(biāo)頭大小(默認(rèn)值為 8,192)
初始連接窗口大小(默認(rèn)值為 128 KB)
初始流窗口大小(默認(rèn)值為 96 KB)
代碼如下所示:
?
其部分源碼如下:
?
參考地址:https://docs.microsoft.com/zh-cn/aspnet/core/fundamentals/servers/kestrel?view=aspnetcore-3.0#maximum-streams-per-connection
總結(jié)
以上是生活随笔為你收集整理的.NET Core 3.0之深入源码理解Kestrel的集成与应用(一)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 我与微软的不解之缘 - 我的Inside
- 下一篇: asp.net ajax控件工具集 Au