ASP.NET的底層體系1

文章引導

               1.ASP.NET的底層體系1html

               2.ASP.NET的底層體系2 程序員

引言:

                學習ASP.NET,要想作的更好,不瞭解ASP.NET是不行的。一個有理想的程序員都會像擠壓海綿同樣,努力的去學習和獲取寶貴的知識。web

                本篇文檔內容,轉自小皓園的博文--->(翻譯)從底層瞭解ASP.NET體系結構,以此來尊重原創精神,並對其進行提煉,去掉一些無關的內容。api

一.ASP.NET是什麼

                ASP.NET是一個請求處理引擎,它獲取客戶端的請求,而後經過內置的管道,把請求傳遞到終點,在這個終點,開發者能夠添加處理這個請求的邏輯代碼。瀏覽器

                整個ASP.NET引擎構建在託管代碼裏,全部的擴展功能都是經過託管代碼的擴展提供。緩存

                使用ASP.NET能夠完成一些任務,以前這些任務是使用IIS的ISAPI擴展和過濾來完成的,儘管還有一些限制,但與ASP相比,已經有了很大的進步。ISAPI是底層Win32樣式的API,它的接口就有1M,這樣對於大型程序開發是很是困難的,因爲ISAPI是底層的接口,所以它的速度也是很快的。安全

                微軟的ASP.NET和IIS的接口是經過宿主在.NET裏的ISAPI擴展來通訊的,ISAPI提供了與WebServer通訊的核心接口,而後ASP.NET使用非託管代碼獲取請求發出響應。服務器

二.HTTP

                HTTP運行時提供了一套複雜的機制,在處理請求的每個層面都牽涉許多對象,但大多數對象均可以經過派生或事件接口來擴展。經過HTTP,能夠進入較低層次的接口如:緩存、身份驗證、受權等信息。能夠在處理請求以前或以後過濾內容等等。多線程

三.從瀏覽器到ASP.NET

                咱們從一個典型的ASP.NET Web請求的生命週期開始提及。用戶經過在瀏覽器輸入一個URL,點擊連接,提交一個HTML表單(一個POST請求),或者一個客戶端程序調用基於ASP.NET的Web Services。在服務端,IIS收到這個請求。異步

                ASP.NET的底層經過ISAPI擴展與IIS通訊,而後,經過ASP.NET這個請求一般被路由到一個帶.aspx擴展名的頁面,可是這個處理過程如何工做,則徹底依賴於HTTP處理器(handler)的執行。在IIS中,.aspx經由「應用程序擴展」被映射到ASP.NET ISAPI的dll文件:aspnet_isapi.dll,每個觸發ASP.NET的請求,都必須由一個已經註冊的,而且指向aspnet_isapi.dll的擴展名來標識。

                依靠擴展名,ASP.NET把一個請求路由到一個恰當的處理器,該處理器則負責處理這個請求。

                     例子:Web Service的擴展名.asmx不會把一個請求路由到磁盤的某一個頁面,而是會路由到定義中附加了指定特性的類,此特性會把它標記爲一個Web Services的實現。

四.ISAPI

                ISAPI是底層非託管的Win32 API,它定義的接口很是的單一且性能最優。用這些接口處理原始指針(raw pointer),而函數指針列表(function pointer)則用於回調。ISAPI提供了最底層的、高性能的接口。

                ISAPI趨向於被當作橋接口使用,用於給高層級的工具提供應用服務類型的功能。

                     例子:ASP.NET就是構建在ISAPI之上,ISAPI給高層次的應用程序提供了高性能垂直訪問接口,使得高層次的應用程序須要的信息能夠從ISAPI提供的信息中提煉,引擎能夠提煉ISAPI接口提供的表單裏的對象有:Request Response。

                做爲約定,ISAPI支持ISAPI擴展(extensions)和ISAPI過濾(filters),擴展是請求處理接口,提供了跟Web Server輸入和輸出相關的邏輯處理。從本質來講,它是一個事務接口。

                ISAPI是鉤子接口,它容許你查看進入IIS的每個請求並能夠修改請求的內容。

                 

                IIS把不一樣的擴展名如.aspx映射到ASP.NET的ISAPI擴展,經過這種機制,在WEB SERVER裏,請求就能夠被路由到ASP.NET的處理管道里。

五.IIS5   IIS6

                當一個請求進來的時候,IIS會檢查腳本映射,而後把請求路由到aspnet_isapi.dll。IIS 6總會保持一個單獨的工做進程:應用程序池,全部的處理都發生在這個進程裏。對於IIS 6來講,應用程序池是一個重大的改進,由於他們容許以更小的粒度控制一個指定進程的執行。你能夠爲每個虛擬目錄或者整個web站點配置應用程序池,這樣它能夠與運行在同一臺機器的其餘程序徹底隔離。

                應用程序池是高度可配置的,經過設置應用程序池的執行許可,能夠配置他們的執行環境。對於ASP.NET而言,IIS 6最大的改進是使用應用程序池代替了machine.config裏的ProcessModel實體的大部分功能。在IIS 5裏,這個實體是很難管理的,由於它的設置是全局的,並且不可以在指定WEB程序的wen.config裏覆蓋這些設置。當IIS 6運行的時候,ProcessModel裏的大部分配置將被忽略,取而代之的是讀取應用程序池的配置。另一些配置,像線程池的大小和IO線程數目等仍然仍是要經過這個節點的配置。

              IIS 6應用程序池也包含了ASP.NET固有的東西,ASP.NET能夠和新的底層API通訊,這些API容許直接訪問HTTP緩衝存儲器的API,而HTTP緩衝存儲器的API能夠直接進入Web SERVER的緩衝存儲器,卸載ASP.NET級別的緩存。

              在IIS 6裏,ISAPI擴展運行在應用程序池的工做進程裏,而.NET運行時也在這個進程裏,因此ISAPI擴展和.NET運行時通訊是發生在進程內。

              

  六.進入.NET運行時

              進入.NET運行時真正登陸點發生在一些沒有正式文檔的類和接口之間。工做進程w3wp.exe宿主在.NET運行裏。ISAPI dll經過底層的COM調用一小撮非託管類型的接口,其實最終調用的是ISAPIRuntime派生類的實例。進入運行時的第一個登陸點是未歸檔的ISAPIRuntime類,它經過COM把接口IISAPIRuntime暴露給調用者,這些COM接口是底層的IUnknown。基於這些接口,就意味着ISAPI到ASP.NET之間的調用屬於內部調用。

              IISAPIRuntime接口擔當着來自ISAPI擴展的非託管代碼和託管代碼之間的橋樑

                            [return:MarshallAs(UnmanagerType.I4)]

                            int ProcessRequest(IntPtr ecb,[In,MarshallAs(UnmanagerType.I4)] int useProcessMode)

              ecb參數是ISAPI擴展控制塊,它做爲非託管資源傳遞給ProcessRequest方法,此方法將獲取ECB,而後做爲基本的輸入和輸出接口,用於Request和Response對象。ISAPI ECB包含着全部底層的請求信息,這其中包括服務器變量、用於表單變量的輸入流和寫數據並把數據發送到客戶端的輸出流中。一個單獨的ECB引用基本提供了一個ISAPI請求能夠訪問的全部功能。

              ISAPI擴展以異步的方式處理請求,因此當ISAPI擴展調用了工做進程或者IIS的線程後,會當即返回,但會爲當前的請求保留ECB,所以,ECB須要包含這樣的機制,當請求結束的時候通知ISAPI,而後ISAPI擴展釋放ECB資源。接着以異步的方式當即釋放ISAPI的工做線程和卸載由ASP.NET託管的那個隔離的處理線程。

              ASP.NET獲得ECB引用後,會在內部使用它來獲取當前請求的相關信息。如服務器變量。ECB將就存活直到這個請求結束或者IIS超時,在這以前,ASP.NET將會與ecb繼續保持通訊,當請求結束的時候,輸出的內容會寫進ISAPI的輸出流中。而後ISAPI擴展會被通知請求已經結束,讓它知道ECB能夠被釋放了,這個執行過程是很是高效的。

七.ProcessRequest

              ISAPI是多線程的,所以請求能夠以多線程的方式穿過AppDomainFactory.Create()返回的對象引用。

              

 

public int ProcessRequest(IntPtr ecb,int iWRType)
{
    //ISAPIWorkerRequest從HttpWorkRequest繼承,這裏建立的是一個ISAPIWorkerRequest派生類的一個實例
    HttpWorkerRequest request=ISAPIWorkerRequest.CreateWorkerRequest(ecb,iWRType);
    //獲得請求的物理路徑
    string str=request.GetAppPathTranslated();
    //獲得AppDomain的物理路徑
    string str2=HttpRuntime.AppDomainAppPathInternal;
    
    if( str2==null || str.Equals(".") || string.Compare(str,str2,true,CultureInfo.InvariantCulture)==0)
    {
         HttpRuntime.ProcessRequest(request);
         return 0;
    }

     //若是外部請求的AppDomain物理路徑和原來的AppDomain的路徑不一樣,說明ISAPI維持的AppDomain已經失效,因此須要把原來的城西關閉
     HttpRuntime.ShutDownAppDomain("from "+str+str2);
     return 1;
}

 

              上述代碼ProcessRequest接收一個ISAPI ecb對象和一個服務器類型參數,這個線程是安全的,所以多個ISAPI線程能夠同時安全的調用單個返回對象的實例。

              System.Web.Hosting.ISAPIWorkerRequest繼承抽象類HttpWorkerRequest,它的職責是建立一個抽象的輸入和輸出視圖,爲Web程序的輸入提供服務。上面的代碼中有一個方法CreateWorkerRequest,這個方法的第二個參數用於指定建立什麼樣的工做請求對象,即ISAPIWorkerRequest的派生類,這裏有三個不一樣的版本:ISAPIWorkerRequestInProc,ISAPIWorkerRequestInProcForIIS6,ISAPIWorkerRequestOutOfProc。當這個請求到來時,這個ISAPIWorkerRequest將被建立,用於給Request和Response對象提供基礎服務,而這兩個對象將從數據的提供者WorkerRequest接收數據流。

              抽象類HttpWworkerRequest圍繞着底層的接口提供了高層的抽象,這樣就不用考慮數據的來源,不管他是一個CGI Web Server,Web瀏覽器仍是自定義的機制(用於把數據流入HTTP運行),ASP.NET均可以以一樣的方式從中獲取數據。

              有關IIS的抽象主要集中在ISAPI ECB塊,在咱們的請求處理當中,ISAPIWorkerRequest依賴於ISAPI ECB塊。

              ISAPIWorkerRequest實現了一個高層次包裝器方法,它調用了低層次的核心方法,而這些方法負責實際調用非託管API或者是「服務層的實現」,核心的方法在ISAPIWorkerRequest的派生類中得以實現,這樣能夠針對它宿主的環境提供特定的實現,爲之後增長一個額外環境的實現類做爲新的Web Server接口提供了便利。

               說句實話,上面的內容講了這麼多,頭都被繞暈了。講來說去總結就是如下幾點:

                            1.用戶在瀏覽器輸入一個URL,提交一個HTML表單。服務端的IIS接收到請求,ASP.NET的底層ISAPI與IIS通訊,路由到指定的頁面。

                            2.ISAPI是底層非託管的win32 API,ASP.NET都是構建在ISAPI之上,它給高層次的應用程序提供了高性能垂直訪問接口。

                            3.在ISAPI擴展裏,當第一個請求命中一個ASP.NET的映射擴展時,工做線程就會引導.NET運行時啓動。一旦運行時存在了,非託管代碼就能夠爲指定的虛擬目錄請求一個ISAPRuntime的實例,固然這個前提是這個實例還不存在,每一個虛擬目錄都會擁有一個AppDomain,ISAPIRuntime存在於AppDomain中,它引導一個單獨的程序啓動。

相關文章
相關標籤/搜索