從底層瞭解ASP.NET體繫結構

來源:互聯網
上載者:User
(翻譯)從底層瞭解ASP.NET體繫結構

前言

關於ASP.NET的底層的工作機制,最近園子裡討論的甚是火熱。相信很多人都看過Rick Strahl先生的一篇經典之作:A low-level Look at the ASP.NET Architecture,經Rick Strahl先生同意,我把他的這篇文章翻譯成中文,希望能夠給想深入瞭解ASP.NET工作機制的朋友一點協助。 

 

 

 

 

  摘要:ASP.NET是一個用於構建Web程式的強大平台,提供了巨大的彈性和能力以至於它可以構建任意的Web程式。許多人僅僅對處於ASP.NET高層次的架構如:WebForms和WebServices比較熟悉,因此,在這篇文章裡,我將會闡述有關ASP.NET比較底層的知識,並且將會解釋,如何將請求從Web Server移交給ASP.NET運行時,然後通過ASP.NET HTTP管道處理這些請求。

對於我來說,瞭解一個平台的內部工作機制總是會讓我感到一些滿足和安慰,如同洞察,可以協助我寫出更好的程式。知道了工具有什麼用途,以及它們如何組裝成複雜架構的一部分,這些將會使你很容易的找到問題的解決方案,以及在你修改和調試錯誤時,都顯得非常重要。這篇文章的目的就是從底層瞭解ASP.NET以及協助你理解請求如何流入ASP.NET處理管道裡。同時,你將會瞭解ASP.NET引擎的核心,以及一個Web請求如何在這裡結束。這裡講到的許多知識都是你日常工作中沒必要知道的,但是,如果你理解了ASP.NET如何把請求路由到應用程式的代碼裡(通常比較高層次的),這將對你非常有用。

 

註:整個ASP.NET引擎完全構建在Managed 程式碼裡,其所有的擴充性都是通過Managed 程式碼去構建。

 

使用ASP.NET的大多數都比較熟悉WebForms和WebServices。這些高層次的實現,使得構建Web程式變得非常容易。ASP.NET被設計為驅動引擎,它把底層的介面提供給Web Server,為高層次Web應用程式的前端和末端提供了路由服務。WebForms和WebServices是建立在ASP.NET架構之上,有關HTTP處理的兩種最常用的方式。

 

其實,在較低的層次上,ASP.NET也提供了足夠多的靈活性。HTTP運行時和請求管道提供了同樣的能力,可以構建類似於WebForms和WebServices的實現,當然,這些已經使用.NETManaged 程式碼實現了。如果你需要構建一個自訂HTTP處理平台,而這個平台要比WebForms所處的層次低一點,那麼你就會用到所有這些類似的功能。

 

構建大多的Web介面,使用WebForms無疑是最容易的方法,但是,如果你想自訂一個內容處理器,或者需要對流入和流出的內容做特殊的處理,或者需要為一個應用程式定製一個應用伺服器介面,那麼使用這些低層次的處理或者模組將會得到更好的效能,以及可以在真正的請求處理中獲得更多的控制權。儘管那些高層次的實現,如:WebForms和WebServices已提供了類似的功能,但由於它們針對請求添加了太多的控制(導致效能下降)。所以你完全可以另闢佳境,在較低層次上處理這些請求。

 

 

ASP.NET是什麼。

 

讓我們從最簡單的定義開始,ASP.NET是什麼。我通常喜歡用如下語句來描述ASP.NET。

 

ASP.NET是完全使用Managed 程式碼處理Web請求的一個成熟引擎平台。它不僅僅只是WebForms和WebServices。

 

ASP.NET是一個請求處理引擎。它擷取用戶端請求,然後通過它內建的管道,把請求傳到一個終點,在這個終點,開發人員可以添加處理這個請求的邏輯代碼。實際上這個引擎和HTTP或者Web Server是完全分開的。事實上,HTTP運行時是一個組件,你可以把它宿主在IIS之外的應用程式上。甚至完全可以和其它的服務組合在一起。例如,你可以把HTTP運行時宿主在Windows傳統型應用程式裡(詳細的內容請查看:http://www.west-wind.com/presentations/aspnetruntime/aspnetruntime.aspx)。

 

通過使用內建的管道路由請求,HTTP運行時提供了一套複雜的,但卻很優雅的機制。在處理請求的每一個層面都牽涉到許多個物件,但大多數對象都可以通過派生或者事件介面來擴充。所以,此架構具有非常高的可擴充性。通過這一套機制,可以進入較低層次的介面如:緩衝,身分識別驗證,授權等是有可能的。你可以在處理請求之前或之後過濾內容,或者僅僅把匹配指定簽名的用戶端請求直接路由到你的代碼裡或轉向其它的URL。針對同一件事情,可以通過不同的處理方法完成,而且實現代碼都非常的直觀。除此之外,在容易開發和效能之間,HTTP運行時還提供了最佳的靈活性。

 

整個ASP.NET引擎完全構建在Managed 程式碼裡,所有的擴充性功能都是通過Managed 程式碼的擴充提供。對於功能強大的.NET架構而言,使用自己的東西,構建一個成熟的、高效能的引擎體繫結構已經成為一個遺囑。儘管如此,但重要的是,ASP.NET給人印象最深的是高瞻遠矚的設計,這使得在其之上的工作變得非常容易,並且提供了幾乎可以鉤住請求處理當中任意部分的能力。

 

使用ASP.NET可以完成一些任務,之前這些任務是使用IIS上的ISAPI擴充和過濾來完成的。儘管還有一些限制,但與ASP相比,已經有了很大的進步。ISAPI是底層Win32樣式的API,僅它的介面就有1兆,這對於大型的程式開發是非常困難的。由於ISAPI是底層的介面,因此它的速度也是非常的快。但對於企業級的程式開發是相當的難於管理的。所以,在一定的時間內,ISAPI主要充當其它應用程式或平台的橋介面。但是無論如何,ISAPI沒有被廢棄。事實上,微軟平台上的ASP.NET和IIS的介面是通過宿主在.NET裡的ISAPI擴充來通訊的,然後直達ASP.NET運行時。ISAPI提供了與Web Server通訊的核心介面,然後ASP.NET使用Unmanaged 程式碼擷取請求以及對用戶端請求發出響應。ISAPI提供的內容經由公用對象類似於HttpRequest和HttpResponse,通過一個設計優良的、可訪問的介面,以託管對象的方式暴露非管理的資料。


從瀏覽器到ASP.NET

 

讓我們從一個典型的ASP.NET Web請求的生命週期的起點開始。使用者通過在瀏覽器中鍵入一個URL,點擊一個超連結,提交一個HTML表單(一個post請求),或者一個用戶端程式調用基於ASP.NET的WebService(通過ASP.NET提供服務)。在伺服器端,IIS5或者IIS6將會收到這個請求。ASP.NET的底層通過ISAPI擴充與IIS通訊,然後,通過ASP.NET,這個請求通常被路由到一個帶有.aspx副檔名的頁面。但是,這個處理過程如何工作,則完全依賴於HTTP處理器(handler)的執行。這個處理器將被安裝用於處理指定的擴充。在IIS中,.aspx經由“應用程式擴充”被映射到ASP.NET ISAPI的dll檔案:aspnet_isapi.dll。每一個觸發ASP.NET的請求,都必須經由一個已經註冊的,並且指向aspnet_isapi.dll的副檔名來標識。

 

註:ISAPI是自訂Web請求處理中第一個並且具有最高效能的IIS進入點。

 

依靠副檔名,ASP.NET把一個請求路由到一個恰當的處理器,該處理器則負責處理這個請求。舉個例子,WebServices的副檔名.asmx不會把一個請求路由到磁碟上的某一個頁面,而是會路由到在定義中附加了指定特性(WebMethodAttribute)的類,此特性會把它標識成一個Web Services的實現。許多其它的處理器將隨著ASP.NET一起被安裝。當然也可以定義你自己的處理器。在IIS裡所有的HttpHandler被映射並指向ASP.NET ISAPI擴充,並且這些HttpHandler也都在web.config裡配置,用於把請求路由到指定的HTTP處理器裡執行。每一個處理器都是一個.NET類,用於處理指定的擴充。而這些處理器可以處理簡單到只有幾行代碼的Hello World,也可以處理複雜到類似ASP.NET的頁面以及執行WebService。就目前而言,僅僅需要理解擴充就是一種基本的映射機制,ASP.NET用它可以從ISAPI裡擷取一個請求,然後把請求路由到指定處理該請求的處理器中。

 

ISAPI串連

 

ISAPI是底層非託管的Win32 API。它定義的介面非常的單一併且效能最優。用這些介面處理原始指標(raw pointer),而函數指標列表(function pointer tables)則用於回調。ISAPI提供了最低層的、高效能的介面,開發人員和工具廠商可以使用這些介面深入到IIS裡。由於ISAPI是非常低層的,所以不太適合使用它構建應用級的程式。ISAPI趨向於被當作橋介面使用,用於給高層次的工具提供應用服務類型的功能。例如,ASP和ASP.NET都是被當作冷聚變(cold fusion)構建於ISAPI之上。大多Perl、PHP和JSP的執行如同許多第三方解決方案一樣,可以在IIS運行。ISAPI是個非常好的工具,它給高層次的應用程式提供了高效能垂直提供者。這使得那些高層次的應用程式需要的資訊可以從ISAPI提供的資訊中提煉。在ASP和ASP.NET裡,引擎可以提煉ISAPI介面提供的表單裡的對象如:Request和Response,這些對象可以從ISAPI請求的資訊中讀取它們各自的內容。

 

作為約定,ISAPI支援ISAPI擴充(extensions)和ISAPI過濾(filters)。擴充是請求處理介面,提供了跟Web Server輸入和輸出相關的邏輯處理。從本質上來說,它是一個事務介面。ASP和ASP.NET都被看作ISAPI擴充的實現。ISAPI是鉤子介面,它允許你查看進入IIS的每一個請求並且可以修改請求的內容(包括輸入和輸出)或者改變模組(如:身分識別驗證等)的行為。順便提一下,ASP.NET通過兩個方面的內容:HTTP處理器(對應ISAPI擴充)和HTTP 模組(對應ISAPI過濾)映射到ISAPI。這些相關的內容我將會在後面詳細描述。

 

ISAPI是代碼的初始點,標識ASP.NET一個請求的開始。ASP.NET映射了不同的擴充到它的ISAPI擴充,ISAPI擴充位於.NET Framework目錄:

 

<.NET FrameworkDir>/aspnet_isapi.dll

 

你可以在IIS服務管理員裡看到這些映射,如圖1所示。開啟Web網站的根目錄的屬性,選擇主目錄選項卡,然後查看 配置|應用程式對應。


圖1:IIS把不同的副檔名如.aspx映射到ASP.NET的ISAPI擴充。通過這種機制,在Web Server裡,請求就可以被路由到ASP.NET的處理管道裡。

 

儘管.NET需要很多副檔名,但不必手工設定它們,你可以使用aspnet_regiis.exe工具 + 生產力確保所有的指令碼映射都被註冊。


cd <.NetFrameworkDirectory> aspnet_regiis – i


這將會把ASP.NET運行時的個別版本,通過指令碼映射註冊到整個Web網站,並且安裝用戶端指令碼庫,這些指令碼庫將會被瀏覽器上的控制項所使用。注意,它是註冊了安裝在上面目錄裡的CLR的那個版本。aspnet_regiis有一個可選項,可以使你單獨配置一個虛擬目錄。每一個.NET架構的版本,都擁有各自的aspnet_regiis,對於不同版本的.NET架構,你需要運行適當版本的aspnet_regiis,註冊到整個網站或者虛擬目錄。從ASP.NET2.0開始,在IIS控制台裡,有一個IIS  ASP.NET配置頁面,在這個頁面你可以挑選.NET的版本。

 

IIS5和IIS6的不同之處

 

當一個請求進來的時候,IIS會檢查指令碼映射,然後把請求路由到aspnet_isapi.dll。接下來這個DLL檔案的操作是什麼呢。在IIS5和IIS6裡,這個請求又是如何到達ASP.NET運行時的呢。它們兩者的處理方式有沒有重大變化呢。圖2展示了一個大致的流程。


圖2:站在比較高的角度,觀看請求從IIS到ASP.NET運行時的流程,然後直達請求處理管道。IIS5和IIS6與ASP.NET的介面採用了不同的方式,但從請求到達ASP.NET管道後的整個過程是完全一樣的。

 

IIS5直接把aspnet_isapi.dll寄宿在inetinfo.exe進程裡,或者它們中的一個將會與背景工作處理序隔離,如果你擁有隔離許可權,那麼可以把Web網站和虛擬目錄隔離的層級設定為中等或者進階。當第一個ASP.NET請求進來的時候,DLL將會在另一個EXE-aspnet_wp.exe裡分配一個新的進程,然後把相關資訊路由到這個新分配的進程裡。接著這個新的進程會依次載入和寄宿.NET運行時。每一個進入到ISAPI DLL的請求,都將通過調用具名管道路由給這個工作者進程。

 

註:IIS6與之前的Web Server不同,已經對ASP.NET進行了最佳化處理。IIS6中使用了應用程式集區。

 

值得注意的是,IIS6改變了這個處理模型,IIS不再直接寄宿像ISAPI擴充的任何外部可執行代碼。代替的是,IIS總會保持一個單獨的背景工作處理序:應用程式集區。所有的處理都發生在這個進程裡,包括ISAPI dll的執行。對於IIS6而言,應用程式集區是一個重大的改進,因為它們允許以更小的粒度控制一個指定進程的執行。你可以為每一個虛擬目錄或者整個Web網站配置應用程式集區,這可以使你很容易的把每一個應用程式隔離到各自的進程裡,這樣就可以把它與運行在同一台機器上其他程式完全隔離。從Web處理的角度看,如果一個進程死掉,至少它不會影響到其它的進程。

 

另外,應用程式集區是高度可配置的。通過設定應用程式集區的執行許可,可以配置它們的執行安全環境。並且可以為指定的應用程式按照相同的粒度定製這些配置。對於ASP.NET而言,IIS6最大的改進是使用應用程式集區代替了machine.config裡的ProcessModel實體的大部分功能。在IIS5裡,這個實體是很難管理的,因為它的設定是全域的,而且不能夠在指定Web程式的web.config裡覆蓋這些設定。當IIS6啟動並執行時候,ProcessModel裡的大部分配置將被忽略,取而代之的是讀取應用程式集區的配置。注意我這裡說的是大部分,另外的一些配置,像線程池的大小和IO線程數目等仍然需要通過這個節點配置,這是因為,在伺服器的應用程式集區裡沒有提供類似功能的配置。

 

由於應用程式集區是在外部執行的,所以這些執行可以很容易的被監控和管理。IIS6還提供了許多效能計數器,可以對重啟和逾時選項進行跟蹤。在許多情況下,這可以輔助應用程式糾正問題。最後,IIS6的應用程式集區的實現不依賴COM+,正如IIS5隔離進程一樣,這提高了程式的效能和穩定性,特別是那些需要在內部使用COM對象的程式。

 

IIS6應用程式集區也包含了ASP.NET固有的東西,ASP.NET可以和新的底層API通訊,這些API允許直接存取HTTP緩衝儲存空間的API,而HTTP緩衝儲存空間的API可以直接進入Web Server的緩衝儲存空間,卸載ASP.NET層級的緩衝。

 

在IIS6裡,ISAPI擴充運行在應用程式集區的背景工作處理序裡。.而NET運行時也運行在這個進程裡,所以ISAPI擴充和.NET運行時的通訊是發生在進程內的。這就使得比必須使用具名管道介面的IIS5具有更高的效能。儘管IIS的宿主模型不同,但是真正進入Managed 程式碼的介面是類似的,僅僅在擷取被路由的請求時有一些變動。

 

進入.NET運行時

 

進入.NET運行時的真正登入點發生在一些沒有正式文檔的類和介面之間。在微軟外面的世界,這些介面鮮為人知。微軟的民間也不太熱衷於討論這些細節,可能是因為他們認為這些,對於使用ASP.NET構建程式的開發人員沒有太多的影響。

 

背景工作處理序aspnet_wp.exe(IIS5)和w3wp.exe(IIS6)宿主在.NET運行時裡。ISAPI DLL通過底層的COM調用一小撮非託管類型的介面,其實,最終調用的是ISAPIRuntime衍生類別的執行個體。進入運行時的第一個登入點是未歸檔ISAPIRuntime類,它通過COM把介面IISAPIRuntime暴露給調用者。這些COM

介面是底層的IUnknown,基於這些介面,就意味著從ISAPI擴充到ASP.NET之間的調用屬於內部調用。圖3是使用有名的反射工具Refector(http://www.aisto.com/roeder/dotnet/)看到的IISAPIRuntime介面的簽名。Refector是一個可以查看和反編譯器集的工具,使用它可以很容易的查看中繼資料、反編譯代碼,就像圖3中看到的那樣。使用它一步一步地探究處理的過程,這是個非常不錯的方法。



圖3:如果你想深入瞭解這個底層的介面,你可以開啟Refector工具,然後指向System.Web.Hosting命名空間。進入ASP.NET的登入點以一個託管的COM介面出現,該介面將在ISAPI dll裡被調用。該登入點接收一個指向ISAPI ECB非託管類型的指標。ECB擁有訪問整個ISAPI介面的許可權,它可以擷取請求的資料以及把返回的資料發回IIS。

 

IISAPIRuntime介面擔當著來自於ISAPI擴充(在IIS6裡是直接通訊的,在IIS5裡間接的通過具名管道通訊的)的Unmanaged 程式碼和Managed 程式碼之間的橋樑。如果你留意一下這個類,你會發現ProcessRequest方法的簽名像下面的樣子:

 

[return: MarshalAs(UnmanagedType.I4)]

int ProcessRequest([In] IntPtr ecb, [In, MarshalAs(UnmanagedType.I4)] int useProcessModel);

 

ecb參數是ISAPI擴充控制塊(extension control block),它被作為非託管資源傳給ProcessRequest方法。此方法將擷取ECB,然後把它作為基本的輸入和輸出介面,用於Request和Response對象。ISAPI ECB包含著所有底層的請求資訊,這其中包括伺服器變數,用於表單變數(form variables)的輸入資料流,以及用於寫資料並把資料發送到用戶端的輸出資料流中。一個單獨的ECB引用基本上提供了一個ISAPI請求可以訪問的所有功能

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.