一张图理清ASP.NET Core启动流程

引用:

1. 引言

对于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.NET Core应用程序的启动主要包含三个步骤:

  1. CreateDefaultBuilder():创建IWebHostBuilder
  2. Build()IWebHostBuilder负责创建IWebHost
  3. Run():启动IWebHost

所以,ASP.NET Core应用的启动本质上是启动作为宿主的WebHost对象。
其主要涉及到两个关键对象IWebHostBuilderIWebHost,它们的内部实现是ASP.NET Core应用的核心所在。下面我们就结合源码并梳理调用堆栈来一探究竟!

2. 宿主构造器:IWebHostBuilder

在启动IWebHost宿主之前,我们需要完成对IWebHost的创建和配置。而这一项工作需要借助IWebHostBuilder对象来完成的,ASP.NET Core中提供了默认实现WebHostBuilder。而WebHostBuilder是由WebHost的同名工具类(Microsoft.AspNetCore命名空间下)中的CreateDefaultBuilder方法创建的。

CreateDefaultBuilder()调用堆栈

从上图中我们可以看出CreateDefaultBuilder()方法主要干了六件大事:

  1. UseKestrel:使用Kestrel作为Web server
  2. UseContentRoot:指定Web host使用的content
    root(内容根目录),比如Views。默认为当前应用程序根目录。
  3. ConfigureAppConfiguration:设置当前应用程序配置。主要是读取 appsettinggs.json配置文件、开发环境中配置的UserSecrets、添加环境变量和命令行参数 。
  4. ConfigureLogging:读取配置文件中的Logging节点,配置日志系统。
  5. UseIISIntegration:使用IISIntegration 中间件。
  6. UseDefaultServiceProvider:设置默认的依赖注入容器。

创建完毕WebHostBuilder后,通过调用UseStartup()来指定启动类,来为后续服务的注册及中间件的注册提供入口。

3. 宿主:IWebHost

在ASP.Net Core中定义了IWebHost用来表示Web应用的宿主,并提供了一个默认实现WebHost。宿主的创建是通过调用IWebHostBuilderBuild()方法来完成的。那该方法主要做了哪些事情呢,我们来看下面这张【ASP.NET Core启动流程调用堆栈】中的黄色边框部分:

ASP.NET Core启动流程调用堆栈

其核心主要在于WebHost的创建,又可以划分为三个部分:

  1. 构建依赖注入容器,初始通用服务的注册:BuildCommonService();
  2. 实例化WebHostvar host = new WebHost(...);
  3. 初始化WebHost,也就是构建由中间件组成的请求处理管道:host.Initialize();

3.1. 注册初始通用服务

BuildBuildCommonService方法主要做了两件事:

  1. 查找HostingStartupAttribute特性以应用其他程序集中的启动配置
  2. 注册通用服务
  3. 若配置了启动程序集,则发现并以IStartup类型注入到IOC容器中

3.2. 创建IWebHost

public IWebHost Build()
{
    //省略部分代码

    var host = new WebHost(
        applicationServices,
        hostingServiceProvider,
        _options,
        _config,
        hostingStartupErrors);
    }

    host.Initialize();

    return host;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

3.3. 构建请求处理管道

请求管道的构建,主要是中间件之间的衔接处理。

而请求处理管道的构建,又包含三个主要部分:

  1. 注册Startup中绑定的服务;
  2. 配置IServer
  3. 构建管道

请求管道的构建主要是借助于IApplicationBuilder,相关类图如下:

请求管道的构建

4. 启动WebHost

WebHost的启动主要分为两步:

  1. 再次确认请求管道正确创建
  2. 启动Server以监听请求
  3. 启动 HostedService

    启动WebHost调用堆栈

4.1. 确认请求管道的创建

从图中可以看出,第一步调用Initialize()方法主要是取保请求管道的正确创建。其内部主要是对BuildApplication()方法的调用,与我们上面所讲WebHost的构建环节具有相同的调用堆栈。而最终返回的正是由中间件衔接而成的RequestDelegate类型代表的请求管道。

4.2. 启动Server

我们先来看下类图:

IServer类图

从类图中我们可以看出IServer接口主要定义了一个只读的特性集合属性、一个启动和停止的方法声明。在创建宿主构造器IWebHostBuilder时我们通过调用UseKestrel()方法指定了使用KestrelServer作为默认的IServer实现。其方法申明中接收了一个IHttpApplication<TContext> application的参数,从命名来看,它代表一个Http应用程序,我们来看下具体的接口定义:

IHttpApplication类图

其主要定义了三个方法,第一个方法用来创建请求上下文;第二个方法用来处理请求;第三个方法用来释放上下文。而至于请求上下文,是用来携带请求和返回响应的核心参数,其贯穿与整个请求处理管道之中。ASP.NET Core中提供了默认的实现HostingApplication,其构造函数接收一个RequestDelegate _application(也就是链接中间件形成的处理管道)用来处理请求。

var httpContextFactory = _applicationServices.GetRequiredService<IHttpContextFactory>();
var hostingApp = new HostingApplication(_application, _logger, diagnosticSource, httpContextFactory);
  • 1
  • 2

4.3. 启动IHostedService

IHostedService接口用来定义后台任务,通过实现该接口并注册到Ioc容器中,它会随着ASP.NET Core 程序启动而启动,终止而终止。

5. 总结

结合源码,通过对ASP.NET Core运行调用堆栈的梳理,其启动流程的总体脉络一目了然,并且了解到主要的几个关键对象:

  1. 负责创建IWebHost的宿主构造器IWebHostBuilder
  2. 代表宿主的IWebHost接口
  3. 用于构建请求管道的IApplicationBuilder
  4. 中间件衔接而成的RequestDelegate
  5. 代表Web ServerIServer接口
  6. 贯穿请求处理管道的请求上下文HttpContext
  7. 可以用来注册后台服务的IHostedService接口

原文地址:https://www.cnblogs.com/nimorl/p/12424101.html

时间: 2024-11-05 13:39:04

一张图理清ASP.NET Core启动流程的相关文章

Taurus.MVC 支持Asp.Net Core 的过程

前言: 这些天,似乎.NET Core相关的新闻和文章经常在我眼前晃~~~ 昨天,微软又发布了.Core 2.1,又愰了一下,差点没亮瞎我的眼睛. 好吧,大概是上天给我的暗示,毕竟 CYQ.Data 早就支持上.Core了. 而 Taurus.MVC ,估计也闹委屈了,好吧,大慈大悲的怜见你一回,给你上ASP.NET Core支持吧. 又要一不小心就研究.NET Core了,这东西,只有家里的电脑有VS2017的环境,因此只能在家研究. 中间停停走走,思考了N天,最后用上三十几年的手速,敲足一天

Pro ASP.NET Core MVC 第6版 第二章(前半章)

目录 第二章 第一个MVC 应用程序 学习一个软件开发框架的最好方法是跳进他的内部并使用它.在本章,你将用ASP.NET Core MVC创建一个简单的数据登录应用.我将它一步一步地展示,以便你能看清楚怎样构建一个MVC 应用程序.为了让事情简单,我跳过了一些技术细节,但是不要担心,如果你是一个MVC的新手,你将会发现许多东西足够提起你的兴趣.因为我用的东西有些没做解释,所以我提供了一些参考以便你可以看到所有的细节的东西. 安装Visual Studio 要想根据本书实践的话,必须安装Visua

ASP.NET Core 2.0 : 五.服务是如何加载并运行的, Kestrel、配置与环境

"跨平台"后的ASP.Net Core是如何接收并处理请求的呢? 它的运行和处理机制和之前有什么不同? 本章从"宏观"到"微观"地看一下它的结构以及不同时期都干了些什么. 本章主要内容如下: ASP.NET Core 的运行机制: "宏观"的看一下Http请求的处理流程. ASP.NET Core 的配置与运行: 2倍放大后的ASP.NET Core Application, Kestrel服务器.启动与配置 ASP.NET

.net core 启动域名及端口配置

前两天转载一篇.net core 启动分析,由于发布时候一直纠结在默认5000端口上,所以好好研究了一下. 1.IIS集成 如果通过IIS当宿主的话,那这些都不是事情,强大的IIS可以帮助我们对站点的域名.端口等等等等的配置.至于如何在IIS上部署asp.net core的web应用,就不是这里的重点.大致简单的描述一下: 需要下载Net Core SDK 与 Server Hosting,下载地址https://www.microsoft.com/net/download 安装完查看.net

asp.net core 2.0 查缺补漏

asp.net core 2.0 一些有用有趣的设置. 面向(targeting)不同的.net版本: 打开asp.net core 2.0的项目文件: xxx.csproj, 这部分: <Project Sdk="Microsoft.NET.Sdk.Web"> <PropertyGroup> <TargetFramework>netcoreapp2.0</TargetFramework> </PropertyGroup> T

【视频】ASP.NET Core MVC 2.* 入门

比较初级的入门教程,网址在B站:https://www.bilibili.com/video/av33728783/ 内容如下: 1. ASP.NET Core 简介和开发工具 2. ASP.NET Core 启动相关的基础知识 3. 使用Nuget & NPM 安装,优化第三方库 4. 配置MVC和其它中间件 5. 环境和Tag Helpers 1 6. Tag Helpers 2 7. 配置参数和View Component 8. 发布 9. 部署到Ubuntu (Nginx, 监控, HT

观看杨老师(杨旭)Asp.Net Core MVC入门教程记录

观看杨老师(杨旭)Asp.Net Core MVC入门教程记录 ASP.NET Core MVC入门 Asp.Net Core启动和配置 Program类,Main方法 Startup类 依赖注入,IoC容器 生命周期 Transient:每次被请求都会创建新的实例 Scoped:每次Web请求会创建一个实例 Singleton:一旦被创建实例,就会一直使用这个实例,直到应用停止 依赖注入好处 不用去管生命周期 类型之间没有依赖 补充: ILogger:在Microsoft.Extensions

[ASP.NET Core 3.1]浏览器嗅探解决部分浏览器丢失Cookie问题

原文:[ASP.NET Core 3.1]浏览器嗅探解决部分浏览器丢失Cookie问题 今天的干货长驱直入,直奔主题 看了前文的同学们应该都知道,搜狗.360等浏览器在单点登录中反复重定向,最终失败报错. 原因在于,非Chrome80+浏览器不识别Cookie上的SameSite=none属性值,导致认证Cookie在后续请求中被抛弃. 截至2020/3/30号,非Chrome浏览器测试包含两种结果: case1:可设置cookie的samesite=none, 浏览器可读取该cookie ca

ASP.NET Core 2.0 : 七.一张图看透启动背后的秘密

为什么我们可以在Startup这个 “孤零零的” 类中配置依赖注入和管道? 它是什么时候被实例化并且调用的? 参数中的IServiceCollection services是怎么来的? 处理管道是怎么构建起来的? 启动过程中,系统“默默的”做了哪些准备工作? 上一篇文章讲了ASP.NET Core中的依赖注入(系列目录), 而它的配置是在Startup这个文件中的 ConfigureServices(IServiceCollection services) 方法,而且Startup这个类也没有继