引用:
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
应用程序的启动主要包含三个步骤:
CreateDefaultBuilder()
:创建IWebHostBuilder
Build()
:IWebHostBuilder
负责创建IWebHost
Run()
:启动IWebHost
所以,ASP.NET Core
应用的启动本质上是启动作为宿主的WebHost
对象。
其主要涉及到两个关键对象IWebHostBuilder
和IWebHost
,它们的内部实现是ASP.NET Core
应用的核心所在。下面我们就结合源码并梳理调用堆栈来一探究竟!
2. 宿主构造器:IWebHostBuilder
在启动IWebHost
宿主之前,我们需要完成对IWebHost的创建和配置。而这一项工作需要借助IWebHostBuilder
对象来完成的,ASP.NET Core
中提供了默认实现WebHostBuilder
。而WebHostBuilder
是由WebHost
的同名工具类(Microsoft.AspNetCore
命名空间下)中的CreateDefaultBuilder
方法创建的。CreateDefaultBuilder()
调用堆栈
从上图中我们可以看出CreateDefaultBuilder()
方法主要干了六件大事:
UseKestrel
:使用Kestrel
作为Web server
。UseContentRoot
:指定Web host使用的content
root(内容根目录),比如Views。默认为当前应用程序根目录。ConfigureAppConfiguration
:设置当前应用程序配置。主要是读取appsettinggs.json
配置文件、开发环境中配置的UserSecrets
、添加环境变量和命令行参数 。ConfigureLogging
:读取配置文件中的Logging节点,配置日志系统。UseIISIntegration
:使用IISIntegration
中间件。UseDefaultServiceProvider
:设置默认的依赖注入容器。
创建完毕WebHostBuilder
后,通过调用UseStartup()
来指定启动类,来为后续服务的注册及中间件的注册提供入口。
3. 宿主:IWebHost
在ASP.Net Core中定义了IWebHost
用来表示Web
应用的宿主,并提供了一个默认实现WebHost
。宿主的创建是通过调用IWebHostBuilder
的Build()
方法来完成的。那该方法主要做了哪些事情呢,我们来看下面这张【ASP.NET Core启动流程调用堆栈】中的黄色边框部分:
ASP.NET Core启动流程调用堆栈
其核心主要在于WebHost
的创建,又可以划分为三个部分:
- 构建依赖注入容器,初始通用服务的注册:
BuildCommonService();
- 实例化
WebHost
:var host = new WebHost(...);
- 初始化
WebHost
,也就是构建由中间件组成的请求处理管道:host.Initialize();
3.1. 注册初始通用服务
BuildBuildCommonService
方法主要做了两件事:
- 查找
HostingStartupAttribute
特性以应用其他程序集中的启动配置 - 注册通用服务
- 若配置了启动程序集,则发现并以
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. 构建请求处理管道
请求管道的构建,主要是中间件之间的衔接处理。
而请求处理管道的构建,又包含三个主要部分:
- 注册
Startup
中绑定的服务; - 配置
IServer
; - 构建管道
请求管道的构建主要是借助于IApplicationBuilder
,相关类图如下:
请求管道的构建
4. 启动WebHost
WebHost
的启动主要分为两步:
- 再次确认请求管道正确创建
- 启动
Server
以监听请求 - 启动
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
运行调用堆栈的梳理,其启动流程的总体脉络一目了然,并且了解到主要的几个关键对象:
- 负责创建
IWebHost
的宿主构造器IWebHostBuilder
- 代表宿主的
IWebHost
接口 - 用于构建请求管道的
IApplicationBuilder
- 中间件衔接而成的
RequestDelegate
- 代表
Web Server
的IServer
接口 - 贯穿请求处理管道的请求上下文
HttpContext
- 可以用来注册后台服务的
IHostedService
接口
原文地址:https://www.cnblogs.com/nimorl/p/12424101.html