當一(yī)個客戶端頁面訪問IIS試圖獲取一(yī)些信息的時候,發生(shēng)了什麽事情?一(yī)個請求在通過了HTTP管道後又(yòu)發生(shēng)了什麽?本文主要是描述這兩個過程,即IIS處理asp.net請求和asp.net的頁面生(shēng)命周期。歡迎大(dà)家積極拍磚,共同學習,共同進步。
首先我(wǒ)們要弄清楚兩個非常重要的概念:
1, worker process(w3wp.exe). worker process管理所有的來自客戶端的請求并給出響應。它是IIS下(xià)asp.net應用程序的核心。
2, application pool. 它是worker process的容器,IIS5及之前的IIS版本均沒有application pool的概念。每一(yī)個application pool對應着一(yī)個worker process,在IIS Metabase中(zhōng)維護着Application Pool和worker process的Mapping。這就避免了IIS5中(zhōng)出現的worker process(IIS5中(zhōng)是aspnet_wp.exe,同一(yī)時間隻能運行一(yī)個該進程)崩潰,application全崩潰的局面。
客戶端向IIS發出一(yī)個資(zī)源請求後發生(shēng)了如下(xià)事情:
1, server接受該請求
IIS6通過内核模式(Kernel mode)中(zhōng)的HTTP.SYS來分(fēn)發各個Request到application pool。 這并不是随機的過程,在application pool創建的時候就已經注冊到了HTTP.SYS,所以當請求來到時HTTP.SYS會直接發送到相應的application pool。 接下(xià)來在IIS的用戶模式(User mode)中(zhōng),Web Admin Services (WAS) 做了從HTTP.SYS中(zhōng)得到Request并分(fēn)發到application pool的工(gōng)作。application pool直接把request傳遞給worker process。
2, 請求傳遞到worker process後,worker process初始化加載ASP.NET ISAPI(Internet Server Application Program Interface),ASP.NET ISAPI進而加載CLR創建托管環境。
(注:ISAPI隻是一(yī)個接口,起到一(yī)個代理的作用,主要能力就是根據Request URL的後綴來尋找該後綴的處理程序)
ASP.NET ISAPI定義在aspnet_isapi.dll中(zhōng),它本身運行在一(yī)個非托管的環境中(zhōng)。ASP.NET ISAPI開(kāi)始一(yī)個HttpRuntime, HttpRuntime調用ProcessRequest方法來開(kāi)始處理請求。ProcessRequest根據ISAPI傳進來的iWRType 來創建不同的HttpWorkerRequest,從而屏蔽了不同IIS的差異。接下(xià)來ProcessRequest方法創建了HttpContext,我(wǒ)們使用HTTPContext.Current來訪問它。在HttpRuntime使用HttpApplicationFactory創建了HttpApplication對象(IHttpHandler)以後,所有的請求都會在通過httpmodule後找到相應的Httphandler進行處理。在HttpApplicationFactory創建HttpApplication之前,會查找config(web.config和Machine.config)文件中(zhōng)注冊的所有的HttpModule,并根據配置信息加載相應的Assembly,通過Reflection創建對應的HttpModule,并将這些Module加到HttpApplication 的_moduleCollection Filed中(zhōng)。我(wǒ)們對一(yī)個Application的請求最終會落到一(yī)個HttpApplication對象上。當一(yī)個請求到來時,ASP.NET會在Httplication Pool中(zhōng)查找未被使用的HttpApplication對象。
3, 請求通過HTTP管道後,每個請求都發向相關的各自的httphandler,IIS請求處理過程結束。
HttpHandler是HTTP管道的終點,它爲每個request生(shēng)成輸出。System.Web.UI.Page就是這樣一(yī)個典型的Httphandler,當我(wǒ)們請求一(yī)個aspx頁面,這個HttpHandler就生(shēng)成html發送回客戶端。看Page類的簽名:
public class Page : TemplateControl, IHttpHandler
{
}
可以看到,Page類就是一(yī)個HttpHandler。
綜上整個過程就是:當客戶端向服務器發送資(zī)源請求時,請求首先到達IIS的HTTP.SYS。然後HTTP.SYS發送請求道對應的Application Pool。 然後Application Pool發送請求到Worker Process(W3WP.exe)中(zhōng)加載ISAPI Extension,ISAPI創建一(yī)個HttpRuntime對象來通過HttpModule和HttpHandler處理請求。 然後頁面生(shēng)命周期就開(kāi)始了。
4, 頁面生(shēng)命周期開(kāi)始
頁面生(shēng)命周期的主要階段包括:
頁面初始化(Init): 服務器創建服務器控件的實例
加載(load): 控件實例被加載到它定義的頁面對象中(zhōng)
預輸出:(PreRender) 對控件的更改被更新,準備輸出。
保存(SaveViewState): 控件的狀态信息被保存。
輸出頁面(Render):服務器爲控件創建html标記。
處理(Dispose): 主要做的工(gōng)作就是dispose, 關閉數據庫連接,文件資(zī)源的釋放(fàng)等。
卸載(Unload):銷毀服務器控件的實例
頁面生(shēng)命周期的主要事件:
PreInit:
1.檢查IsPostBack 屬性
2.動态設置Master Page
3.動态設置Theme
4.設置控件的默認值(UniqueId等)
5.重新創建動态控件(初始化控件),初始化控件的值
Init: 這個事件發生(shēng)在所有的控件被初始化,所有的皮膚設置被應用以後。它用來讀取或者初始化控件屬性。它能夠用來注冊一(yī)些aspx頁面中(zhōng)沒有指出的控件的事件。
InitComplete: Use this event for processing tasks that require all initialization to be complete.
PreLoad: 加載頁面的ViewState和所有的控件,然後處理所有的包含在Request實例中(zhōng)的postback數據。
Load: 這個事件可能是大(dà)家最熟悉的了。需要注意的是,Page對象會遞歸的調用子控件的onload事件直到頁面和所有的子控件被加載完成。這個事件主要用來設置控件屬性的值,建立數據庫連接(通常不這麽做)。
Control events: 這個就不多說了,主要是處理控件的事件,例如click。這也就讓我(wǒ)們明白(bái)了每次我(wǒ)們click一(yī)個Button的時候,實際上是要先去(qù)執行load事件然後才執行click事件的,一(yī)般我(wǒ)們用!IsPostBack來判斷一(yī)下(xià)從而避免執行不必要的加載邏輯。
LoadComplete: 頁面所有的控件都被加載以後執行,暫時沒有想到用來幹什麽。。。
PreRender: 在HTML被生(shēng)成之前這是最後一(yī)個事件。每一(yī)個頁面中(zhōng)的控件都有PreRender的過程。在這裏對将要輸出的HTML結果進行最後一(yī)次修改。
SaveStateComplete: 在這個時間發生(shēng)之前,已經保存了所有控件和頁面的,任何對page或者控件的改動都不會産生(shēng)左右。暫時沒想到用來幹啥。
Render: 它不是一(yī)個事件而是一(yī)個方法。工(gōng)作就是把HTML寫回客戶端浏覽器。
UnLoad: 頁面中(zhōng)的每一(yī)個控件都會發生(shēng)這件事。在控件中(zhōng),使用這個事件來做清理工(gōng)作,例如關閉數據庫連接等。對與頁面本身也是做清理工(gōng)作,例如關閉打開(kāi)的文件和數據庫連接,或者結束日志(zhì)或者其它指定的工(gōng)作。
需要說明的是,每次Request都會創建一(yī)個全新的Page類的實例,所以在頁面中(zhōng)的自己定義的字段是不能在兩次request中(zhōng)傳遞值的,需要使用viewstate來存儲。
5, HttpHandler根據頁面生(shēng)命周期中(zhōng)事件的處理把結果發回IIS,IIS再把結果發回客戶端浏覽器。
值得注意的是,在這個過程中(zhōng)請求會再次通過HttpModule(注冊一(yī)個EndRequest事件)。
至此,整個Request結束。
聯系電話(huà):020-87518715
聯系郵箱:services@picusit.com
公司名稱:鄭州易科計算機服務有限公司
公司地址:廣州市天河區龍口西路100号中(zhōng)明大(dà)廈1601