前言 css
爲何我會起這樣的一個標題,其實我本來只想瞭解asp.net的管道模型而已,但在查看資料的時候遇到不明白的地方又橫向地查閱了其餘相關的資料,而收穫比當初預想的大了不少。 html
有本篇做基礎,下面兩篇就更好理解了: web
理解並自定義HttpHandler windows
理解並自定義HttpModule api
目錄 瀏覽器
通常不寫目錄,感受此次要寫的東西有些多就寫一個清晰一下吧。 服務器
1.Asp.net管道模型; session
2.進程的子進程與進程的線程; 併發
3.應用程序域(AppDomain); 框架
參考:ASP.NET使用管道模型(PipleLines)處理HTTP請求
管道模型中包含如下對象:
流程圖:
Http Request傳到工做進程(IIS5.x爲aspnet_wp.exe,IIS6.x和IIS7.x爲w3wp.exe)後,工做進程實例中經過ISAPIRuntime(主要做用是調用一些非託管代碼生成HttpWorkerRequest對象,HttpWorkerRequest對象包含當前請求的全部信息,而後傳遞給HttpRuntime)傳遞HttpWorkerRequest對象給HttpRuntime並調用HttpRuntime的ProcessRequest方法,HttpRuntime爲管道模型的入口此時正式進入管道模型。
HttpRuntime根據HttpWorkerRequest對象生成HttpContext,HttpContext包含request、response等屬性, 再調用HttpApplicationFactory的GetApplicationInstance方法生成HttpApplication, HttpApplication對象包含多個HttpModule對象(當一個HTTP請求到達HttpModule時,整個ASP.NET Framework系統還並無對這個HTTP請求作任何處理,也就是說此時對於HTTP請求來說,HttpModule是一個HTTP請求的「必經之路」,因此能夠在這個HTTP請求傳遞到真正的請求處理中心(HttpHandler)以前附加一些須要的信息在這個HTTP請求信息之上,或者針對截獲的這個HTTP請求信息做一些額外的工做,或者在某些狀況下乾脆終止知足一些條件的HTTP請求,從而能夠起到一個Filter過濾器的做用),並調用各個HttpModule對象的Init方法初始化HttpModule,在Init方法中能夠訂閱HttpApplication的事件從而做出相應的處理。當HttpApplication執行到Application_ResolveRequestCache時暫時將控制權交給HttpHandler並根據HttpHandler中是否啓用SessionState來肯定是否生成會話跟蹤功能(.aspx中用enablesessionstate設置,.ashx中用是否繼承IRequiresSessionState接口來設置),而後HttpApplication繼續執行自身的事件直到執行完PreRequestHandlerExecute事件就根據URL請求的後綴名獲取HttpHandlerFactory對象(默認狀況下.aspx調用System.Web.UI.PageHandlerFactory,.ashx調用System.Web.UI.SimpleHandlerFactory),調用HttpHandlerFactory的GetHandler方法生成具體的HttpHandler對象或調用ReleaseHandler方法使工廠能夠重用現有的處理程序實例來處理http請求並返回http響應,再通過HttpApplication對象的一系列事件(具體事件請參考HttpModule的認識(轉載))最終返回到客戶端,固然http響應所通過的HttpApplication的一系列事件均可以被HttpModule對象所訂閱。
參考:百度問答
我拿Windows舉例子吧, 由於Linux的內核好像是沒有線程概念的.進程和線程的區別在於粒度不一樣, 進程之間的變量(或者說是內存)是不能直接互相訪問的, 而線程能夠, 線程必定會依附在某一個進程上執行.我舉個例子, 你在Windows下開一個IE瀏覽器, 這個IE瀏覽器是一個進程. 你用瀏覽器去打開一個pdf, IE就去調用Acrobat去打開, 這時Acrobat是一個獨立的進程, 就是IE的子進程.而IE本身自己同時用同一個進程開了2個網頁, 而且同時在跑兩個網頁上的腳本, 這兩個網頁的執行就是IE本身經過兩個線程實現的.值得注意的是, 線程仍然是IE的內容, 而子進程Acrobat嚴格來講就不屬於IE了, 是另一個程序.之因此是IE的子進程, 只是受IE調用而啓動的而已.
追問:那我可不能夠這樣理解,父進程建立了一個子進程,只要給這個子進程分配必定的任務,他們今後就沒有關係了 。。。。
回答:也不能這麼說今後就不要緊了, 父進程仍是能夠經過和子進程通訊來得到一些信息的. 拿上面的例子來講,
IE能夠經過一些進程間通訊的接口來知道Acrobat是否順利的把pdf打開了之類的信息. 但有一點我以爲你的理解基本正確,
就是父進程和子進程是獨立的. 假如IE開了一個病毒子進程, 子進程不聽話, 父進程也沒什麼特別的辦法, 除了向系統申請去關閉它以外.
區分子進程和線程很簡單:一個獨立程序的運行稱爲一個進程, 在進程裏併發執行的不一樣部分稱爲線程. 由這個進程引起的另外的獨立程序運行爲這個進程的子進程. (基本上就是這樣, 更加嚴格的定義建議參考操做系統的教科書) 參考: .NET簡談組件程序設計之(AppDomain應用程序域) 參考: http://blog.csdn.net/zhoufoxcn/article/details/2425420 中周公的回答 進程:屬於操做系統上的概念,一個進程佔有一個內存地址,是應用程序與應用程序之間的邊界,進程之間不能共享代碼和數據空間(也就是不能直接交互),但能夠經過IPC(remoting、named pipe、webservice等)進行數據交互。一個進程出現錯誤甚至崩潰不會影響其餘進程的執行。 子進程:由另外一個進程啓動,子進程與父進程沒有從屬關係,兩進程能夠經過IPC進行數據交互。 線程:屬於操做系統上的概念,是代碼執行堆棧和執行上下文的邊界,同一進程的多個線程共享代碼和數據空間,但只負責執行代碼而沒有攜帶數據的功能。獨立或多個線程協同負責執行進程中的任務。 題外:對於線程其實還有不少方面能夠深刻,更多請參考《 深刻線程 》 應用程序域(AppDomain) 參考: 理解AppDomain AppDomain是.net framework獨有的概念,是邏輯宿主,其功能就像進程那樣是程序運行的獨立空間(從進程中分配獨立的內存空間,AppDomain間不能共享代碼和數據空間),當一個AppDomain中的程序出現異常甚至崩潰時不會影響到其餘AppDomain中運行的程序。但AppDomain不是進程,一個進程能夠擁有一個或多個AppDomain,其中必須有一個默認的AppDomain。 也許這裏您會有這樣的疑問:AppDomain是線程嗎?若是不是那麼與線程的關係是什麼呢?在.net framework中存在進程、應用程序域(AppDomain)、線程三個獨立又有聯繫的概念,一個進程含一個或多個AppDomain(必須存在一個默認AppDomain);一個進程含一個或多個線程(一般含一個線程池,裏面有多個可重用的線程);AppDomain與線程是多對多關係,但某一個時刻一個線程只能處理一個AppDomain,而AppDomain能夠由多個線程同時處理(併發)。 從運行程序時的過程是這樣的:系統首先分配一段內存地址空間而後把控制權交給了CLR生成默認AppDomain,而後將程序集加載到默認AppDomain中,程序正式運行(系統在託管堆中沒有AppDomain的概念,AppDomain不是操做系統的概念,由CLR管理)。默認AppDomain隨CLR而生而亡,沒法以編碼方式刪除或者卸載其中的程序集。 下面以圖的形式描述進程、線程、AppDomain的位置關係。
AppDomain之間不能直接交互,可經過代理的方式進行數據交互(若是是進程就使用IPC)。(具體實現之後探討!)
上圖左邊爲IIS5.X WEB SERVER,右邊爲Asp.net Application的工做進程(worker process),Asp.net是以做爲IIS組件的形式擴展IIS的。
當一個http request發送到IIS5.X時,IIS先把虛擬目錄轉變爲物理目錄,而後根據文件後綴名檢查iis中的metabase文件檢查文件擴展名與可執行代碼(擴展程序)映射記錄(如.aspx、.ashx等對應aspnet_isapi.dll),若是metabase文件中沒有就再檢查是否爲不受服務器端保護的文件(受服務器端保護:App_Code文件夾下的文件;不受服務器端保護:css、js文件),若是都不存在則直接返回404HTTP狀態碼給客戶端;(該查找循序可經過《理解並自定HttpHandler》)存在則iis的inetinfo.exe實例會調用相應的可執行代碼(這裏是aspnet_isapi.dll),aspnet_isapi.dll會經過一個命名管道(named pipe,一種簡單的IPC——進程通訊機制,具體內容請參考:《命名管道及延伸進程通訊學習》)把從inetinfo.exe獲取的request異步轉發到Asp.net工做進程實例:aspnet_wp.exe,而後就進入管道模型。同時aspnet_isapi.dll經過named pipe監測工做進程的運行情況,若是工做進程性能低於某個值aspnet_isapi.exe就會殺死工做進程,當下一個請求傳遞過來時從新啓動一個工做進程處理請求。而工做進程經過named pipe同步請求web server的信息(如調用Server對象獲取服務器信息)。
圖依然秉承着我很醜但頗有用的原則,嘻嘻!! aspnet_wp.exe的工做進程中含有一個線程池和一個默認AppDomain,當一個Request發送到工做進程後,工做進程會根據請求的虛擬目錄的文件(一個虛擬目錄對應一個Application)由默認AppDomain建立AppDomain並將該虛擬目錄的程序集加載到AppDomain中(虛擬目錄中可能不止一個程序集,而默認AppDomain會將整個虛擬目錄下的全部程序集加載到AppDomain上),若是該虛擬目錄的AppDomain已存在就直接使用該AppDomain,若是虛擬目錄的程序集發生變化(包括web.config變化),就會新建一個AppDomain再將以變化的程序集加載到新的AppDomain中;這時從線程池獲取空閒線程執行程序集(寫一個網站發佈成兩個虛擬目錄進行測試,能夠看到執行http請求處理的線程不斷地變化,兩個虛擬目錄會出現使用相同線程的狀況)。程序集中的變量和狀態均保存在所屬的AppDomain的內存中,如HttpContext.Current.Items、Application等(Application對象其實就是一張HashTable,能夠被多個線程(iis5.X)或多個Application實例(iis6.x)訪問),AppDomain之間不能直接訪問對方的變量和狀態。Session狀態變量有三種模式InProc、StateServer和SQLServer,其中默認爲InProc表示Session狀態保存在Asp.net進程中,若是虛擬目錄的程序集發生變化後在新AppDomain中調用以前所設置的Session狀態變量就會發現Session丟失了(客戶端的Cookie中保存的SessionID依舊,若是存在應該是能夠讀取的),代表Session模式爲InProc時Session狀態變量保存在對應的AppDomain中。 題外話:若是session模式設置爲StateServer表示使用狀態服務器保存Session狀態,就是使用另一個本地或遠程進程來保存Session狀態,本地開啓狀態服務器步驟(系統爲Windows server類型):1.開始->全部程序->管理工具->服務->開啓 Asp.net狀態服務,而後配置一下網站的web.config爲<sessionState mode="StateServer" stateConnectionString="tcpip=localhost:4242"/>