前言: 記錄 IIS 相關的筆記還是從公司筆試考核題開始的,問 Application Pool 與 AppDomain 的區別? 促使我對進程池進了知識的學習,所以記錄一下學習的筆記。 我們知道現在 .NET 就業來看,80% 的 .NET 程式員都是從事 Web 開發, 如果對微軟唯一(現在不唯 ...
前言: 記錄 IIS 相關的筆記還是從公司筆試考核題開始的,問 Application Pool 與 AppDomain 的區別? 促使我對進程池進了知識的學習,所以記錄一下學習的筆記。 我們知道現在 .NET 就業來看,80% 的 .NET 程式員都是從事 Web 開發, 如果對微軟唯一(現在不唯一了)Web 伺服器都不熟的話,那就有點兒尷尬了;(不能被微軟寵壞了) Web 站點性能的好壞不在於 Web 伺服器本身,IIS 可以說已經說一款非常強悍的 Web 伺服器了。 現在對 IIS 6.0、IIS 8.5 做一些基本知識的整理; 微軟早期在 IIS 上,提出進程池的概念,允許多個 Web 站點運行在一個 IIS 進程池(W3WP.exe)上,怎麼說有好有壞, 好在他節省了 CPU、記憶體的開銷,壞在他進程池的配置非獨立,最大問題是某一個 Web 站點掛了,同一個進程次下的站點都會掛掉。 乃至在 IIS 7+ 以上的版本,預設創建的站點都會是獨立的進程池; Web 伺服器其實深入進去也沒有什麼多神秘的東西,核心取決於你的設計,怎麼合理處理請求/響應、併發控制; // 追評: 所有的 Web 伺服器,無非是對網路層和 HTTP 協議層做了相應的解析處理而已。 一、IIS 6.0 早些年,公司還在一直在使用 IIS 6.0,作為微軟早期的版本,那各種安全問題源源不斷,此處默哀一下苦逼的程式員 什麼遠程代碼執行、上傳數據流漏洞、身份認證漏洞.... 導致很多 .NET 開發人員覺得 Web 伺服器放在 Windows 下就是不安全。 其實微軟背後的團隊,已經非常努力的在做補丁和迭代了, 註意: 1、伺服器上一定不要關閉 Windows Update。 2、作為一名程式員,有責任關於微軟動態、更新穩定的 IIS 版本。 IIS 6.0 由於太老的產品,不做過多的分析。 二、IIS 運行過程 (這樣比較好理解,假裝自己在寫 Web 伺服器) 首先,HTTP 請求規範原理、細節不做解釋了。 我們都知道 IIS Web 伺服器預設監聽 80 埠,那麼監聽的過程總得需要支撐吧, HTTP.sys 組件,它負責監聽所有的 HTTP 請求,監聽到請求了以後, 根據請求信息(URL)分配對對應的進程池上(W3WP.exe/Application Pool),進程池完成本次請求處理後進行響應; // 在上文簡單提到了 IIS 進程池,所有的站點都必要依賴與他,而進程池啟動後會產生一個獨立的 W3WP.exe 進程 1、HTTP.SYS:(Kernel)的一個組件,它負責偵聽(Listen)來自於外部的HTTP請求,根據請求的URL將其轉發給相應的應用程式池 (Application Pool)。 當此HTTP請求處理完成時,它又負責將處理結果發送出去。 為了提供更好的性能,HTTP.sys 內部建立了一個緩衝區,將最近的HTTP請求處理結果保存起來。 2、Application Pool:IIS 總會保持一個單獨的工作進程:應用程式池。所有的處理都發生在這個進程里,包括 ISAPI dl l的執行。 應用程式池它們允許以更小的粒度控制一個指定進程的執行。 你可以為每一個虛擬目錄或者整個Web 站點配置應用程式池,這可以使你很容易的把每一個應用程式隔離到各自的進程里, 這樣就可以把它與運行在同一臺機器上其他程式完全隔離。從 Web 處理的角度看,如果一個進程死掉,至少它不會影響到其它的進程。 當應用程式池接收到 HTTP 請求後,交由在此應用程式池中運行的工作者進程 Worker Process: w3wp.exe 來處理此HTTP請求。 3、Worker Process: 當工作者進程接收到請求後,首先根據尾碼找到並載入對應的 ISAPI 擴展 (如:aspx 對應的映射是 aspnet_isapi.dll ), 工作者進程載入完 aspnet_isapi.dl l後,由 aspnet_isapi.dll 負責載入 ASP.NET應用程式的運行環境即CLR (.NET Runtime)。 Worker Proces s運行在非托管環境,而 .NET 中的對象則運行在托管環境之上(CLR),它們之間的橋梁就是 ISAPI 擴展。 4、WAS(Web Admin Service):這是一個監控程式,它一方面可以存取放在InetInfo元資料庫(Metabase)中的各種信息, 另一方面也負責監控應用程式池(Application Pool)中的工作者進程的工作狀態況,必要時它會關閉一個老的工作者進程並創建一個新的取而代之。 看圖: 進程池中 經典管道 ISAPI 的作用、生命周期? 集成管道中的乞求處置管道怎麼理解? 二、ASP.NET 運行原理(淺析) 看圖: ( AppDomain 運行過程圖示) AppDomain 的作用,相信大家都很瞭解了吧.這裡簡明扼要的寫幾點: 1、一個 AppDomain 中的代碼創建的對象不能由另一個 AppDomain 中的代碼直接訪問(只能使用按引用封送或者按值封送,起到了很好的隔離作用); 2、AppDomain 可以卸載 CLR 不支持從 AppDomain 中卸載一個程式集的能力,但可以告訴 CLR 卸載一個 AppDomain, 從而達到卸載當前包含在該 AppDomain 內的所有程式集. 3、AppDomain 可以單獨保護 當宿主載入一些代碼之後,可以保證這些代碼不會被破壞(或讀取)宿主本身使用的一些重要的數據結構.。 4、AppDomain 可以單獨配置 設置主要影響 CLR 在 AppDomain 中載入程式集的方式,涉及搜索路徑、版本綁定重定向、捲影複製及載入器的優化。 由以上幾點可以看出 AppDomain 確保了 Windows 系統及其中運行的應用程式的健壯性。AppDomain 提供了保護、配置和終止其中每一個應用程式所需的隔離性。 再來看下 ProcessRequest 的過程: 簡單分析一下上圖 ProcessRequest(HttpWorkerRequest wr)中判斷 wr 是否為 null,然後判斷管線是否完整,再調用 ProcessRequestNoDemand(wr) 方法, 並判斷當前 RequestQueue 是否為 null,接著計算等待時間並更新管線數 CalculateWaitTimeAndUpdatePerfCounter(wr); 重置 wr 開始時間 wr.ResetStartTime();調用 ProcessRequestNow(wr) 方法,並調用 ProcessRequestInternal(wr) 方法;
到這裡想必能夠使大家對ASP.NET管道機制能夠有一個簡單的回顧.當然還有很多地方沒有詳細分析。 再來總結一下IIS運行過程及ASP.NET管道機制: Request→ (Internet ) HTTP.sys 監聽 → WAS (IIS6 web Admin Service /IIS7 (Windows Activation Service) 接收請求 → (傳入)Application Pool's → w3wp.exe(檢查URL尾碼) → (載入)ISAPI擴展[aspnet_isapi.dll] → 註冊映射 構造HttpRuntime類 →ProcessRequest方法 HttpContext實例產生(Request,Response,Session and so on…) HttpRuntime 調用 HttpApplicationFactory載入HttpApplication對象 穿越HttpModule到達HttpHandler 簡單用140個字元(即一條微博的字數)概括: Request→ (Internet ) HTTP.sys →(WAS)→Application Pool's → w3wp.exe→ISAPI→ Map→ (Pipeline) HttpWorkerRequest→AppDomain→HttpRuntime→ProcessRequest()→ HttpContext(Request,Response) → HttpRuntime→HttpApplicationFactory→HttpApplication→ HttpModule→HttpHandler→EndRequest