[翻譯] ASP.NET內幕 – ISAPI和應用程式定義域之間的橋樑

來源:互聯網
上載者:User
原文地址:ASP.NET Internals - The bridge between ISAPI and Application Domains。

2007.06.13
Simone Busoli

ASP.NET內部工作原理有時候看起來像發生在幕後的黑暗魔法,為開發人員提供了一個較高層次的抽象,使得他們只用關注應用程式的商務邏輯,而不需要處理HTTP協議底層機制。ASP.NET基於.NET架構開發,應用於.NET架構,因此絕大部分是Managed 程式碼。然而web請求的進入點是使用本地代碼(native code)編寫的web伺服器,因此需要一個通訊機制。這篇文章中我將描述託管和非託管世界的橋樑,它們怎樣協作設定ASP.NET處理請求時所需的處理環境。

參考第一部分:ASP.NET內幕 - IIS處理模型

介紹

在前一篇,也是這一系列的第一篇中,我介紹了web伺服器接收到web請求之後進行的第一步處理,以及如果被確定為ASP.NET資源請求時如何路由請求。你已經明白不同的IIS版本在處理ASP.NET相關請求時的差異,最終請求被分發到一個叫做aspnet_isapi.dll的非託管Win32組件,這個組件的作用就是web伺服器和託管ASP.NET架構之間的橋樑。

這篇文章中我將繼續討論上一篇中的遺留問題,開始研究處理環境的託管部分,在前一篇文章中它被稱作ASP.NET運行時環境,作為一個黑盒子提到過。

注意:ASP.NET運行時環境有時也叫做ASP.NET管道、Http運行時管道,或者是這些單詞的混合。

從aspnet_isapi.dll擴充到託管世界

前一篇文章中我解釋了IIS 5和IIS 6怎樣管理ASP.NET請求,忽略它們怎樣處理背景工作處理序的建立、管理和回收,最後所有與請求相關的訊息歸結到了aspnet_isapi.dll擴充上。

這是非託管和託管世界的橋樑,也是所有ASP.NET架構中最缺乏文檔的部分。

注意:在寫這篇文章的時候,IIS 7以一個上線許可與Longhorn Server Beta 3一起發布了。IIS 7中許多事情會改變,儘管這些前期文章只是關注之前的IIS版本,以後的文章將會致力於IIS 7中引入的改進。

因為在這個主題的很多方面缺乏可用的文檔,我將進行的解釋可能不完全正確,特別是涉及到非託管結構的部分。然而我關於未文檔化部分主題的考量,是基於一些對理解架構內部工作原理很有協助的工具進行的:

  • Lutz Roeder's .NET
    Reflector, 靜態分析、反編譯.NET託管類代碼。

  • Microsoft CLR Profiler, 通過查看方法調用、記憶體配置、類結構以及它提供的很多其他特性,分析架構的動態行為。
  • JetBrains dotTrace
    Profiler, 用於.NET應用程式的商業化分析工具,也可以擷取一個有時間限制的免費版本。
  • Red Gate
    ANTS Profiler, 另一個用於.NET應用程式的商業化分析工具,可以擷取一個有時間限制的免費版本。

回到非託管和託管世界的橋樑上來,不管是IIS 6處理模式的情況下通過ISAPI擴充,還是IIS 5處理模式的情況下通過背景工作處理序,在CLR載入之後,黑暗魔法出現了。ASP.NET ISAPI組件通過位於System.Web.Hosting命名空間中的兩個託管類,調用一大把的非託管COM介面,通過COM介面方式暴露這些方法的類是AppManagerAppDomainFactory和ISAPIRuntime。

注意:通用語言執行平台CLR掌管每一個.NET應用程式的執行環境,它為運行託管應用程式提供環境和服務。CLR必須運行在Win32進程中,ASP.NET是.NET架構為CLR提供的一個宿主之一,確切地說在ASP.NET中,ASP.NET背景工作處理序(IIS 5中為aspnet_wp.exe,IIS 6中為w3wp.exe)就是運行CLR的進程。

在研究這些類中發生的互動行為的技術細節之前,我們先大致看一下處理請求時究竟發生了什麼。我前面已經介紹過這兩個類,因為處理請求的進入點可以大致的分為兩個方面。

    1. 如果AppDomain還不存在則建立APPDomain,將AppDomain指派給與請求對應的應用程式,這通過AppManagerAppDomain類實現。
    2. 提交和處理請求,由ISAPIRuntime類實現。

這兩個方面都很重要,第一個包括了不需要開發人員參與的一些互動動作,主要涉及應用程式的運行環境,而第二個則是結構上最可配置的部分,我將在這個系列的後續文章中完整地探討。

從另一個角度來看,第一步包含的操作在應用程式生存期裡只執行一次,就是說在啟動的時候,而第二步包含的互動在每一次定位請求的目標應用程式時都會出現。

建立AppDomain

在前面文章中瞭解到,一個ASP.NET應用程式被封裝成一個叫做應用程式定義域的實體,簡寫AppDomain,由ASP.NET架構中的一個類AppDomain表示。當特定應用程式的請求到達時,如果不存在則必須建立AppDomain對象,這通常發生在屬於特定應用程式的請求第一次到達時,或者由於某種原因相應的AppDomain被關閉掉了,幾個可能導致這個問題的原因我在後面會談到。注意一個ASP.NET應用程式只會有一個AppDomain存在,它跟IIS應用程式一對一映射,可能基於物理目錄或者虛擬目錄建立。那麼這個類的執行個體是怎樣建立的呢?

圖1:建立AppDomain執行個體時由JetBrains dotTrace Profiler產生的調用棧

使用Reflector可以推斷AppDomain有一個拋出NotSupportedException異常的私人構造器,因此很明顯這個方法行不通。實際上初始化AppDomain執行個體的進入點是AppManagerAppDomainFactory.Create方法,為了找出這一點,需要使用一個分析器跟蹤初始化對象時產生的調用棧。圖1顯示了JetBrains dotTrac Profiler的截屏,它顯示了運行在IIS上的一個web應用程式在初始化AppDomain時產生的調用棧。有很多類參與了這個過程,它們也許是開發人員永遠不需要用到的。

注意:AppManagerAppDomainFactory類在CLR初始化過程中只運行一次,就像它的名字暗示的,它作為建立AppDomain以及其他重要對象的進入點。

圖2顯示了一個跟前面圖1一樣的調用棧,這次是從微軟CLR Profiler調用樹的輸出中截取的,它為AppDomain的初始化提供了更多的資訊。實際上高亮行表明主線程建立了兩個AppDomain類的執行個體。

圖2:微軟CLR Profiler調用樹視圖顯示的建立AppDomain執行個體時的調用棧

那麼是怎樣建立這個額外的執行個體呢,為什麼建立?很不幸這不是個容易的問題。前面圖中顯示的調用棧,指示了在建立與實際執行應用程式相關的AppDomain執行個體時採用的步驟,因此這個額外的執行個體,看起來像是用於某些難於理解的目的的輔助對象,盡我所能的猜測,它被用於容納所有不屬於任何應用程式的對象,例如AppManagerAppDomainFactory,因此被放置在一個隔離的AppDomain中。對於AppManagerAppDomainFactory類,這個輔助AppDomain只在CLR初始化時執行個體化一次,它在CLR初始化很早的時候進行,3所示。

圖3:額外AppDomain執行個體的順序和分配方法

圖3展示了Red Gate ANTS Profiler的一個截屏,它顯示了額外AppDomain執行個體在CLR初始化很早的時候建立,很明顯它比AppManagerAppDomainFactory類更早建立,因為很有可能它是AppManagerAppDomainFactory的容器。實際上在前面分析會話圖示中,單例AppManagerAppDomainFactory執行個體的ID為52。

另一個查看前面提到的兩個AppDomain執行個體初始化過程的方法,是微軟CLR Profiler提供的分配視圖,它建立一個圖形流程,展示處理中類的使用位置,像圖4顯示那樣。

圖4:微軟CLR Profiler分配視圖顯示的兩個AppDomain初始化過程

它展示了一個平面視圖,從根項目,即CLR,和線程類之間裁剪出所有的類,然而它清晰的顯示了建立兩個AppDomain時的調用順序。

從前面圖中可以得到另外一個關於AppDomain執行個體的資訊是,每個執行個體佔用100位元組記憶體。這不會帶來多少問題,但有人會認為AppDomain是一個很大的類,因為它必須容納整個應用程式。實際上它提供很多的服務,但並不儲存太多資料。

到現在輔助AppDomain執行個體已經被建立了,包括AppManagerAppDomainFactory類,它的Create方法就是圖1和2中顯示的調用棧的入口方法。

這個方法通過COM暴露出來,提供給調用者,因此是Unmanaged 程式碼。AppManagerAppDomainFactory類實現了 IAppManagerAppDomainFactory介面,它的結構顯示在圖5中。

圖5:IAppManagerAppDomainFactory介面結構

這個介面使用ComImport和InterfaceType屬性修飾,它們將類型綁定到非託管介面類型上。調用這個方法時,將產生圖1和2的調用棧圖形,最終觸發AppDomain類執行個體的建立,容納用於處理請求的目標應用程式。

AppDomain對象建立以及運行之後,剩餘工作就是處理請求,這比前面已經完成的工作內容更多,這也許是ASP.NET架構中最有意思的部分,但在這個有趣的部分開始之前我已經介紹了一些關鍵的主題。

總結

這篇文章中我介紹了ASP.NET基礎結構中一些很底層的主題,涉及那些由ASP.NET ISAPI擴充展示的非託管世界,以及運行web應用程式的AppDomain所展示的託管世界之間的一些介面。我展示了初始化AppDomain的機制,以及哪些類參與了這個處理。下一篇文章中我會通過HTTP管道討論Managed 程式碼,在我的映像裡這應當是ASP.NET架構最迷人的一章,實際上它使得ASP.NET不同於其他所有的web開發架構。我希望你像我寫這篇文章時一樣充滿興趣的閱讀,我的建議是開啟一些分析工具自己嘗試這些內容,這是充分理解它怎樣工作的最好方法。

引用

  • Simone Busoli - ASP.NET Internals – IIS and the Process
    Model
  • Rick Strahl -

    A low-level Look at the ASP.NET Architecture
  • Dino Esposito –

    Programming Microsoft ASP.NET 2.0 Core Reference
  • Dino Esposito –

    Programming Microsoft ASP.NET 2.0 Applications Advanced Topics
  • 相關文章

    聯繫我們

    該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.