1. 程式人生 > >ASP.NET之旅--淺談Asp.net的執行機制(二)

ASP.NET之旅--淺談Asp.net的執行機制(二)

      上節中我們從Http請求在Asp.net中的執行過程進行了分析,但是對於真正核心的東西我們並沒有說明,那接下來我們將問題上拋,從底層類和物件的建立層面上來看Asp.net的執行機制。

三、Asp.net底層執行機制

   1、理解HTTP.SYS


       HTTP.SYS:運行於Windows核心(Kernel)的一個元件,它負責偵聽(Listen)來自於外部的HTTP請求(通常來自網路中另一臺計算機上的瀏覽器),根據請求的URL將其轉發給相應的應用程式池 (Application Pool)。當此HTTP請求處理完成時,它又負責將處理結果傳送出去(其接收者通常為發出HTTP請求的瀏覽器)。為了提供更好的效能,HTTP.SYS內部建立了一個緩衝區,將最近的HTTP請求處理結果儲存起來。
       通俗點說,HTTP.SYS 判斷了哪些 URL 是可以訪問的, 哪些是不可以訪問的。 舉個簡單的例子,為什麼你訪問不存在的檔案會出現  404  錯誤呢,就是在這一步確定的。如果請求的是一個可訪問的 URL,HTTP.SYS會將這個請求交給  IIS  工作者程序。

    2、AppDomain內部執行方式

        首先來看張圖,我們可以把HTTP請求畫在一張圖上來看。


 

步驟1

       HTTP請求進入Web伺服器後,首先由HTTP.SYS來判斷請求的頁面是否存在,如果存在的話將把請求資訊轉交給.NET Runtime。在這部分實際是完成兩個步驟,在將請求轉交給.NET Runtime的同時將請求資訊封存在HTTPWorkRequest類中供其它步驟呼叫。
Note:HttpWorkRequest類在以後的操作中至關重要,它第一次將Http請求資訊轉換為類資訊。

步驟2

      當請求到達.NET Runtime後,接下來的操作將會在託管環境中完成,這時請求就真正進入了.NET中,對請求資訊的操作是由.NET的底層類庫來實現。首先.NET Runtime將會針對請求資訊做兩個動作,一是準備HostingEnvironment;二是呼叫ApplicationManager類為HTTP請求動態的分配AppDomain,並把處理權交給AppDomain。

步驟3

        HTTP請求進入AppDomain後,將由物件ISAPIRuntime來接管,一方面經方法ProcessRequest()得到HttpWorkerRequest物件,另一方面由方法StartProcessing()生成HttpRuntime物件,接下來把處理權交給了HttpRuntime(HttpWorkerRequest物件將作為HttpRuntime方法中的引數被使用)。

步驟4

       HTTPRuntime接收到Http請求後,方法ProcessRequest處理請求。還記得步驟1中的HTTPWorkRequest類嗎,此時將會針對該類中的資訊進行操作,具體的實現由ProcessRequest方法實現。內部程式碼如下:

[AspNetHostingPermission(SecurityAction.Demand, Level=AspNetHostingPermissionLevel.Medium)]
public static void ProcessRequest(HttpWorkerRequest wr)
{
    if (wr == null)
    {
        throw new ArgumentNullException("wr");
    }
    if (UseIntegratedPipeline)
    {
        throw new PlatformNotSupportedException(System.Web.SR.GetString("Method_Not_Supported_By_Iis_Integrated_Mode", new object[] { "HttpRuntime.ProcessRequest" }));
    }
    ProcessRequestNoDemand(wr);
}
internal static void ProcessRequestNoDemand(HttpWorkerRequest wr)
{
    RequestQueue queue = _theRuntime._requestQueue;
    if (queue != null)
    {
        wr = queue.GetRequestToExecute(wr);
    }
    if (wr != null)
    {
        CalculateWaitTimeAndUpdatePerfCounter(wr);
        wr.ResetStartTime();
        ProcessRequestNow(wr);
    }
}
internal static void ProcessRequestNow(HttpWorkerRequest wr)
{
    _theRuntime.ProcessRequestInternal(wr);
}

        Note:在上面的請求中是不是看到有很多ProcessRequest()方法,該方法在很多類裡面出現,但是所處理的請求並不相同。實際上我們可以理解為一個驅動,在處理的過程中通過該方法加工請求資訊,然後驅動請求向下進行。

步驟5

       在HttpRunTime中經過一系列的驅動後,將會在ProcessRequestInternal方法中為Http請求分配應用程式。在這一步中還將建立HttpContext物件。

context = new HttpContext(wr, false); // 基於HttpWorkerRequest生成HttpContext
IHttpHandler applicationInstance = HttpApplicationFactory.GetApplicationInstance(context); // 得到HttpApplication
handler2.BeginProcessRequest(context, this._handlerCompletionCallback, context); // 由HttpApplication處理請求

       HttpSessionState 、HttpServerUtility等。 這些物件其實是開發人員常常使用的Asp物件,在程式中可以通過 Page 類或者 Context 類進行訪問。

步驟6

       經過步驟5後HTTP請求資訊才由基本資訊轉交給了Asp.net中的各個物件。接下來的操作會觸發一些列的管道事件,這時的請求才真正轉到HttpModule和HttpHandler中。

接下來我們看看常說的管道事件的建立過程:

internal override void BuildSteps(WaitCallback stepCallback)
{
    ArrayList steps = new ArrayList();
    HttpApplication app = base._application;
    bool flag = false;
    UrlMappingsSection urlMappings = RuntimeConfig.GetConfig().UrlMappings;
    flag = urlMappings.IsEnabled && (urlMappings.UrlMappings.Count > 0);
    steps.Add(new HttpApplication.ValidatePathExecutionStep(app));
    if (flag)
    {
        steps.Add(new HttpApplication.UrlMappingsExecutionStep(app));
    }
    app.CreateEventExecutionSteps(HttpApplication.EventBeginRequest, steps);
    app.CreateEventExecutionSteps(HttpApplication.EventAuthenticateRequest, steps);
    app.CreateEventExecutionSteps(HttpApplication.EventDefaultAuthentication, steps);
    app.CreateEventExecutionSteps(HttpApplication.EventPostAuthenticateRequest, steps);
    app.CreateEventExecutionSteps(HttpApplication.EventAuthorizeRequest, steps);
    app.CreateEventExecutionSteps(HttpApplication.EventPostAuthorizeRequest, steps);
    app.CreateEventExecutionSteps(HttpApplication.EventResolveRequestCache, steps);
    app.CreateEventExecutionSteps(HttpApplication.EventPostResolveRequestCache, steps);
    steps.Add(new HttpApplication.MapHandlerExecutionStep(app));
    app.CreateEventExecutionSteps(HttpApplication.EventPostMapRequestHandler, steps);
    app.CreateEventExecutionSteps(HttpApplication.EventAcquireRequestState, steps);
    app.CreateEventExecutionSteps(HttpApplication.EventPostAcquireRequestState, steps);
    app.CreateEventExecutionSteps(HttpApplication.EventPreRequestHandlerExecute, steps);
    steps.Add(new HttpApplication.CallHandlerExecutionStep(app));
    app.CreateEventExecutionSteps(HttpApplication.EventPostRequestHandlerExecute, steps);
    app.CreateEventExecutionSteps(HttpApplication.EventReleaseRequestState, steps);
    app.CreateEventExecutionSteps(HttpApplication.EventPostReleaseRequestState, steps);
    steps.Add(new HttpApplication.CallFilterExecutionStep(app));
    app.CreateEventExecutionSteps(HttpApplication.EventUpdateRequestCache, steps);
    app.CreateEventExecutionSteps(HttpApplication.EventPostUpdateRequestCache, steps);
    this._endRequestStepIndex = steps.Count;
    app.CreateEventExecutionSteps(HttpApplication.EventEndRequest, steps);
    steps.Add(new HttpApplication.NoopExecutionStep());
    this._execSteps = new HttpApplication.IExecutionStep[steps.Count];
    steps.CopyTo(this._execSteps);
    this._resumeStepsWaitCallback = stepCallback;
}

     具體的管道請求事件步驟如下圖:


四、Asp物件的獲取原則

Application物件

       為當前 Web 請求獲取 HttpApplicationState 物件

public HttpApplicationState Application { get; }

Request物件


       獲取請求的頁的 HttpRequest 物件。

public HttpRequest Request { get; }


Response物件


        獲取與該 Page 物件關聯的 HttpResponse 物件。 該物件使您得以將 HTTP 響應資料傳送到客戶端,幷包含有關該響應的資訊。

public HttpResponse Response { get; }

Session物件


       獲取 ASP.NET 提供的當前 Session 物件。
       該屬性提供有關當前請求的會話的資訊。 為從 ASP.NET 應用程式請求頁或文件的每個使用者維護一個 Session 物件。 當用戶在應用程式中從一頁移動到另一頁時,儲存在 Session 物件中的變數不會被放棄;相反,只要使用者在應用程式中訪問頁,這些變數就將保持。

public virtual HttpSessionState Session { get; }

五、回顧


       說了這麼多其實都是由Asp.net執行機制引發的。剛開始我們從IIS架構著說,著重介紹了IIS內部的一些結構,然後圍繞該伺服器管理程式展開了一系列的論述,這些論述雖然很多都是理論知識,但對於我們深入學習Web應用程式來說卻有著十分重要的作用,幫助開發人員更好的開發Web應用程式打下基礎。

       學習有粗有細,對於一些基本的概念或者一些整體的知識點我們要進行粗略的理解,但對於在實際開發過程中要應用到的知識我們要進行細緻的掌握,這樣在應用時才不至於出錯,做到遊刃有餘。這也可以說是學習的一種全域性觀,對知識點有整體、粗略的把握,才能更細緻的運用知識,理論加實踐這才是學技術的最高境界。

       Asp.net和IIS內部執行互動過程我們已經講完,接下來將會著重從Web應用程式角度入手講解開發人員所需要的Asp.net知識。

相關推薦

ASP.NET--Asp.net執行機制

      上節中我們從Http請求在Asp.net中的執行過程進行了分析,但是對於真正核心的東西我們並沒有說明,那接下來我們將問題上拋,從底層類和物件的建立層面上來看Asp.net的執行機制。 三、Asp.net底層執行機制    1、理解HTTP.SYS      

ASP.NET--Asp.net執行機制

       很多Asp.net開發人員都有過Asp的背景,以至於我們開發程式的時候總是停留在“頁面”層次思考,也就是說我們常常會只考慮我們現在所做的系統是要完成什麼功能,是要做問卷調查網站還是個人網站,而很少在“請求級”思考,思考能不能通過編碼的方式來操作一個Http請

A1—JavaScript中的原型

js原型是什麽?想要了解這個問題,我們就必須要知道對象。對象根據w3cschool上的介紹:對象只是帶有屬性和方法的特殊數據類型。我們知道,數組是用來描述數據的。其實呢,對象也是用來描述數據的。只不過有一點點的區別,那就是數組的下標只能是數字。所以,數組最好只用來裝同樣意義的內容。比如說[1,2,3,4,5]

我的MongoDB學習

如果 自動 淺談 查詢 技術分享 刪除 insert 工作經歷 posit   上一篇簡單講了mongodb的安裝,mongo的windows服務安裝,這樣服務器重啟windows服務會自動重啟mongodb的server,然後我們就可以用客戶端去管理數據了。mongod

PHP面向物件程式設計

和一些面向物件的語言有所不同,PHP並不是一種純面向物件的語言,包PIP它支援面向物件的程式設計,並可以用於開發大型的商業程式。因此學好面向物件輸程對PHP程式設計師來說也是至關重要的。本章並針對面向物件程式設計在PIP語言中的使用進行詳細講解。 2.1 面向物件概述   面向物件是一種符

排序演算法的效率Java筆記

首先:咱也借用一下網上的那張XXX的圖,咯!在下面: 接下來,就是咱的驗證時間了(驗證什麼?當然是各種演算法的時間複雜度比較咯),沒什麼好說的了,直接上碼吧。 程式碼實現: import java.util.Arrays; public class SortSum

Android 事件分發機制

get touch 需要 傳遞 cimage android ges 常見 滑動 在上一篇文章中,淺談Android 事件分發機制(一),簡要分析了一下事件分發機制的原理,總結一下就是事件層層傳遞,直到被消費,原理看似簡單,但是在實際使用過程中,場景各不相同,復雜程度也就因

SQL 中的鎖餘額問題的處理

上次模擬了 SQL 中併發執行更新餘額的語句,出現餘額負數的問題:http://blog.csdn.net/closurer/article/details/54288628 現在說說它的解決方法。 事務要正確地執行,就需要【隔離性】這個基本要素。更新餘額的語句之所以會偏離

Linux PCI裝置驅動

我們在 淺談Linux PCI裝置驅動(一)中(以下簡稱 淺談(一) )介紹了PCI的配置暫存器組,而Linux PCI初始化就是使用了這些暫存器來進行的。後面我們會舉個例子來說明Linux PCI裝置驅動的主要工作內容(不是全部內容),這裡只做文字性的介紹而不會涉及具體程

4.ASP.NET全棧開發在MVC中使用服務端驗證

help alt 來講 測試 數據類型 throw 存在 數據 問題 首先聲明,這篇博文是完善.ASP.NET全棧開發之在MVC中使用服務端驗證 的,所以重復內容,我就不過多的闡述,很多問題都是在實踐中去發現,然後再去完善,這篇博文也一樣,建立在已閱 “.ASP.NET

ASP.NET Core MVC 和 EF Core 構建Web應用

work nal nta 多個 包括 catch web 應用 自動 選項卡 本節學習如何執行基本的 CRUD (創建、 讀取、 更新、 刪除) 操作。 自定義“詳細信息”頁 學生索引頁的基架代碼省略了 Enrollments 屬性,因為該屬性包含一個集合。 在“詳細信息”

ASP.NET Core MVC 和 Entity Framework Core 連線mysql

EF Core 開啟negut管理器 安裝如下的包 新增Models類 新增Students using System; using System.Collections.Generic; using System.Linq; using System

ASP.NET Core 打造一個簡單的圖書館管理系統Code First 多對多關係的建立

前言: 本系列文章主要為我之前所學知識的一次微小的實踐,以我學校圖書館管理系統為雛形所作。 本系列文章主要參考資料: 微軟文件:https://docs.microsoft.com/zh-cn/aspnet/core/getting-started/?view=aspnetcore-2.1&ta

ASP.NET Core 打造一個簡單的圖書館管理系統Code First 多對多關系的建立

兩個 microsoft 創建 int lan rar -c bsp dem 前言: 本系列文章主要為我之前所學知識的一次微小的實踐,以我學校圖書館管理系統為雛形所作。 本系列文章主要參考資料: 微軟文檔:https://docs.microsoft.com/zh-c

腳本化css方塊運動函數

-c containe cti var eight lan abs print clas 我們可以寫一個讓小方塊運動的函數: 1 div#demo { 2 width: 100px; 3 height: 100; 4 p

【SSH】一步步學習Hibernate框架:關於持久化

stc localhost 對象 schema hbm.xml java let pass [] 在不引用不論什麽框架下,我們會通過平庸的代碼不停的對數據庫進行操作,產生了非常多冗余的可是又有規律的底層代碼,這樣頻繁的操作數據庫和大量的底層代碼的反復

分布式事務

back 微服務 目的 light ber message values 及其 環境 現今互聯網界,分布式系統和微服務架構盛行。一個簡單操作,在服務端非常可能是由多個服務和數據庫實例協同完成的。在一致性要求較高的場景下,多個獨立操作之間的一致性問題顯得格外棘手。基

.NET垃圾回收機制

sel 結點 是個 pac public 良好的 方案 環境 哪裏 一、GC的必要性   1、應用程序對資源操作,通常簡單分為以下幾個步驟:為對應的資源分配內存 → 初始化內存 → 使用資源 → 清理資源 → 釋放內存。   2、應用程序對資源(內存使用)管理的方式,常見的

分詞算法1分詞中的基本問題

最短 hub 好的 說明 可能 漢語 等等 http ring [TOC] 前言 分詞或說切詞是自然語言處理中一個經典且基礎的問題,在平時的工作中也反復的接觸到分詞問題,用到了不同的模型,不同的方法應用在各個領域中,所以想對分詞問題做一個系統的梳理。大多數分詞問題主要是針對

協方差矩陣

但是 資料 sample 可能 tlab 原來 data- 一個 處理 原文地址:http://pinkyjie.com/2010/08/31/covariance/ 今天看論文的時候又看到了協方差矩陣這個破東西,以前看模式分類的時候就特困擾,沒想到現在還是搞不清楚,索性開