跟我一起学.NetCore之Asp.NetCore启动流程浅析
前言
一个Asp.NetCore项目,知道大概的启动流程是有必要的,比如后续遇见配置信息覆盖等相关问题时也大概知道是什么原因,了解原因之后,再去搜索引擎找答案,否则目标不明确,茫茫人海怎么会一下找到自己想要的,除非是“偶遇”;“偶遇”太难,一起浅析一个Asp.NetCore 项目的启动流程;
正文
先创建一个WebAPI项目,用的是.NetCore3.1,后续的项目例子都统一用.NetCore3.1,除非特殊说明;项目如下:
如上图所示,一个WebAPI项目启动方式本质也是一个控制台程序,程序入口都是从Main函数开始,就从里面方法看看大概都做了什么,其中择取几个方法源码简要说明主要功能,通过增加代码注释的方式(我觉得这样比较方便对应浏览),完整源代码从以下两个地址获取,通过Everything查找工具比较方便查询代码:
主项目地址:https://github.com/dotnet/aspnetcore/tree/v3.1.0
扩展项目地址:https://github.com/dotnet/extensions/releases/tag/v3.1.6
GitHub代码地址
1. Host.CreateDefaultBuilder方法
public static IHostBuilder CreateDefaultBuilder(string[] args)
{//实例化一个HostBuildervar builder = new HostBuilder();//设置根目录builder.UseContentRoot(Directory.GetCurrentDirectory());//设置 Host相关配置的配置源builder.ConfigureHostConfiguration(config =>{//从环境变量中获取,前缀名为DOTNET_config.AddEnvironmentVariables(prefix: "DOTNET_");//如果命令行中有参数,可从命令行中读取if (args != null){config.AddCommandLine(args);}});//设置应用程序配置的配置源builder.ConfigureAppConfiguration((hostingContext, config) =>{var env = hostingContext.HostingEnvironment;//根据运行环境加载不同的配置文件,并开启了热更新config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true).AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true);if (env.IsDevelopment() && !string.IsNullOrEmpty(env.ApplicationName)){var appAssembly = Assembly.Load(new AssemblyName(env.ApplicationName));if (appAssembly != null){config.AddUserSecrets(appAssembly, optional: true);}}//可从环境变量中获取config.AddEnvironmentVariables();//如果命令行中有参数,可从命令行中读取if (args != null){config.AddCommandLine(args);}})//配置日志显示.ConfigureLogging((hostingContext, logging) =>{//判断操作系统var isWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows);//如果是Windows系统,配置对应的显示级别//IMPORTANT: This needs to be added *before* configuration is loaded, this lets//the defaults be overridden by the configuration.if (isWindows){// Default the EventLogLoggerProvider to warning or abovelogging.AddFilter<EventLogLoggerProvider>(level => level >= LogLevel.Warning);}//获取配置文件中Logging 段相关的配置信息添加到日志配置中logging.AddConfiguration(hostingContext.Configuration.GetSection("Logging"));//在控制台输出,所以启动程序的时候就看见输出日志logging.AddConsole();//在Debug窗口输出logging.AddDebug();logging.AddEventSourceLogger();//如果是Windows系统,可以在系统日志中输出日志if (isWindows){// Add the EventLogLoggerProvider on windows machineslogging.AddEventLog();}})//使用默认的依赖注入容器.UseDefaultServiceProvider((context, options) =>{var isDevelopment = context.HostingEnvironment.IsDevelopment();options.ValidateScopes = isDevelopment;options.ValidateOnBuild = isDevelopment;});return builder;
}
2. ConfigureWebHostDefaults 方法
public static IHostBuilder ConfigureWebHostDefaults(this IHostBuilder builder, Action<IWebHostBuilder> configure)
{return builder.ConfigureWebHost(webHostBuilder =>{//指定是用的服务器及集成一些默认管道WebHost.ConfigureWebDefaults(webHostBuilder);//调用传入的委托,这里是外部指定Startup类做服务注册和管道配置configure(webHostBuilder);});
}
2.1 WebHost.ConfigureWebDefaults方法
internal static void ConfigureWebDefaults(IWebHostBuilder builder)
{builder.ConfigureAppConfiguration((ctx, cb) =>{if (ctx.HostingEnvironment.IsDevelopment()){//静态文件环境的配置启用StaticWebAssetsLoader.UseStaticWebAssets(ctx.HostingEnvironment, ctx.Configuration);}});//指定Kestrel作为默认的Web服务器builder.UseKestrel((builderContext, options) =>{options.Configure(builderContext.Configuration.GetSection("Kestrel"));})// 服务中间的注册,包含路的中间件注册.ConfigureServices((hostingContext, services) =>{// 针对配置节点AllowedHosts改变时的回调// Fallbackservices.PostConfigure<HostFilteringOptions>(options =>{if (options.AllowedHosts == null || options.AllowedHosts.Count == 0){// "AllowedHosts": "localhost;127.0.0.1;[::1]"var hosts = hostingContext.Configuration["AllowedHosts"]?.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries);// Fall back to "*" to disable.options.AllowedHosts = (hosts?.Length > 0 ? hosts : new[] { "*" });}});//对应配置改变时触发通知// Change notificationservices.AddSingleton<IOptionsChangeTokenSource<HostFilteringOptions>>(new ConfigurationChangeTokenSource<HostFilteringOptions>(hostingContext.Configuration));services.AddTransient<IStartupFilter, HostFilteringStartupFilter>();if (string.Equals("true", hostingContext.Configuration["ForwardedHeaders_Enabled"], StringComparison.OrdinalIgnoreCase)){services.Configure<ForwardedHeadersOptions>(options =>{options.ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;// Only loopback proxies are allowed by default. Clear that restriction because forwarders are// being enabled by explicit configuration.options.KnownNetworks.Clear();options.KnownProxies.Clear();});services.AddTransient<IStartupFilter, ForwardedHeadersStartupFilter>();}services.AddRouting();})//对使用IIS相关中间件.UseIIS().UseIISIntegration();
}
3. Build方法,其实这个方法就是根据之前配置构造出一个IHost对象
public IHost Build()
{if (_hostBuilt){throw new InvalidOperationException("Build can only be called once.");}_hostBuilt = true;//执行ConfigureHostConfiguration添加的一系列配置回调方法BuildHostConfiguration();//运行环境相关创建,如ApplicationName、EnvironmentName、ContentRootPath等CreateHostingEnvironment();//构建HostBuilderCreateHostBuilderContext();//执行ConfigureAppConfigureation添加的一系列配置回调方法BuildAppConfiguration();//注入默认服务如:IHost、ILogging等,执行ConfigureServices添加的一系列回调方法CreateServiceProvider();return _appServices.GetRequiredService<IHost>();
}
4. Run()方法,开启服务器,之后就可以进行请求了
综上几个关键方法,从其中Host这个关键词出现很多次,其实在Asp.Net Core应用中是通过配置并启动一个Host来完成应用程序的启动和生命周期的管理。而Host主要就是对Web Server的配置和请求处理管理的管理,简要流程如下图:
在整个启动流程中,返回的IHostBuilder中暴露配置和注入的相关接口,可用于自己定义扩展,接下来通过打印的方式来看看一下几个暴露方法的执行顺序,其实以上Build方法的时候已经明确了对应方法的顺序;
改造代码如下:
Startup方法中的三个方法也增加对应的打印,运行如下:
如上图,除了Startup中的ConfigureServices会跟随ConfigureWebHostDefaults改变以外,其他方法顺序都是固定。那这些方法主要作用都是什么呢?如下图:
图中Program.ConfigureServices和Startup.ConfigureServices的执行顺序会根据ConfigureWebHostDefaults的位置改变会交替变动;
总结
以上内容只是提取了其中比较关键的流程进行说明,并没有详细解析源代码,这里只是先浅析,后续再继续一起深究源代码;下一节说说依赖注入;
跟我一起学.NetCore之Asp.NetCore启动流程浅析相关推荐
- 跟我一起学.NetCore之Asp.NetCore中集成Autofac扩展
前言 前两节针对.NetCore自带的依赖注入进行简要概述,对于日常开发的需求应该是能满足了,那为什么还需要引入第三方依赖注入组件呢,这里就从自带的依赖注入来分析,有什么样的需求满足不了?主要归纳为以 ...
- ASP.NETCore学习记录(一)
ASP.NETCore学习记录(一) asp.net core介绍 Startup.cs ConfigureServices Configure 0. ASP.NETCore 介绍 ASP.N ...
- ASP.NETCore
0. ASP.NETCore 介绍 ASP.NETCore是一个新的开源和跨平台的框架,用于构建如Web应用.物联网(IoT)应用和移动后端应用等连接到互联网的基于云的现代应用程序.ASP.NET C ...
- Asp.NetCore轻松学-部署到 IIS 进行托管
前言 经过一段时间的学习,终于来到了部署服务这个环节,.NetCore 的部署方式非常的灵活多样,但是其万变不离其宗,所有的 Asp.NetCore 程序都基于端口的侦听,在部署的时候仅需要配置侦听地 ...
- ASP.netcore MVC钉钉H5微应用(一)准备工作
本文是我在做ASP.netcore MVC钉钉H5微应用的第一章,准备工作 首先,进入钉钉开发平台,需要自己在钉钉上创建一个工作室,然后申请成为开发者,并创建一个H5微应用 在H5微应用里填写需要的信 ...
- Asp.NetCore MVC Web 应用
Asp.NetCore MVC 与 普通的MVC 基本一致, 只是代码结构稍有改动 一.创建项目 1. 2. 3. 项目结构 二. 构建数据模型 1. Startup类中配置EF Core MySql ...
- ASP.NETCore微服务(七)——【docker部署linux上线】(ECS+linux+docker+API上线部分)
ASP.NETCore微服务(七)--[docker部署linux上线](ECS+linux+docker+API上线部分) 对应练习sql下载路径(0积分):[ASP.NETCore微服务(一)-- ...
- 4 angular 重构 项目_c# – 将Angular 4添加到ASP.NETCore项目中
我想在Visual Studio 2017中的ASP.NetCore 1.1项目中使用Angular 4(读作:* .csproj文件) 以前使用ASP.NET Core 1.0和Visual Stu ...
- 极简实用的Asp.NetCore模块化框架决定免费开源了
背景 在开发这个框架之前,前前后后看过好几款模块化的框架,最后在一段时间内对ABP VNext痛下狠心,研究一段时间后,不得不说 ABP VNext的代码层面很规范,也都是一些最佳实践,开发出一个模块 ...
最新文章
- AIX5.3安装bash shell
- Ubuntu14.04 工作区设置
- 12、Kubernetes核心技术Ingress
- JavaScript中实现私有属性的写类方式(2)
- openstack rootwrap详解
- PHP对请求时间范围条件的判断
- 【浸入式英文学习方式】山姆莱萌帮助孩子建立扎实语言功底
- Linux搭建虚拟机,桥接模式下,主机能够Ping通虚拟机,虚拟机ping不通主机
- 模块说和神经网络学说_教师招聘中常见的5种脑机能学说
- RocketMQ入门
- Python机器学习---2.聚类分析代码部分
- 修改Maven本地仓库的位置 方法
- ufw禁止IP访问ubuntu服务器
- .Net 的 Web 项目中 关于TreeView 的 checkBox 的操作……
- 【14年浙江省赛 ZOJ 3780】Paint the Grid Again【图转换】
- 游戏技能一:激光扫射的实现【CocosCreator 2D】【TypeScript】
- C语言提取PDF字符串,C语言资料精华.pdf
- 产品经理如何设计网页导航菜单
- 超酷的iOS动画集合
- Mybatis动态sql是做什么的?都有哪些动态sql?简述一下动态sql的执行原理?
热门文章
- VMware虚拟机VMware Authorization Service不能启动问题
- modernizer的意义
- iOS开发UI篇—使用嵌套模型完成的一个简单汽车图标展示程序
- SQL Server创建索引(转)
- 开源项目导入eclipse的一般步骤[转]
- Oracle命令--alter 操作
- 个人电脑的楷模:新款IMac G5
- linux是只读添加 来覆盖,Linux之指令 重定向 文件覆盖和文件追加
- php larval开发规范,数据模型 |《 Laravel 项目开发规范 5.5》| Laravel China 社区
- windows 系统监视器_使用Windows 7中的可靠性监视器对计算机问题进行故障排除