ASP.NET Core 的啓動和運行機制

ASP .NET Core 的運行機制

core web server

  1. Web Server: ASP.NET Core 提供兩種服務器可用, 分別是 Kestrel 和 HTTP.sys (Core 1.x 中被命名爲 WebListener),
    • Kestrel是一個跨平臺的Web服務器。
    • HTTP.sys只能用在Windows系統中.
  2. Internet: 當須要部署在Internal Network 中並須要 Kestrel 中沒有的功能(如 Windows 身份驗證)時,能夠選擇HTTP.sys。
  3. IIS、Apache、Nginx: Kestrel 能夠單獨使用 ,也能夠將其與反向代理服務器(如 IIS、Nginx 或 Apache)結合使用。 請求經這些服務器進行初步處理後轉發給Kestrel(即圖中虛線的可選流程).

ASP .NET Core 的啓動

core startup

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

    public static IWebHost BuildWebHost(string[] args) =>
        WebHost.CreateDefaultBuilder(args)
            .UseStartup<Startup>()
            .Build();
}
  1. Main: 程序的起點. ASP .NET Core 應用程序本質上是控制檯應用程序。
  2. CreateDefaultBuilder:建立並配置WebHostBuilder, 首先調用Create­DefaultBuilder( 如圖所示, 它是一系列配置的大綜合,下文作詳細介紹), 進行一系列配置。
  3. UseStartup: 指定Startup爲啓動配置文件. 在Startup中, 將進行兩個比較重要的工做, 服務的依賴注入和配置管道。
    1. ConfigureServices方法是註冊服務
    2. Configure方法是配置管道,用來具體指定如何處理每一個http請求的, 例如咱們可讓這個程序知道我使用mvc來處理http請求, 那就調用app.UseMvc()這個方法就行.
  4. BuildWebHost:生成WebHostBuilder並進行了一系列配置以後, 經過這個WebHostBuilder來Build出一個IWebHost。
  5. Run:調用IWebHost的Run方法使之開始運行。

Create­DefaultBuilderweb

public static IWebHostBuilder CreateDefaultBuilder(string[] args)
{
    var builder = new WebHostBuilder()
        .UseKestrel()
        .UseContentRoot(Directory.GetCurrentDirectory())
        .ConfigureAppConfiguration((hostingContext, config) =>
        {
            var env = hostingContext.HostingEnvironment;

            config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
                  .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true);

            if (env.IsDevelopment())
            {
                var appAssembly = Assembly.Load(new AssemblyName(env.ApplicationName));
                if (appAssembly != null)
                {
                    config.AddUserSecrets(appAssembly, optional: true);
                }
            }

            config.AddEnvironmentVariables();

            if (args != null)
            {
                config.AddCommandLine(args);
            }
        })
        .ConfigureLogging((hostingContext, logging) =>
        {
            logging.AddConfiguration(hostingContext.Configuration.GetSection("Logging"));
            logging.AddConsole();
            logging.AddDebug();
        })
        .UseIISIntegration()
        .UseDefaultServiceProvider((context, options) =>
        {
            options.ValidateScopes = context.HostingEnvironment.IsDevelopment();
        });

    return builder;
}
  • UseKestrel 指定服務器使用 Kestrel,若使用HttpSys,需使用UseHttpSys。
  • UseContentRoot 指定根目錄
  • ConfigureAppConfiguration 讀取配置文件
  • ConfigureLogging 配置日誌處理程序
  • UseIISIntegration 將應用程序配置爲在 IIS 中運行。若是應用程序沒有使用 IIS 做爲反向代理,那麼 UseIISIntegration 不會有任何效果。所以,即便應用程序在非 IIS 方案中運行,也能夠安全調用這種方法。
  • UseDefaultServiceProvider 設置默認的依賴注入容器。

ASP .NET Core 的管道和中間件

請求管道: 那些處理http requests並返回responses的代碼組成了request pipeline(請求管道).json

中間件: 咱們可使用一些程序來配置請求管道(request pipeline)以便處理requests和responses. 好比處理驗證(authentication)的程序, MVC自己就是個中間件(middleware).安全

當接收到一個請求時,請求會交給中間件構成的中間件管道進行處理,管道就是多箇中間件構成,請求從一箇中間件的一端進入,從中間件的另外一端出來,每一箇中間件均可以對HttpContext請求開始和結束進行處理.服務器

Middleware

本身寫一箇中間件測試下:mvc

  1. 經過約定方法實現:app

    public class Floor1Middleware
    {
        private readonly RequestDelegate _next;
    
        public Floor1Middleware(RequestDelegate next)
        {
            _next = next;
        }
    
        public async Task InvokeAsync(HttpContext context)
        {
            Console.WriteLine("Floor1Middleware In");
            //Do Something
            //To FloorTwoMiddleware
            await _next(context);
            //Do Something
            Console.WriteLine("Floor1Middleware Out");
        }
    }

    添加擴展方法:async

    public static class Floor1MiddlewareExtensions
    {
        public static IApplicationBuilder UseFloor1Middleware(this IApplicationBuilder builder)
        {
            return builder.UseMiddleware<Floor1Middleware>();
        }
    }
  2. 經過 IMiddleware 實現ide

    public class Floor3Middleware : IMiddleware
    {
        public async Task InvokeAsync(HttpContext context, RequestDelegate next)
        {
            Console.WriteLine("Floor3Middleware In");
            //Do Something
            //To FloorTwoMiddleware
            await next(context);
            //Do Something
            Console.WriteLine("Floor3Middleware Out");
        }
    }
    public static class MiddlewareExtensions
    {
        public static IApplicationBuilder UseFloor3Middleware(
            this IApplicationBuilder builder)
        {
            return builder.UseMiddleware<Floor3Middleware>();
        }
    }
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddTransient<Floor3Middleware>();
    
        services.AddMvc();
    }
  3. 也能夠用簡要的寫法,直接在Startup的Configure方法中這樣寫:測試

    app.Use(async (context, next) =>
    {
        Console.WriteLine("Floor2Middleware In");
    
        await next.Invoke();
    
        Console.WriteLine("Floor2Middleware Out");
    });
  4. 測試中間件:

    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        app.UseFloor1Middleware();
    
        app.Use(async (context, next) =>
        {
            Console.WriteLine("Floor2Middleware In");
    
            await next.Invoke();
    
            Console.WriteLine("Floor2Middleware Out");
        });
    
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseExceptionHandler("/Home/Error");
        }
    
        app.UseStaticFiles();
        app.UseCookiePolicy();
    
        app.UseMvc(routes =>
        {
            routes.MapRoute(
                name: "default",
                template: "{controller=Home}/{action=Index}/{id?}");
        });
    }

    運行查看輸出爲:

    DIDemo> Floor1Middleware In
    DIDemo> Floor2Middleware In
    DIDemo> Floor3Middleware In
    DIDemo> info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
    DIDemo>       Route matched with {action = "Index", controller = "Home"}. Executing action DIDemo.Controllers.HomeController.Index (DIDemo)
    DIDemo> info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
    DIDemo>       Executing action method DIDemo.Controllers.HomeController.Index (DIDemo) - Validation state: Valid
    DIDemo> info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
    DIDemo>       Executed action method DIDemo.Controllers.HomeController.Index (DIDemo), returned result Microsoft.AspNetCore.Mvc.ViewResult in 0.1167ms.
    DIDemo> info: Microsoft.AspNetCore.Mvc.ViewFeatures.ViewResultExecutor[1]
    DIDemo>       Executing ViewResult, running view Index.
    DIDemo> info: Microsoft.AspNetCore.Mvc.ViewFeatures.ViewResultExecutor[4]
    DIDemo>       Executed ViewResult - view Index executed in 3.3508ms.
    DIDemo> info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
    DIDemo>       Executed action DIDemo.Controllers.HomeController.Index (DIDemo) in 9.5638ms
    DIDemo> Floor3Middleware Out
    DIDemo> Floor2Middleware Out
    DIDemo> Floor1Middleware Out

參考

相關文章
相關標籤/搜索