ASP.NET Core 源碼解讀


ASP.NET Core WebApi 項目搭建
提前准備下載
  1. Vs 2019
  2. .Net Core SDK
一、新建一個.NET Core 項目
這里我選用Vs 創建,先選一個文件夾例如
 
可以通過可視化界面創建,也可以通過命令行創建
我這里選擇命令行創建
 
第一次打開C#時,會自動幫你下載 omnisharp和debugger,在線下載安裝需要等待安裝完成
二、項目介紹
先介紹查看源碼的方式F12
VS2019-工具-文本編輯器-C#-高級-勾選支持導航到反編譯
目前只開源了.net Core2.X,3.X的暫時還看不到
Program類
首先介紹Main方法入口,0個引用說明是被框架調用
  public class Program
    {
        public static void Main(string[] args)
        {
            CreateHostBuilder(args).Build().Run();
        }

        public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .ConfigureWebHostDefaults(webBuilder =>
                {
                    webBuilder.UseStartup<Startup>();
                });
    }
  1. 前期准備WebHostBuild()
CreateHostBuilder創建WebHost,默認配置
Host是一個靜態類,里面有一個 CreateDefaultBuilder方法,我們去看源碼
這里實例化了一個WebHostBuilder類進去看看
 private readonly HostingEnvironment _hostingEnvironment;
        private readonly List<Action<WebHostBuilderContext, IServiceCollection>> _configureServicesDelegates;
        private IConfiguration _config;
        private WebHostOptions _options;
        private WebHostBuilderContext _context;
        private bool _webHostBuilt;
        private List<Action<WebHostBuilderContext, IConfigurationBuilder>> _configureAppConfigurationBuilderDelegates;
        public WebHostBuilder()//默認構造函數
        {
            _hostingEnvironment = new HostingEnvironment();
            _configureServicesDelegates = new List<Action<WebHostBuilderContext, IServiceCollection>>();
            _configureAppConfigurationBuilderDelegates = new List<Action<WebHostBuilderContext, IConfigurationBuilder>>();
            _config = new ConfigurationBuilder().AddEnvironmentVariables("ASPNETCORE_").Build();
            if (string.IsNullOrEmpty(GetSetting(WebHostDefaults.EnvironmentKey)))
            {
                UseSetting(WebHostDefaults.EnvironmentKey, Environment.GetEnvironmentVariable("Hosting:Environment") ?? Environment.GetEnvironmentVariable("ASPNET_ENV"));
            }
            if (string.IsNullOrEmpty(GetSetting(WebHostDefaults.ServerUrlsKey)))
            {
                UseSetting(WebHostDefaults.ServerUrlsKey, Environment.GetEnvironmentVariable("ASPNETCORE_SERVER.URLS"));
            }
            _context = new WebHostBuilderContext
            {
                Configuration = _config
            }//
這里不就是實現依賴注入嗎(構造函數實例化對象)
WebHost前期需要准備默認配置,這些配置它需要用到一些參數和一些變量通過注入的方式。
它具體需要配置那些地方呢
1.UseContentRoot
 WebHostBuilder webHostBuilder = new WebHostBuilder();
if (string.IsNullOrEmpty(webHostBuilder.GetSetting(WebHostDefaults.ContentRootKey)))
{
    webHostBuilder.UseContentRoot(Directory.GetCurrentDirectory());
}
指定了Web主機所使用的內容、站點根目錄
因為前期就要將那些wwwroot靜態文件,靜態網頁、配置文件讀取到,所以先指定目錄
2.UseConfiguration
if (args != null)
{
     webHostBuilder.UseConfiguration(new ConfigurationBuilder().AddCommandLine(args).Build());
}
傳的控制台命令args就在這里執行
3.UseKestrel
webHostBuilder.UseKestrel(delegate (WebHostBuilderContext builderContext, KestrelServerOptions options)
{
   options.Configure(builderContext.Configuration.GetSection("Kestrel"));
}
配置Kestrel服務器
4.ConfigureAppConfiguration
ConfigureAppConfiguration(delegate (WebHostBuilderContext hostingContext, IConfigurationBuilder config)
{
    IHostingEnvironment hostingEnvironment = hostingContext.HostingEnvironment;
    config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true).AddJsonFile("appsettings." + hostingEnvironment.EnvironmentName + ".json", optional: true, reloadOnChange: true);
    if (hostingEnvironment.IsDevelopment())
        {
             Assembly assembly = Assembly.Load(new AssemblyName(hostingEnvironment.ApplicationName));
             if (assembly != null)
               {
                config.AddUserSecrets(assembly, optional: true);//在開發環境使用UserSecrets
              }
        }
                config.AddEnvironmentVariables();//自動獲取環境變量
                if (args != null)
                {
                    config.AddCommandLine(args);//命令行參數
                }
}

  

首先配置了appsettings.json,然后規定在開發環境使用UserSecrets,UserSecrets是個人的密鑰,項目中是不會推送至遠程倉庫,該怎么創建呢
5.ConfigureLogging
ConfigureLogging(delegate (WebHostBuilderContext hostingContext, ILoggingBuilder logging)
            {
                //添加服務的地方Logging配置
                logging.AddConfiguration(hostingContext.Configuration.GetSection("Logging"));
                logging.AddConsole();//控制台
                logging.AddDebug();//Debug
                logging.AddEventSourceLogger();//事件
            }
配置日志
6.ConfigureServices
ConfigureServices(delegate (WebHostBuilderContext hostingContext, IServiceCollection services)
                {
                    services.PostConfigure(delegate (HostFilteringOptions options)
                    {
                        if (options.AllowedHosts == null || options.AllowedHosts.Count == 0)
                        {
                            string[] array = hostingContext.Configuration["AllowedHosts"]?.Split(new char[1]
                            {
                                ';'
                            }, StringSplitOptions.RemoveEmptyEntries);
                            options.AllowedHosts = ((array != null && array.Length != 0) ? array : new string[1]
                            {
                                "*"
                            });
                        }
                    });
                    services.AddSingleton((IOptionsChangeTokenSource<HostFilteringOptions>)new ConfigurationChangeTokenSource<HostFilteringOptions>(hostingContext.Configuration));
                    services.AddTransient<IStartupFilter, HostFilteringStartupFilter>();
                }
ConfigureServices是Startup方法里面的,會自動把我們的一些服務進行默認配置,我們提前寫好的配置服務,在WebHostBuilder里面構建,進行服務注入。
最后返回一個WebHostBuilder,就完成構建了。
我們在默認配置的時候是默認不包含我們自己創建的Startup的服務,而是系統默認的服務。
public void ConfigureServices(IServiceCollection services)
        {
            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
        }
  1. Build()-構建
構建一個Microsoft.AspNetCore.Hosting,托管Web應用程序的WebHost,一個方法只會執行一次
  1. Run()-構啟動
發現run方法下面是一個異步方法
 public static void Run(this IWebHost host)
        {
            host.RunAsync().GetAwaiter().GetResult();
        }

        public static async Task RunAsync(this IWebHost host, CancellationToken token = default(CancellationToken))
        {
            if (token.CanBeCanceled)
            {
                await host.RunAsync(token, null);
                return;
            }
            ManualResetEventSlim done = new ManualResetEventSlim(initialState: false);
            using (CancellationTokenSource cts = new CancellationTokenSource())
            {
                AttachCtrlcSigtermShutdown(cts, done, host.Services.GetRequiredService<WebHostOptions>().SuppressStatusMessages ? string.Empty : "Application is shutting down...");
                try
                {
                    await host.RunAsync(cts.Token, "Application started. Press Ctrl+C to shut down.");
                }
                finally
                {
                    done.Set();
                }
            }
        }

        private static async Task RunAsync(this IWebHost host, CancellationToken token, string shutdownMessage)
        {
            using (host)
            {
                await host.StartAsync(token);
                IHostingEnvironment service = host.Services.GetService<IHostingEnvironment>();
                if (!host.Services.GetRequiredService<WebHostOptions>().SuppressStatusMessages)
                {
                    Console.WriteLine("Hosting environment: " + service.EnvironmentName);
                    Console.WriteLine("Content root path: " + service.ContentRootPath);
                    ICollection<string> collection = host.ServerFeatures.Get<IServerAddressesFeature>()?.Addresses;
                    if (collection != null)
                    {
                        foreach (string item in collection)
                        {
                            Console.WriteLine("Now listening on: " + item);
                        }
                    }
                    if (!string.IsNullOrEmpty(shutdownMessage))
                    {
                        Console.WriteLine(shutdownMessage);
                    }
                }
                await host.WaitForTokenShutdownAsync(token);
            }
        }
因此顯示以下信息
三、.Net Core進程內外托管
進程是指IIS Worker Process工作進程
啟動IIS運行.net Core項目可以在任務管理器中看到,結束項目運行進程消失
 
進程內托管就是指的這個
進程外托管就是dotnet.exe,打開網頁可以看到服務器
雙擊項目
AspNetCoreHostingModel配置了托管模式。InProcess指定進程內,OutProcess指定進程外
1. 當AspNetCoreHostingModel設置InProcess進程內托管,啟動IIS,任務管理器這時候有IIS Worker Process,網頁服務器顯示IIS
2.當AspNetCoreHostingModel設置InProcess進程內托管,啟動項目,任務管理器這時候沒有IIS Worker Process,網頁服務器顯示IIS
3. 當AspNetCoreHostingModel設置OutProcess進程外托管,啟動IIS,任務管理器這時候還是有IIS Worker Process,網頁服務器顯示Kestrel
4.當AspNetCoreHostingModel設置OutProcess進程外托管,啟動項目,任務管理器沒有IIS Worker Process,網頁服務器顯示Kestrel
這是怎么回事,怎么進程內外都會啟動IIS Worker Process,進程內外到底有什么區別
原因分析:藍色字體第1、3點進程內外的IIS服務都會啟動,不過啟動的作用確實不一樣的
1.進程內啟動IIS是當作服務器
2.進程外也啟動IIS,是Kestrel配合IIS,將IIS當作反向代理服務器使用,不是作為整個項目的應用服務器了
以前是請求通過IIS監聽,通過IIS托管代碼響應直接完成
ASP.NET Core不同的是 靠ASP.NET Core Module把HTTP請求轉發
IIS這個時候等同於Nginx反向代理,本身不再處理了
ASP.NET Core內置Kestrel服務器等價於IIS--Webserver
 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM