主頁 > .NET開發 > ASP.NET CORE 啟動程序及原始碼解讀

ASP.NET CORE 啟動程序及原始碼解讀

2020-09-16 20:34:35 .NET開發

在這個特殊的春節,大家想必都在家出不了們,遠看已經到了回城里上班的日子,但是因為一只蝙蝠的原因導致我們無法回到作業崗位,大家可能有的在家遠程辦公,有些在家躺著看書,有的是在家打游戲;在這個特殊無聊的日志,我果斷從無聊的被窩中 開啟了流量共享wifi 來進行.net core 3.1 源代碼的解讀和學習,并且把學習到的東西分享給大家,

疑問

剛剛接觸ASP.NET CORE 專案的同學可能會有如下疑問:

  • ASP.NET CORE 專案的啟動程序是怎么樣的?
  • 為什么ASP.NET CORE專案可以在控制臺中運行啟動后變成了一個網站程式?

現在我這里使用.NETCORE 3.1 最新穩定發布版本來進行以上問題的決議,帶大家解決以上問題的疑惑,學習完大家可以對ASP.NETCORE 專案會有一個不一樣的理解和領悟.


啟動程序

剛剛接觸ASP.NET core 的同學們估計都會覺得和之前的ASP.NET 設計大不一樣,代碼風格也有很大的變化,以前的ASP.NET 是全家桶框架模式,里面包含了所有的實作,你用的到的用不到的都集成在里面;然而ASP.NET CORE 框架做了大的改變,以最小化抽象設計,通過擴展方法完成易用性擴展.

解讀過源代碼的同學們都可以發現大多api都是最小化單元抽象介面方式進行設計,其他復雜的方法api都是通過擴展方法進行擴展提供,這也是.NET Core 高效易擴展的一大優勢原因.

對于ASP.NET Core應用程式來說,我們要記住非常重要的一點是:其本質上是一個獨立的控制臺應用,它并不是必需在IIS內部托管且并不需要IIS來啟動運行(而這正是ASP.NET Core跨平臺的基石),ASP.NET Core應用程式擁有一個內置的Self-Hosted(自托管)Web Server(Web服務器),用來處理外部請求,

不管是托管還是自托管,都離不開Host(宿主),在ASP.NET Core應用中通過配置并啟動一個Host來完成應用程式的啟動和其生命周期的管理,而Host的主要的職責就是Web Server的配置和Pilpeline(請求處理管道)的構建,

我們現在來創建一個ASP.NETCORE WEB 專案 步驟如下

檔案-> 新建 -> 專案 -> 選擇ASP.Net Core Web應用程式 -> 選擇.NETCORE 3.1 框架 如圖:

2.png

創建專案后我們從Program 類中可以看到以下代碼:

public class Program
{
        public static void Main(string[] args)
        {
            CreateHostBuilder(args).Build().Run();
        }

        public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)//開啟一個默認的通用主機Host建造者
                .ConfigureWebHostDefaults(webBuilder =>
                {
                    // 從前綴為“ASPNETCORE” 環境變數加載WEB主機配置
                    // 默認是Kestrel 設定為web 服務器并對其進行默認配置, 支持iis集成
                    //注冊系統啟動所使用的組件,比如配置的組件,容器的組件等
                    webBuilder.UseStartup<Startup>();
                });
}

查看以上代碼可以發現 Main 方法中代碼很簡單 ,清晰可見

CreateHostBuilder(args) :方法創建了一個IHostBuilder 抽象物件,創建程序包含CreateDefaultBuilder(args) :開啟創建一個默認的通用宿主機Host建造者,再通過ConfigureWebHostDefaults()方法配置開啟默認的Kestrel 為默認的Web服務器并對其進行默認配置,并集成對iis的集成

Build() :負責創建IHost,看過源代碼的同學可以發現Build的程序 會配置各種東西,本身通過管道模式進行了一系列的默認或者自定義的配置以及服務注冊的構建(下面會詳細講解)

Run() :啟動IHost

所以,ASP.NET Core應用的啟動本質上是啟動作為宿主的Host物件,

其主要涉及到兩個關鍵物件IHostBuilderIHost,它們的內部實作是ASP.NET Core應用的核心所在,下面我們就結合原始碼并梳理呼叫堆疊來一探究竟!

源代碼詳細圖如下:

從上圖中我們可以看出CreateDefaultBuilder()方法主要干了五件大事:
  • UseContentRoot:指定Web host使用的content root(內容根目錄),比如Views,默認為當前應用程式根目錄,
  • ConfigureHostConfiguration :啟動時宿主機需要的環境變數等相關,支持命令列
  • ConfigureAppConfiguration:設定當前應用程式配置,主要是讀取 appsettinggs.json 組態檔、開發環境中配置的UserSecrets、添加環境變數和命令列引數 ,
  • ConfigureLogging:讀取組態檔中的Logging節點,配置日志系統,
  • UseDefaultServiceProvider:設定默認的依賴注入容器,
從圖中可以看出CreateDefaultBuilder 后呼叫了ConfigureWebHostDefaults 方法,該方法默認主要做了以下幾個事情
  • UseStaticWebAssets:靜態檔案環境的配置啟用
  • UseKestrel:開啟Kestrel為默認的web 服務器.
  • ConfigureServices:服務中間件的注冊,包含路由的中間件的注冊
  • UseIIS:對iis 集成的支持
  • UseStartup:程式Startup 啟動,該啟動類中可以注冊中間件、擴展第三方中間件,以及相關應用程式配置的處理等等操作
現在所有的配置都已經配置創建好了,接下來我們來看看Build 方法主要做了哪些不為人知的事情,先來看下源代碼
/// <summary>
        /// Run the given actions to initialize the host. This can only be called once.
        /// </summary>
        /// <returns>An initialized <see cref="IHost"/></returns>
        public IHost Build()
        {
            if (_hostBuilt)
            {
                throw new InvalidOperationException("Build can only be called once.");
            }
            _hostBuilt = true;

            BuildHostConfiguration();
            CreateHostingEnvironment();
            CreateHostBuilderContext();
            BuildAppConfiguration();
            CreateServiceProvider();

            return _appServices.GetRequiredService<IHost>();
        }

從代碼中可以發現有一個_hostBuilt 的變數,細心的同學可以發現該變數主要是用于控制是否build 過,所以這里可以大膽猜測只能build 一次該Host;現在看下源代碼決議圖:
3.1 IHost Build 流程.png

經過查看源代碼得到的執行結構如上,因此我把代碼改造成如下結構,

public class Program
{
        public static void Main(string[] args)
        {
            CreateHostBuilder(args).Build().Run();
        }

        public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)//開啟一個默認的通用主機Host建造者
                .ConfigureAppConfiguration(config => {
                    //注冊應用程式內所使用的組態檔,比如資料庫鏈接等等
                    Console.WriteLine("ConfigureAppConfiguration");
                })
                .ConfigureServices(service =>
                {
                    //注冊服務中間件等操作
                    Console.WriteLine("ConfigureServices");
                })
                .ConfigureHostConfiguration(builder => {
                    //啟動時需要的組件配置等,比如監聽的埠 url地址等
                   Console.WriteLine("ConfigureHostCOnfiguration");
                })
                .ConfigureWebHostDefaults(webBuilder =>
                {
                    webBuilder.UseStartup<Startup>();
                });
}

Startup 代碼如下:

public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
            Console.WriteLine("Startup ");
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            Console.WriteLine("ConfigureServices");
            services.AddControllersWithViews();
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            Console.WriteLine("Configure");
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/Home/Error");
                // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
                app.UseHsts();
            }
            app.UseHttpsRedirection();
            app.UseStaticFiles();

            app.UseRouting();

            app.UseAuthorization();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllerRoute(
                    name: "default",
                    pattern: "{controller=Home}/{action=Index}/{id?}");
            });
        }
    }
}

通過執行發現執行代碼順序正如我們源代碼的執行順序一致,執行順序如下圖:

3.png

為何通過控制臺命令運行后自動啟動了一個網站程式?

以前ASP.NET web專案是需要搭建在iis 中托管運行,但是ASP.NETCORE 專案可以直接通過命令列進行托管運行,運行后可以直接瀏覽器打開,你們有沒有考慮過為什么?,細心的同學查看專案屬性也會發現專案的輸出型別也是控制臺專案,如圖:

1.png

查看這圖,有沒有發現很神奇,為什么輸出型別竟然可以通過控制臺命令列進行啟動專案呢?

image.png

在上面的源代碼分析程序中可以發現啟動時會啟動一個Kestrel 服務器(ConfigureWebHostDefaults方法中會呼叫UseKestrel),所以命令后啟動一個控制臺應用程式后相當于啟動了一臺web服務器;下面簡要的概括下Kestrel 服務器的優勢:

  • Kestrel:Kestrel 是個精簡高效的 HttpServer,以包形式提供,自身不能單獨運行,

內部封裝了對 libuv 的呼叫,作為I/O底層,屏蔽各系統底層實作差異;有了Kestrel才能真正的實作跨平臺.
好了,想必同學們到這里已經對上面 兩個疑惑有了清晰的答案了,這里我拋出一個疑問,看了上面的代碼解讀,大家有沒有發現ASP.NET CORE 和ASP.NET 有了很大的不同,這是什么樣的設計改進呢?敬請期待下期我們一起來學習ASP.NET CORE 的牛逼的管道模型.

轉載請註明出處,本文鏈接:https://www.uj5u.com/net/59639.html

標籤:.NET Core

上一篇:Angular SPA基于Ocelot API網關與IdentityServer4的身份認證與授權(一)

下一篇:ASP.NET CORE 管道模型及中間件使用解讀

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • WebAPI簡介

    Web體系結構: 有三個核心:資源(resource),URL(統一資源識別符號)和表示 他們的關系是這樣的:一個資源由一個URL進行標識,HTTP客戶端使用URL定位資源,表示是從資源回傳資料,媒體型別是資源回傳的資料格式。 接下來我們說下HTTP. HTTP協議的系統是一種無狀態的方式,使用請求/ ......

    uj5u.com 2020-09-09 22:07:47 more
  • asp.net core 3.1 入口:Program.cs中的Main函式

    本文分析Program.cs 中Main()函式中代碼的運行順序分析asp.net core程式的啟動,重點不是剖析原始碼,而是理清程式開始時執行的順序。到呼叫了哪些實體,哪些法方。asp.net core 3.1 的程式入口在專案Program.cs檔案里,如下。ususing System; us ......

    uj5u.com 2020-09-09 22:07:49 more
  • asp.net網站作為websocket服務端的應用該如何寫

    最近被websocket的一個問題困擾了很久,有一個需求是在web網站中搭建websocket服務。客戶端通過網頁與服務器建立連接,然后服務器根據ip給客戶端網頁發送資訊。 其實,這個需求并不難,只是剛開始對websocket的內容不太了解。上網搜索了一下,有通過asp.net core 實作的、有 ......

    uj5u.com 2020-09-09 22:08:02 more
  • ASP.NET 開源匯入匯出庫Magicodes.IE Docker中使用

    Magicodes.IE在Docker中使用 更新歷史 2019.02.13 【Nuget】版本更新到2.0.2 【匯入】修復單列匯入的Bug,單元測驗“OneColumnImporter_Test”。問題見(https://github.com/dotnetcore/Magicodes.IE/is ......

    uj5u.com 2020-09-09 22:08:05 more
  • 在webform中使用ajax

    如果你用過Asp.net webform, 說明你也算是.NET 開發的老兵了。WEBform應該是2011 2013左右,當時還用visual studio 2005、 visual studio 2008。后來基本都用的是MVC。 如果是新開發的專案,估計沒人會用webform技術。但是有些舊版 ......

    uj5u.com 2020-09-09 22:08:50 more
  • iis添加asp.net網站,訪問提示:由于擴展配置問題而無法提供您請求的

    今天在iis服務器配置asp.net網站,遇到一個問題,記錄一下: 問題:由于擴展配置問題而無法提供您請求的頁面。如果該頁面是腳本,請添加處理程式。如果應下載檔案,請添加 MIME 映射。 WindowServer2012服務器,添加角色安裝完.netframework和iis之后,運行aspx頁面 ......

    uj5u.com 2020-09-09 22:10:00 more
  • WebAPI-處理架構

    帶著問題去思考,大家好! 問題1:HTTP請求和回傳相應的HTTP回應資訊之間發生了什么? 1:首先是最底層,托管層,位于WebAPI和底層HTTP堆疊之間 2:其次是 訊息處理程式管道層,這里比如日志和快取。OWIN的參考是將訊息處理程式管道的一些功能下移到堆疊下端的OWIN中間件了。 3:控制器處理 ......

    uj5u.com 2020-09-09 22:11:13 more
  • 微信門戶開發框架-使用指導說明書

    微信門戶應用管理系統,采用基于 MVC + Bootstrap + Ajax + Enterprise Library的技術路線,界面層采用Boostrap + Metronic組合的前端框架,資料訪問層支持Oracle、SQLServer、MySQL、PostgreSQL等資料庫。框架以MVC5,... ......

    uj5u.com 2020-09-09 22:15:18 more
  • WebAPI-HTTP編程模型

    帶著問題去思考,大家好!它是什么?它包含什么?它能干什么? 訊息 HTTP編程模型的核心就是訊息抽象,表示為:HttPRequestMessage,HttpResponseMessage.用于客戶端和服務端之間交換請求和回應訊息。 HttpMethod類包含了一組靜態屬性: private stat ......

    uj5u.com 2020-09-09 22:15:23 more
  • 部署WebApi隨筆

    一、跨域 NuGet參考Microsoft.AspNet.WebApi.Cors WebApiConfig.cs中配置: // Web API 配置和服務 config.EnableCors(new EnableCorsAttribute("*", "*", "*")); 二、清除默認回傳XML格式 ......

    uj5u.com 2020-09-09 22:15:48 more
最新发布
  • C#多執行緒學習(二) 如何操縱一個執行緒

    <a href="https://www.cnblogs.com/x-zhi/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/2943582/20220801082530.png" alt="" /></...

    uj5u.com 2023-04-19 09:17:20 more
  • C#多執行緒學習(二) 如何操縱一個執行緒

    C#多執行緒學習(二) 如何操縱一個執行緒 執行緒學習第一篇:C#多執行緒學習(一) 多執行緒的相關概念 下面我們就動手來創建一個執行緒,使用Thread類創建執行緒時,只需提供執行緒入口即可。(執行緒入口使程式知道該讓這個執行緒干什么事) 在C#中,執行緒入口是通過ThreadStart代理(delegate)來提供的 ......

    uj5u.com 2023-04-19 09:16:49 more
  • 記一次 .NET某醫療器械清洗系統 卡死分析

    <a href="https://www.cnblogs.com/huangxincheng/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/214741/20200614104537.png" alt="" /&g...

    uj5u.com 2023-04-18 08:39:04 more
  • 記一次 .NET某醫療器械清洗系統 卡死分析

    一:背景 1. 講故事 前段時間協助訓練營里的一位朋友分析了一個程式卡死的問題,回過頭來看這個案例比較經典,這篇稍微整理一下供后來者少踩坑吧。 二:WinDbg 分析 1. 為什么會卡死 因為是表單程式,理所當然就是看主執行緒此時正在做什么? 可以用 ~0s ; k 看一下便知。 0:000> k # ......

    uj5u.com 2023-04-18 08:33:10 more
  • SignalR, No Connection with that ID,IIS

    <a href="https://www.cnblogs.com/smartstar/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/u36196.jpg" alt="" /></a>...

    uj5u.com 2023-03-30 17:21:52 more
  • 一次對pool的誤用導致的.net頻繁gc的診斷分析

    <a href="https://www.cnblogs.com/dotnet-diagnostic/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/3115652/20230225090434.png" alt=""...

    uj5u.com 2023-03-28 10:15:33 more
  • 一次對pool的誤用導致的.net頻繁gc的診斷分析

    <a href="https://www.cnblogs.com/dotnet-diagnostic/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/3115652/20230225090434.png" alt=""...

    uj5u.com 2023-03-28 10:13:31 more
  • C#遍歷指定檔案夾中所有檔案的3種方法

    <a href="https://www.cnblogs.com/xbhp/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/957602/20230310105611.png" alt="" /></a&...

    uj5u.com 2023-03-27 14:46:55 more
  • C#/VB.NET:如何將PDF轉為PDF/A

    <a href="https://www.cnblogs.com/Carina-baby/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/2859233/20220427162558.png" alt="" />...

    uj5u.com 2023-03-27 14:46:35 more
  • 武裝你的WEBAPI-OData聚合查詢

    <a href="https://www.cnblogs.com/podolski/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/616093/20140323000327.png" alt="" /><...

    uj5u.com 2023-03-27 14:46:16 more