一张图理清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对象。
其主要涉及到两个关键对象IWebHostBuilder和IWebHost,它们的内部实现是ASP.NET Core应用的核心所在。下面我们就结合源码并梳理调用堆栈来一探究竟!

2. 宿主构造器:IWebHostBuilder

在启动IWebHost宿主之前,我们需要完成对IWebHost的创建和配置。而这一项工作需要借助IWebHostBuilder对象来完成的,ASP.NET Core中提供了默认实现WebHostBuilder。而WebHostBuilder是由WebHost的同名工具类(Microsoft.AspNetCore命名空间下)中的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。宿主的创建是通过调用IWebHostBuilder的Build()方法来完成的。那该方法主要做了哪些事情呢,我们来看下面这张【ASP.NET Core启动流程调用堆栈】中的黄色边框部分:

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

  1. 构建依赖注入容器,初始通用服务的注册:BuildCommonService();

  2. 实例化WebHost:var 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;
}

3.3. 构建请求处理管道

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

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

  1. 注册Startup中绑定的服务;

  2. 配置IServer;

  3. 构建管道

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

4. 启动WebHost

WebHost的启动主要分为两步:

  1. 再次确认请求管道正确创建

  2. 启动Server以监听请求

  3. 启动 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(也就是链接中间件形成的处理管道)用来处理请求。

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运行调用堆栈的梳理,其启动流程的总体脉络一目了然,并且了解到主要的几个关键对象:

  1. 负责创建IWebHost的宿主构造器IWebHostBuilder

  2. 代表宿主的IWebHost接口

  3. 用于构建请求管道的IApplicationBuilder

  4. 中间件衔接而成的RequestDelegate

  5. 代表Web Server的IServer接口

  6. 贯穿请求处理管道的请求上下文HttpContext

  7. 可以用来注册后台服务的IHostedService接口

这一节就先从总体上对ASP.NET Core的运行原理有个基本的认识,后续我们再一一讲解这几个核心对象来加深理解。

原文地址: http://www.cnblogs.com/sheng-jie/p/7640163.html 


.NET社区新闻,深度好文,微信中搜索dotNET跨平台或扫描二维码关注

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/323343.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ssl提高组周六备考赛【2018.10.20】

前言 er…竟然卡读入输出还不给快读qwq 成绩 有些dalao被老师拉去USACO了&#xff0c;所以没有 HJW应该去jzoj做题了 RankRankRankPersonPersonPersonScoreScoreScoreAAABBBCCC1112017myself2017myself2017myself2402402407070701001001007070702222017zyc2017zyc2017zyc1901…

DevOps之发布系统V1.0

一、发布系统架构 &#xff08;1&#xff09;普通发布 &#xff08;2&#xff09;微服务发布 二、子系统与功能模块 &#xff08;1&#xff09;代码仓库 github、gitlab、svn &#xff08;2&#xff09;构建机 jenkins、maven构建机、本地构建包 &#xff08;3&#xff0…

Nodejs安装及使用

现阶段nodejs我用的多的是它里面的npm js的各种库都可以用npm安装&#xff0c;十分方便&#xff0c;再也不用去网上找了 当然&#xff0c;主要还是github上面的很多项目都要用npm“解封” 那下面说下它的安装吧 进入官网 https://nodejs.org/en/ 它会自动检测你的电脑&#xf…

在ASP.NET Core上实施每个租户策略的数据库

不定时更新翻译系列&#xff0c;此系列更新毫无时间规律&#xff0c;文笔菜翻译菜求各位看官老爷们轻喷&#xff0c;如觉得我翻译有问题请挪步原博客地址 本博文翻译自&#xff1a; http://gunnarpeipman.com/2017/08/database-per-tenant/ 让我们继续使用ASP.NET Core web应用…

nssl1216-码灵鼠【数学】

正题 题目大意 一个序列 a01a_01a0​1 akaiaj(i,j∈[0..k−1])a_ka_ia_j(i,j\in[0..k-1])ak​ai​aj​(i,j∈[0..k−1]) i和j随机选取 求ana_nan​的期望值 解题思路 先打个表不难发现aii1a_ii1ai​i1 之后我们用数学归纳法开始证明 a0011a_0011a0​011 然后用等差序列之和计…

JS中typeof的用法

转载自 JS中typeof的用法 js是一门弱语言&#xff0c;它在声明变量时无需确定变量的类型&#xff0c;js在运行时会自动判断。那么如何判断一个变量的类型呢&#xff0c;js提供了typeof运算符&#xff0c;用来检测一个变量的类型。 1. typeof的语法 typeof是一个运算符&#x…

php动态网站

记得从五六月份就说要建一个可以注册登录的网站了&#xff0c;结果自己两个多月都没能建成&#xff0c;由于学习动态网站实在需要太多知识了&#xff0c;可以说我这几个月的时间都是花在网页上的&#xff0c;从刚开始的htmlcss 到后面的js&#xff0c;js花了太多太多时间&#…

从头编写 asp.net core 2.0 web api 基础框架 (2)

上一篇是: 从头编写 asp.net core 2.0 web api 基础框架 (1) Github源码地址是: https://github.com/solenovex/Building-asp.net-core-2-web-api-starter-template-from-scratch 本文讲的是里面的Step 2. 上一次, 我们使用asp.net core 2.0 建立了一个Empty project, 然后做了…

nssl1217-So many prefix?【KMP】

正题 题目大意 求长度为偶数的前缀在字符串SSS中出现的次数和。 解题思路 我们先不考虑长度为偶数的话&#xff0c;答案很好求。先求出KMP的next数组&#xff0c;然后numinumnexti1num_inum_{next_i}1numi​numnexti​​1。 之后num的和就是答案。 注:num数组表示前i个字符的…

js中toString()和String()区别详解

转载自 js中toString()和String()区别详解 我们知道String()与 .toString()都是可以转换为字符串类型&#xff0c;但是String()与 .toString()的还是有区别的 1、.toString()可以将所有的的数据都转换为字符串&#xff0c;但是要排除null 和 undefined 例如将false转为字符…

java实现上传网络图片到七牛云存储

大家好&#xff0c;我是雄雄。 前言 最近阳了&#xff0c;第二条杠红的发紫&#xff0c;真难受啊&#xff0c;但是吧&#xff0c;博客上有个bug&#xff0c;不解决感觉比阳了还难受。 话还是要从博客的图片显示不出来这里说起&#xff0c;当时做的时候&#xff0c;在发文章这…

【php】php对mysql的连接操作【mysql】

思路&#xff1a; 1、数据库做两个表单&#xff0c;一个是user用来记录用户的信息&#xff0c;方便登录与注册。另一个表单是chat&#xff0c;用来记录聊天内容。 2、用到的技术是ajax&#xff0c;网页及时交互数据&#xff0c;可以做到无刷新聊天。 遍历数据库表单 数据库连…

nssl1218-TRAVEL【SPFA】

正题 题目大意 n个图&#xff0c;有m条双向道路&#xff0c;每条道路有一个l和r。 求一条路径&#xff0c;使得路上最小的r和路上最大的l的差最大。 解题思路 我们考虑枚举l&#xff0c;然后用SPFA计算最大的r。然后这样会超时。 之后我们发现其实答案的l一定是某一条边的l&…

gRPC官方快速上手学习笔记(c#版)

上手前准备工作 支持操作系统&#xff1a;windows、OS X、Linux。实例采用.net、.net core sdk。 The .NET Core SDK command line tools. The .NET framework 4.5 (for OS X and Linux, the open source .NET Framework implementation, “Mono”, at version 4, is suitable…

JS中的加号+运算符详解

转载自 JS中的加号运算符详解 加号运算符 在 JavaScript 中&#xff0c;加法的规则其实很简单&#xff0c;只有两种情况: 把数字和数字相加把字符串和字符串相加 所有其他类型的值都会被自动转换成这两种类型的值。 为了能够弄明白这种隐式转换是如何进行的&#xff0c;我们…

ajax做聊天交互

本想学了几天ajax就可以弄一个类似于qq的网页聊天界面&#xff0c;发现自己想的还是太简单了。 有两个问题无法解决&#xff1a; 1、即使用ajax还是无法保证数据的及时交互&#xff0c;没有办法无时无刻刷新页面。现学的ajax还是依赖于点击事件&#xff0c;才能请求后台数据。 …

ssl提高组周三备考赛【2018.10.24】

前言 快乐题警告&#xff01; 成绩 RankRankRankPersonPersonPersonScoreScoreScoreAAABBBCCC1112017myself2017myself2017myself2102102101001001001001001001010102222017zyc2017zyc2017zyc1581581581001001001818184040403332017xxy2017xxy2017xxy157157157100100100272727…

spring cloud+dotnet core搭建微服务架构:Api网关(三)

前言 国庆假期&#xff0c;一直没有时间更新。 根据群里面的同学的提问&#xff0c;强烈推荐大家先熟悉下spring cloud。文章下面有纯洁大神的spring cloud系列。 上一章最后说了&#xff0c;因为服务是不对外暴露的&#xff0c;所以在外网要访问服务必须通过API网关来完成&…

java实现人脸识别源码【含测试效果图】——前期准备工作及访问提示

注意&#xff1a; 看完之后如有不懂&#xff0c;请看&#xff1a;关于人脸和指纹识别共同交流方案&#xff0c;也可以关注微信公众号&#xff1a;雄雄的小课堂&#xff0c;回复&#xff1a;人脸识别群获取群号&#xff0c;群内有直接可以运行的源码可供下载&#xff0c;人脸识…

JS原型链与instanceof底层原理

转载自 JS原型链与instanceof底层原理 一、问题&#xff1a; instanceof 可以判断一个引用是否属于某构造函数&#xff1b; 另外&#xff0c;还可以在继承关系中用来判断一个实例是否属于它的父类型。 老师说&#xff1a;instanceof的判断逻辑是&#xff1a; 从当前引用的…