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应用程序的启动主要包含三个步骤:
- 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()方法主要干了六件大事:
- 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启动流程调用堆栈】中的黄色边框部分:

其核心主要在于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;
}
3.3. 构建请求处理管道
请求管道的构建,主要是中间件之间的衔接处理。
而请求处理管道的构建,又包含三个主要部分:
- 注册Startup中绑定的服务;
- 配置IServer;
- 构建管道
请求管道的构建主要是借助于IApplicationBuilder,相关类图如下:
4. 启动WebHost
WebHost的启动主要分为两步:
- 再次确认请求管道正确创建
- 启动Server以监听请求
- 启动 HostedService

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

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

其主要定义了三个方法,第一个方法用来创建请求上下文;第二个方法用来处理请求;第三个方法用来释放上下文。而至于请求上下文,是用来携带请求和返回响应的核心参数,其贯穿与整个请求处理管道之中。ASP.NET Core中提供了默认的实现HostingApplication,其构造函数接收一个RequestDelegate _application(也就是链接中间件形成的处理管道)用来处理请求。
|
1
2
|
var httpContextFactory = _applicationServices.GetRequiredService<IHttpContextFactory>();
var hostingApp = new HostingApplication(_application, _logger, diagnosticSource, httpContextFactory);
|
4.3. 启动IHostedService
IHostedService接口用来定义后台任务,通过实现该接口并注册到Ioc容器中,它会随着ASP.NET Core 程序启动而启动,终止而终止。
5. 总结
结合源码,通过对ASP.NET Core运行调用堆栈的梳理,其启动流程的总体脉络一目了然,并且了解到主要的几个关键对象:
- 负责创建IWebHost的宿主构造器IWebHostBuilder
- 代表宿主的IWebHost接口
- 用于构建请求管道的IApplicationBuilder
- 中间件衔接而成的RequestDelegate
- 代表Web Server的IServer接口
- 贯穿请求处理管道的请求上下文HttpContext
- 可以用来注册后台服务的IHostedService接口
这一节就先从总体上对ASP.NET Core的运行原理有个基本的认识,后续我们再一一讲解这几个核心对象来加深理解。
原文地址:https://www.coderbusy.com/archives/877.html
ASP.NET Core启动流程的更多相关文章
- 一张图理清ASP.NET Core启动流程
1. 引言 对于ASP.NET Core应用程序来说,我们要记住非常重要的一点是:其本质上是一个独立的控制台应用,它并不是必需在IIS内部托管且并不需要IIS来启动运行(而这正是ASP.NET Cor ...
- Asp.net Core 启动流程分析
新建的.net core 程序启动本质上是一个控制台应用程序,所以它的入口在Main方法中,所以启动的开始时从Main方法开始. public class Program { public stati ...
- Asp.net Core启动流程讲解(四)
Asp.net Core内 DI(DependencyInjection)贯穿了项目的始终,要学习Asp.net Core就无法越过DI. 下面讲解一下DI在Asp.Net Core内的流程 asp. ...
- Asp.net core 启动流程
- asp.net core启动源码以及监听,到处理请求响应的过程
摘要 asp.net core发布至今已经将近6年了,很多人对于这一块还是有些陌生,或者说没接触过:接触过的,对于asp.net core整个启动过程,监听过程,以及请求过程,响应过程也是一知半解,可 ...
- ASP.NET CORE 启动过程及源码解读
在这个特殊的春节,大家想必都在家出不了们,远看已经到了回城里上班的日子,但是因为一只蝙蝠的原因导致我们无法回到工作岗位,大家可能有的在家远程办公,有些在家躺着看书,有的是在家打游戏:在这个特殊无聊的日 ...
- 聊聊asp.net core 授权流程
在上一篇 聊聊 asp.net core 认证和授权 中我们提到了认证和授权的基本概念,以及认证和授权的关系及他们之间的协同工作流程,在这篇文章中,我将通过分析asp.net core 3.1 授权流 ...
- ASP.NET Core 启动流程图
简洁描述: 一 WebHostBuilder.Build() =>1注入公共的实例 2创建WebHost实例 3注入自定义实例 4创建IServer 5添加中间件(_components集合 ...
- 深入探究ASP.NET Core Startup初始化
前言 Startup类相信大家都比较熟悉,在我们使用ASP.NET Core开发过程中经常用到的类,我们通常使用它进行IOC服务注册,配置中间件信息等.虽然它不是必须的,但是将这些操作统一在Start ...
随机推荐
- jmeter 常用插件
一.下载安装及使用 下载地址:https://jmeter-plugins.org/install/Install/ 安装:下载后文件为plugins-manager.jar格式,将其放入jmeter ...
- SCHED_FIFO与SCHED_OTHER调度机制
疑问 两个线程分别有不同的调度策略,一个SCHED_FIFO,一个SCHED_OTHER,按照之前的理解,SCHED_FIFO实时线程一定会占用CPU一直运行,导致SCHED_OTHER的普通线程得不 ...
- Main property in package.json defines package entry point
I know my project's dependencies are installed under node_modules directory. But when I do require(' ...
- 解决com.android.support版本冲突问题
原文:https://www.jianshu.com/p/0fe985a7e17e 项目中不同Module的support包版本冲突怎么办? 只需要将以下代码复制到每个模块的build.gradle( ...
- python笔记7 logging模块 hashlib模块 异常处理 datetime模块 shutil模块 xml模块(了解)
logging模块 日志就是记录一些信息,方便查询或者辅助开发 记录文件,显示屏幕 低配日志, 只能写入文件或者屏幕输出 屏幕输出 import logging logging.debug('调试模式 ...
- php接口数据安全解决方案(一)
前言 目录介绍 登录鉴权图 接口请求安全性校验整体流程图 代码展示 演示用户登录 演示获取用户信息 文章完整代码地址 后记 前言 目的: 1.实现前后端代码分离,分布式部署 2.利用token替代se ...
- “用户名不在 sudoers文件中,此事将被报告” 解决方案
第一次接触Docker是在CentOS上搭建的,没想到第一步就被弄懵了:执行sudo时提示“XXX 不在sudoers文件中,此事将被报告”. 这才刚开始就遇到个未知问题,于是上网找了下解决方法,嗨, ...
- Canvas恢复布局
package com.loaderman.customviewdemo; import android.content.Context; import android.graphics.Canvas ...
- MySQL数据库备份之xtrabackup工具使用
一.Xtrabackup备份介绍及原理 二.Xtrabackup的安装 1.在centos7上基于yum源安装percona-xtrabackup软件 [root@node7 ~]# yum -y i ...
- Python - Django - 添加作者
在 book_list.html 的页面下方加上 “添加作者” 的链接 <!DOCTYPE html> <html lang="en"> <head& ...