ASP.NET底層架構探索之進入.NET運行時

來源:互聯網
上載者:User
asp.net|架構

  進入.NET運行時的真正的入口發生在一些沒有被文檔記載的類和介面中(譯著:當然,你可以用Reflector來查看J).除了微軟,很少人知道這些介面,微軟的傢伙們也並不熱衷於談論這些細節,他們認為這些實現細節對於使用ASP.NET開發應用的開發人員並沒有什麼用處。

  背景工作處理序(IIS5中是ASPNET_WP.EXE,IIS6中是W3WP.EXE)寄宿.NET運行時和ISAPI DLL,它(背景工作處理序)通過調用COM對象的一個小的非託管介面最終將調用發送到ISAPIRuntime類的一個執行個體上(譯註:原文為an instance subclass of the ISAPIRuntime class,但是ISAPIRuntime類是一個sealed類,疑為作者筆誤,或者這裡的subclass並不是子類的意思).進入運行時的第一個入口就是這個沒有被文檔記載的類,這個類實現了IISAPIRuntime介面(對於調用者說明來說,這個介面是一個COM介面)這個基於Iunknown的底層COM介面是從ISAPI擴充到ASP.NET的一個預定的介面.圖3展示了IISAPIRuntime介面和它的呼叫簽章.(使用了Lutz Roeder出色的.NET Reflector 工具http://www.aisto.com/roeder/dotnet/).這是一個探索這個步步為營過程的很好的方法.

  

  圖3-如果你想深入這個介面,開啟Reflector,指向System.Web.Hosting命名空間. ISAPI DLL通過調用一個託管的COM介面來開啟進入ASP.NET的入口,ASP.NET接收一個指向ISAPI ECB的非託管指標.這個ECB包含訪問完整的ISAPI介面的能力,用來接收請求和發送響應回到IIS.

  IISAPIRuntime介面作為從ISAPI擴充來的Unmanaged 程式碼和ASP.NET之間的介面點(IIS6中直接相接,IIS5中通過具名管道).如果你看一下這個類的內部,你會找到含有以下籤名的ProcessRequest函數:

  [return: MarshalAs(UnmanagedType.I4)]

  int ProcessRequest([In] IntPtr ecb,

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

  其中的ecb參數就是ISAPI擴充控制塊(Extention Control Block),被當作一個非託管資源傳遞給ProcessRequest函數.這個函數接過ECB後就把它做為基本的輸入輸出介面,和Request和Response對象一起使用.ISAPI ECB包含有所有底層的請求資訊,如伺服器變數,用於表單(form)變數的輸入資料流和用於回寫資料到用戶端的輸出資料流.這一個ecb引用基本上提供了用來訪問ISAPI請求所能訪問的資源的全部功能,ProcessRequest是這個資源(ecb)最初接觸到Managed 程式碼的入口和出口.

  ISAPI擴充非同步地處理請求.在這個模式下ISAPI擴充馬上將調用返回到背景工作處理序或者IIS線程上,但是在當前請求的生命週期上ECB會保持可用.ECB含有使ISAPI知道請求已經被處理完的機制(通過ecb.ServerSupportFunction方法)(譯註:更多資訊,可以參考開發ISAPI擴充的文章),這使得ECB被釋放.這個非同步處理方法可以馬上釋放ISAPI背景工作執行緒,並將處理傳遞到由ASP.NET管理的一個單獨的線程上.

  ASP.NET接收到ecb引用並在內部使用它來接收當前請求的資訊,如伺服器變數,POST的資料,同樣它也返回資訊給伺服器.ecb在請求完成前或逾時時間到之前都保持可訪問(stay alive),這樣ASP.NET就可以繼續和它通訊直到請求處理完成.輸出被寫入ISAPI輸出資料流(使用ecb.WriteClient())然後請求就完成了,ISAPI擴充得到請求處理完成的通知並釋放ECB.這個實現是非常高效的,因為.NET類本質上只是對高效的、非託管的ISAPI ECB的一個非常”瘦”(thin)的封裝器.

  裝載.NET-有點神秘

  讓我們從這兒往回退一步:我跳過了.NET運行時是怎麼被載入的.這是事情變得有一點模糊的地方.我沒有在這個過程中找到任何的文檔,而且因為我們在討論機器碼,沒有很好的辦法來反編譯ISAPI DLL並找出它(裝載.NET運行時的代碼)來.

  我能作出的最好的猜測是當ISAPI擴充接受到第一個映射到ASP.NET的副檔名的請求時,背景工作處理序裝載了.NET運行時.一旦運行時存在,Unmanaged 程式碼就可以為指定的虛擬目錄請求一個ISAPIRuntime的執行個體(如果這個執行個體還不存在的話).每個虛擬目錄擁有它自己的應用程式定義域(AppDomain),當一個獨立的應用(指一個ASP.NET程式)開始的時候ISAPIRuntime從啟動過程就一直在應用程式定義域中存在.執行個體化(譯註:應該是指ISAPIRuntime的執行個體化)似乎是通過COM來進行的,因為介面方法都被暴露為COM可調用的方法.

  當第一個針對某虛擬目錄的請求到來時,System.Web.Hosting.AppDomainFactory.Create()函數被調用來建立一個ISAPIRuntime的執行個體.這就開始了這個應用的啟動進程.這個調用接收這個應用的類型,模組名稱和虛擬目錄資訊,這些資訊被ASP.NET用來建立應用程式定義域並啟動此虛擬目錄的ASP.NET程式.這個HttpRuntime執行個體(譯註:原文為This HttpRuntime derived object,但HttpRuntime是一個sealed類,疑為原文錯誤)在一個新的應用程式定義域中被建立.每個虛擬目錄(即一個ASP.NET應用程式寄)宿在一個獨立的應用程式定義域中,而且他們也只有在特定的ASP.NET程式被請求到的時候才會被載入.ISAPI擴充管理這些HttpRuntime對象的執行個體,並根據請求的虛擬目錄將內部的請求路由到正確的那個HttpRuntime對象上.

  

  圖4-ISAPI請求使用一些沒有文檔記載的類,介面並調用許多Factory 方法傳送到ASP.NET的HTTP管道的過程.每個Web程式/虛擬目錄在它自己的應用程式定義域中運行,調用者(譯註:指ISAPI DLL)保持一個IISAPIRuntime介面的引用來觸發ASP.NET的請求處理.



聯繫我們

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