.NET CORE学习笔记系列(5)——ASP.NET CORE的运行原理解析
一、概述
在ASP.NET Core之前,ASP.NET Framework应用程序由IIS加载。Web应用程序的入口点由InetMgr.exe创建并调用托管,初始化过程中触发HttpApplication.Application_Start()事件。开发人员第一次执行代码的机会是处理Application_StartGlobal.asax中的事件。在ASP.NET Core中,Global.asax文件不再可用,已被新的初始化过程替代。
二、宿主
ASP.NET Core应用程序其本质上是一个独立的控制台应用,是在.NET Core 控制台程序下调用特定的库,它并不是必需在 IIS内部托管且并不需要IIS来启动运行(而这正是ASP.NET Core跨平台的基石)。ASP.NET Core应用程序拥有一个内置的 Self-Hosted(自托管)的Web Server(Kestrel服务器),用来处理外部请求。 不管是托管还是自托管,都离不开Host(宿主)。在ASP.NET Core应用中通过配置并启动一个Host来完成应用程序的启动和其生命周期的管理。 而Host的主要的职责就是Web Server的配置和Pilpeline(请求处理管道)的构建。
既然提到了宿主,下面就详细解释一下:
什么是宿主?
ASP.NET Core应用程序需要在宿主中执行,一个宿主必须实现 IWebHost
接口,该接口暴露了功能和服务的集合,以及一个 Start
方法。宿主通常使用 WebHostBuilder
的实例来创建,该实例构建并返回一个 WebHost
实例。 WebHost
引用一个将用于处理请求的服务器Kestrel。
宿主和服务器有什么不同?
宿主负责应用程序启动和生命周期的管理。服务器Kestrel负责接受HTTP请求。宿主的部分职责还包括确保应用程序服务和服务器Kestrel可用并正确配置。你可以把宿主看作是服务器Kestrel的包装。宿主引用了Kestrel服务器接收HTTP请求;服务器并不知道它的宿主。
所有的ASP.NET托管库都是从Program
开始执行,而不是由IIS托管。
public class Program { /// 创建宿主的步骤 /// ASP.NET Core应用程序的启动主要包含三个步骤: /// CreateDefaultBuilder():创建IWebHostBuilder /// Build():IWebHostBuilder负责创建IWebHost /// Run():启动IWebHost public static void Main(string[] args) { CreateWebHostBuilder(args).Build().Run(); } public static IWebHostBuilder CreateWebHostBuilder(string[] args) => WebHost.CreateDefaultBuilder(args) .UseStartup<Startup>();// 调用Startup.cs类下的Configure 和 ConfigureServices }
以上是Program
类中Main
方法的示例代码,Main
方法负责初始化Host宿主,调用Startup和执行应用程序。宿主将调用Startup
类下面的Configure
和ConfigureServices
方法。
三、WebHostBuild
WebHostBuild 用来构建 WebHost ,也是我们最先接触的一个类,它提供了如下方法:
1、ConfigureAppConfiguration
Configuration 在 ASP.NET Core 进行了全新的设计,使其更加灵活简洁,可以支持多种数据源。在 ASP.NET Core 1.x 中,我们是在Startup
的构造函数中配置各种数据源的,而在 ASP.NET Core 2.0 中则移动了到Program
中,这样能与控制台应用程序保持一致:
public static class WebHostBuilderExtensions { public static IWebHostBuilder ConfigureAppConfiguration(this IWebHostBuilder hostBuilder, Action<IConfigurationBuilder> configureDelegate) { return hostBuilder.ConfigureAppConfiguration((context, builder) => configureDelegate(builder)); } } public class WebHostBuilder : IWebHostBuilder { private List<Action<WebHostBuilderContext, IConfigurationBuilder>> _configureAppConfigurationBuilderDelegates; public IWebHostBuilder ConfigureAppConfiguration(Action<WebHostBuilderContext, IConfigurationBuilder> configureDelegate) { if (configureDelegate == null) { throw new ArgumentNullException(nameof(configureDelegate)); } _configureAppConfigurationBuilderDelegates.Add(configureDelegate); return this; } }
而_configureAppConfigurationBuilderDelegates
委托会在 WebHostBuilder 的Build
方法中执行,生成 IConfiguration 对象并以单例的形式注册到 DI 系统中, 我们可以在Startup
以及应用程序的任何地方,通过 DI 系统来获取到。在CreateDefaultBuilder
中会通过该方法来添加appsettinggs.json
等基本配置的配置源。
2、UseSetting
UseSetting 是一个非常重要的方法,它用来配置 WebHost 中的 IConfiguration 对象。需要注意与上面ConfigureAppConfiguration
的区别, WebHost 中的 Configuration 只限于在 WebHost 使用,并且我们不能配置它的数据源,它只会读取ASPNETCORE_
开头的环境变量:
private IConfiguration _config; public WebHostBuilder() { _config = new ConfigurationBuilder() .AddEnvironmentVariables(prefix: "ASPNETCORE_") .Build(); }
而我们比较熟悉的当前执行环境,也是通过该_config
来读取的,虽然我们不能配置它的数据源,但是它为我们提供了一个UseSetting
方法,为我们提供了一个设置_config
的机会:
public string GetSetting(string key) { return _config[key]; }
而我们通过UseSetting
设置的变量最终也会以MemoryConfigurationProvider
的形式添加到上面介绍的ConfigureAppConfiguration
所配置的IConfiguration
对象中。
3、UseStartup
UseStartup 这个我们都比较熟悉,它用来显式注册我们的Startup
类,可以使用泛性,Type , 和程序集名称三种方式来注册:
// 常用的方法 public static IWebHostBuilder UseStartup<TStartup>(this IWebHostBuilder hostBuilder) where TStartup : class { return hostBuilder.UseStartup(typeof(TStartup)); } // 通过指定的程序集来注册 Startup 类 public static IWebHostBuilder UseStartup(this IWebHostBuilder hostBuilder, string startupAssemblyName) { if (startupAssemblyName == null) { throw new ArgumentNullException(nameof(startupAssemblyName)); } return hostBuilder .UseSetting(WebHostDefaults.ApplicationKey, startupAssemblyName) .UseSetting(WebHostDefaults.StartupAssemblyKey, startupAssemblyName); } // 最终的 Startup 类注册方法,上面两种只是一种简写形式 public static IWebHostBuilder UseStartup(this IWebHostBuilder hostBuilder, Type startupType) { .... }
4、ConfigureLogging
ConfigureLogging 用来配置日志系统,在 ASP.NET Core 1.x 中是在Startup
类的Configure
方法中,通过ILoggerFactory
扩展来注册的,在 ASP.NET Core 中也变得更加简洁,并且统一通过 WebHostBuild 来配置:
public static class WebHostBuilderExtensions { public static IWebHostBuilder ConfigureLogging(this IWebHostBuilder hostBuilder, Action<ILoggingBuilder> configureLogging) { return hostBuilder.ConfigureServices(collection => collection.AddLogging(configureLogging)); } public static IWebHostBuilder ConfigureLogging(this IWebHostBuilder hostBuilder, Action<WebHostBuilderContext, ILoggingBuilder> configureLogging) { return hostBuilder.ConfigureServices((context, collection) => collection.AddLogging(builder => configureLogging(context, builder))); } }
AddLogging 是Microsoft.Extensions.Logging
提供的扩展方法。
四、 Starup文件配置
对于一个ASP.NET Core 程序而言,Startup
类是必须的。ASP.NET Core在程序启动时会从Program
类中开始执行,然后再找到UseStartup<Startup>
中找到配置的Startup
的类,如果不指定Startup
类会导致启动失败。
在Startup
中必须定义Configure
方法,而ConfigureServices
方法则是可选的,方法会在程序第一次启动时被调用,类似传统的ASP.NET MVC的路由和应用程序状态均可在Startup
中配置,也可以在此初始化所需中间件。
Configure
在ASP.NET Core 应用程序中Configure
方法用于指定中间件以什么样的形式响应HTTP请求。 Configure 方法是用来配置请求管道的,通常会在这里会注册一些中间件
public void Configure(IApplicationBuilder app, IHostingEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } else { app.UseExceptionHandler("/Home/Error"); app.UseHsts(); } app.UseHttpsRedirection(); app.UseStaticFiles();//中间件:允许应用程序提供静态资源 app.UseCookiePolicy(); app.UseMvc(routes => { routes.MapRoute( name: "default", template: "{controller=Home}/{action=Index}/{id?}"); });//中间件:将MVC添加到管道并允许配置路由 }
ASP.NET Core是通过对IApplicationBuilder进行扩展来构建中间件的, 上面代码中每个use扩展方法都是将中间件添加到请求管道。也可以给Configure
方法附加服务(如:IHostingEnvironment)这些服务在ConfigureServices
方法中被初始化。
用ASP.NET Core项目模板添加的应用程序,默认添加的几个中间件:
UseStaticFiles 允许应用程序提供静态资源。
UseMvc 将MVC添加到管道并允许配置路由。
ConfigureServices
ConfigureServices
方法是应用程序运行时将服务添加到容器中,用ASP.NET Core项目模板的时候默认会将MVC的服务添加到容器中。
public void ConfigureServices(IServiceCollection services){ services.AddMvc(); }
五、处理管道(中间件)
在ASP.NET Core应用程序中使用中间件,应用程序所做的任何事情(包括服务器中的静态文件)都是由中间件来完成的。没有任何中间件的应用程序在请求的出错时候简单返回404 Not Found
。中间件可以让您完全控制请求的处理方式,并且让您的应用程序更加精简。
当接收到一个请求时,请求会交给中间件构成的中间件管道进行处理,管道就是多个中间件构成,请求从一个中间件的一端进入,从中间件的另一端出来,每个中间件都可以对HttpContext
请求开始和结束进行处理:
参考
运行原理:https://blog.csdn.net/sD7O95O/article/details/78126384
宿主介绍:http://www.jkeabc.com/460935.html
WebHostBuild:https://blog.csdn.net/linux12a/article/details/77676127
中间件:https://www.cnblogs.com/vipyoumay/p/5640645.html
中间件请求管道的构成:https://blog.csdn.net/bieguolaia/article/details/77816445
.NET CORE学习笔记系列(5)——ASP.NET CORE的运行原理解析的更多相关文章
- .NET CORE学习笔记系列(4)——ASP.NET CORE 程序启用SSL
一.什么是SSL? 1.概念: SSL(Secure Sockets Layer 安全套接层),及其继任者传输层安全(Transport Layer Security,TLS)是为网络通信提供安全及数 ...
- .NET CORE学习笔记系列(3)——ASP.NET CORE多环境标识
在开发项目的过程当中,生产环境与调试环境的配置是不一样的.比如连接字符串. ASP .NET CORE 支持利用环境变量来动态配置 JSON 文件.ASP.NET Core 引用了一个特定的环境变量 ...
- .NET CORE学习笔记系列(1)——ASP.NET MVC Core 介绍和项目解读
ASP.NET MVC Core 项目文件夹解读 一.项目文件夹总览 1.1.Properties——launchSettings.json 启动配置文件,你可以在项目中“Properties”文件夹 ...
- ASP.NET Core 学习笔记 第一篇 ASP.NET Core初探
前言 因为工作原因博客断断续续更新,其实在很早以前就有想法做一套关于ASP.NET CORE整体学习度路线,整体来说国内的环境的.NET生态环境还是相对比较严峻的,但是干一行爱一行,还是希望更多人加入 ...
- .NET CORE学习笔记系列(2)——依赖注入[6]: .NET Core DI框架[编程体验]
原文https://www.cnblogs.com/artech/p/net-core-di-06.html 毫不夸张地说,整个ASP.NET Core框架是建立在一个依赖注入框架之上的,它在应用启动 ...
- .NET CORE学习笔记系列(2)——依赖注入【3】依赖注入模式
原文:https://www.cnblogs.com/artech/p/net-core-di-03.html IoC主要体现了这样一种设计思想:通过将一组通用流程的控制权从应用转移到框架中以实现对流 ...
- .NET CORE学习笔记系列(2)——依赖注入【1】控制反转IOC
原文:https://www.cnblogs.com/artech/p/net-core-di-01.html 一.流程控制的反转 IoC的全名Inverse of Control,翻译成中文就是“控 ...
- 学习ASP.NET Core Razor 编程系列五——Asp.Net Core Razor新建模板页面
学习ASP.NET Core Razor 编程系列目录 学习ASP.NET Core Razor 编程系列一 学习ASP.NET Core Razor 编程系列二——添加一个实体 学习ASP.NET ...
- .NET CORE学习笔记系列(2)——依赖注入[7]: .NET Core DI框架[服务注册]
原文https://www.cnblogs.com/artech/p/net-core-di-07.html 包含服务注册信息的IServiceCollection对象最终被用来创建作为DI容器的IS ...
随机推荐
- asp.net core系列 37 WebAPI 使用OpenAPI (swagger)中间件
一.概述 在使用Web API时,对于开发人员来说,了解其各种方法可能是一项挑战.在ASP.NET Core上,Web api 辅助工具介绍二个中间件,包括:Swashbuckle和NSwag .NE ...
- Python爬虫入门教程 28-100 虎嗅网文章数据抓取 pyspider
1. 虎嗅网文章数据----写在前面 今天继续使用pyspider爬取数据,很不幸,虎嗅资讯网被我选中了,网址为 https://www.huxiu.com/ 爬的就是它的资讯频道,本文章仅供学习交流 ...
- C#版(击败97.76%的提交) - Leetcode 557. 反转字符串中的单词 III - 题解
版权声明: 本文为博主Bravo Yeung(知乎UserName同名)的原创文章,欲转载请先私信获博主允许,转载时请附上网址 http://blog.csdn.net/lzuacm. Leetcod ...
- 【链表问题】打卡2:删除单链表的第 K个节点
前言 以专题的形式更新刷题贴,欢迎跟我一起学习刷题.每道题会提供简单的解答. 题目描述 在单链表中删除倒数第 K 个节点 要求 如果链表的长度为 N, 时间复杂度达到 O(N), 额外空间复杂度达到 ...
- 【WCF学习大全】
我的WCF之旅(1):创建一个简单的WCF程序 我的WCF之旅(2):Endpoint Overview 我的WCF之旅(3):在WCF中实现双向通信(Bi-directional Communica ...
- SmartSql = Dapper + MyBatis + Cache(Memory | Redis) + ZooKeeper + R/W Splitting + ......
SmartSql Why 拥抱 跨平台 DotNet Core,是时候了. 高性能.高生产力,超轻量级的ORM.156kb (Dapper:168kb) So SmartSql TargetFrame ...
- sysbench的框架实现介绍
sysbench是一个非常经典的综合性能测试工具,它支持CPU,IO,内存,尤其是数据库的性能测试.那它是怎么做到通用性的呢,总结一句话是大量运用了重载的方法. sysbench总体架构 sysben ...
- ASP.NET Core 2.1 : 十三.httpClient.GetAsync 报SSL错误的问题
不知什么时候 ,出现了这样的一个奇怪问题,简单的httpClient.GetAsync("xxxx")居然报错了.(ASP.NET Core 系列目录) 一.问题描述 把原来的程序 ...
- [零]java8 函数式编程入门官方文档中文版 java.util.stream 中文版 流处理的相关概念
前言 本文为java.util.stream 包文档的译文 极其个别部分可能为了更好理解,陈述略有改动,与原文几乎一致 原文可参考在线API文档 https://docs.oracle.com/jav ...
- java集合框架容器 java框架层级 继承图结构 集合框架的抽象类 集合框架主要实现类
本文关键词: java集合框架 框架设计理念 容器 继承层级结构 继承图 集合框架中的抽象类 主要的实现类 实现类特性 集合框架分类 集合框架并发包 并发实现类 什么是容器? 由一个或多个确 ...