作者:cmliu;.NET Core启动都做了什么

.NET Core默认启动时的流程,您可以将图片另存为,在本地放大查看

.NET Core默认模板都做了些什么,首先贴出模板里面的Program.cs

    public class Program
{
public static void Main(string[] args)
{
CreateWebHostBuilder(args).Build().Run();
} public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>();
}

解读:

1,入口main方法首先调用CreateWebHostBuilder(string[] args)方法获取一个[Web主机构建者WebHostBuilder]

2,CreateWebHostBuilder(string[] args)方法首先是调用:WebHost.CreateDefaultBuilder(args)创建一个默认的WebHostBuilder

    在WebHost.CreateDefaultBuilder中,首先读取了命令行,ContentRoot配置;然后指定Kestrel的配置,日志提供程序,以及相关优先执行的中间件,并明确注入了IServer的实现类为KestrelServer;

    并配置了IIS相关的服//WebHost.CreateDefaultBuilder部分源码    

     public static IWebHostBuilder CreateDefaultBuilder(string[] args)
{
var builder = new WebHostBuilder(); if (string.IsNullOrEmpty(builder.GetSetting(WebHostDefaults.ContentRootKey)))
{
builder.UseContentRoot(Directory.GetCurrentDirectory());
}
if (args != null)
{
builder.UseConfiguration(new ConfigurationBuilder().AddCommandLine(args).Build());
}

         //该方法底层指定了Server的实现类为KestrelServer()
  builder.UseKestrel((builderContext, options) =>
{
//省略其他代码

})
.ConfigureAppConfiguration((hostingContext, config) =>
{
//省略其他代码
})
.ConfigureLogging((hostingContext, logging) =>
{
//省略其他代码
})
.ConfigureServices((hostingContext, services) =>
{
//省略其他代码
})
.UseIIS()
.UseIISIntegration()
.UseDefaultServiceProvider((context, options) =>
{
//省略其他代码
}); return builder;
}

  3, 调用WebHost.CreateDefaultBuilder(args)返回对象的UseStartup<Startup>()方法;用于将服务注册到容器(ConfigureServices方法),以及注册管道(Configure方法)

        这里也说明一下Startup中的ConfigureServices,Configure两个方法与【下面】的Program类中ConfigureServices,Configure方法作用是一样的,都是用于将服务注册到容器(ConfigureServices方法),以及注册管道(Configure方法)

        public static IWebHostBuilder CreateWebHostBuilder(string[] args)
{
var webHostBuilder = WebHost.CreateDefaultBuilder(args).ConfigureServices((services) =>
{
//省略其他代码,用于注册服务到容器
}).Configure((app) =>
{
//省略其他代码,用于注册管道
});
return webHostBuilder;
}

4,Statrtup中的代码,省略,后面进行解读

5,main方法中调用CreateWebHostBuilder(string[] args)返回的WebHostBuilder的Build方法

    在这个Build方法中,直接初始化并返回了一个WebHost,并指定了WebHost的IServiceCollection(服务),IServiceProvider(容器),该WebHost有一个Server对象,对象实际上为KestrelServer

6,调用Build返回的WebHost对象的Run方法,用于启动服务器

    *******实际上WebHost.Run方法中,首先获取一个ApplicationBuilder(就是Startip中的Configure方法中那个用于注入管道的类),并使用ApplicationBuilder.Build方法倒序构建RequestDelegate委托链管道

    *******ApplicationBuilder.Build方法中,会把404中间件最为最后一个中间件注入到管道

    *******使用获得的RequestDelegate,日志,HttpContextFactory相关参数,构造一个HostingApplication

    *******最底层:以异步的方式启动WebHost.Server.StartAsync,即调用KestrelServer的StartAsync的方法,并在方法中指定了HostingApplication【此时KestrelServer已经有了一个拥有RequestDelegate管道的HostingApplication】

    internal class WebHost : IWebHost
{
//省略其他代码
private readonly IServiceCollection _applicationServiceCollection;
private readonly IServiceProvider _hostingServiceProvider;
private IServiceProvider _applicationServices;
private IServer Server { get; set; }
//省略其他代码
public WebHost(IServiceCollection appServices,IServiceProvider hostingServiceProvider,
WebHostOptions options,IConfiguration config,AggregateException hostingStartupErrors)
{
//省略其他代码
_applicationServiceCollection = appServices;
_hostingServiceProvider = hostingServiceProvider;
//省略其他代码
}
//省略其他代码
public IServiceProvider Services
{
get
{
return _applicationServices;
}
}
//省略其他代码
public void Start()
{
StartAsync().GetAwaiter().GetResult();
}
//省略其他代码
public virtual async Task StartAsync(CancellationToken cancellationToken = default)
{
//省略其他代码
//构建RequestDelegate委托链管道
var application = BuildApplication(); _applicationLifetime = _applicationServices.GetRequiredService<IApplicationLifetime>() as ApplicationLifetime;
_hostedServiceExecutor = _applicationServices.GetRequiredService<HostedServiceExecutor>();
var diagnosticSource = _applicationServices.GetRequiredService<DiagnosticListener>();
var httpContextFactory = _applicationServices.GetRequiredService<IHttpContextFactory>();
//RequestDelegate委托链管道用于构建HostingApplication
var hostingApp = new HostingApplication(application, _logger, diagnosticSource, httpContextFactory);
//启动KestrelServer服务器,并将HostingApplication绑定到KestrelServer
await Server.StartAsync(hostingApp, cancellationToken).ConfigureAwait(false);
//省略其他代码
}
//省略其他代码 private RequestDelegate BuildApplication()
{
try
{
//省略其他代码
var builderFactory = _applicationServices.GetRequiredService<IApplicationBuilderFactory>();
var builder = builderFactory.CreateBuilder(Server.Features);
builder.ApplicationServices = _applicationServices;
          //省略其他代码
          return builder.Build();
}
catch (Exception ex)
{
          //省略其他代码
        }
}
//省略其他代码
}

  7,KestrelServer启动HttpListener后,开始监听来自客户端浏览器的请求

  8,KestrelServer接收到浏览器请求后,将请求参数构造出HttpContext,并选择对应的HTTP协议处理类,通过协议处理类的ProcessRequests方法(传说中的PR方法)

    public abstract partial class HttpProtocol : IHttpResponseControl
{
//HTTP协议类调用HttpApplication
private async Task ProcessRequests<TContext>(IHttpApplication<TContext> application)
{
while (_keepAlive)
{
//省略其他代码
try
{
//省略其他代码
await application.ProcessRequestAsync(httpContext);
//省略其他代码
}
catch (BadHttpRequestException ex)
{
//省略其他代码
}
//省略其他代码
}
}
}

  9,PR方法会去调用KestrelServer的HostingApplication的ProcessRequestAsync,而ProcessRequestAsync则是把HttpContext交给RequestDelegate管道处理

public class HostingApplication : IHttpApplication<HostingApplication.Context>
{
//委托链管道
private readonly RequestDelegate _application;
//省略其他代码
public HostingApplication(
RequestDelegate application,
ILogger logger,
DiagnosticListener diagnosticSource,
IHttpContextFactory httpContextFactory)
{
_application = application;
//省略其他代码
} //PR方法,调用委托链处理请求
public Task ProcessRequestAsync(Context context)
{
return _application(context.HttpContext);
}
    //省略其他代码
}

.NET Core原理(不知道怎么命名合适)的更多相关文章

  1. 什么鬼,又不知道怎么命名class了

    什么鬼,又不知道怎么命名class了 2015/10/25 · CSS · class 分享到:5 原文出处: 结一(@结一w3cplus)    相信写css的人都会遇到下面的问题: 糟糕,怎么命名 ...

  2. [转]什么鬼,又不知道怎么命名class了

    (本文作者Mrcxt,原文链接:http://blog.csdn.net/mrcxt/article/details/52038884) 相信写css的人都会遇到下面的问题: 糟糕,怎么命名这个cla ...

  3. ASP.NET Core原理概述

    ASP.NET Core 是一个控制台应用程序,在其 main 方法中创建一个Web服务器,以下是program.cs中的代码: using Microsoft.AspNetCore; using M ...

  4. EF Core 原理从源码出发(二)

    紧接着我的上一篇博客,上回分析到ef 一个重要的对象,changetracker这个对象,当我们向DbContext添加对象的时候我们会调用如下代码. 1 private EntityEntry< ...

  5. day 变量的赋值原理 变量的命名规则

    print(3*4*5*6/2) #简单的计算输出 x=3 y=4 print("x乘以y=",x*y) #运行5分钟 = 12 print(x*y) #在运行5分钟 = 12 ' ...

  6. EntityFramework Core 运行dotnet ef命令迁移背后本质是什么?(EF Core迁移原理)

    前言 终于踏出第一步探索EF Core原理和本质,过程虽然比较漫长且枯燥乏味还得反复论证,其中滋味自知,EF Core的强大想必不用我再过多废话,有时候我们是否思考过背后到底做了些什么,到底怎么实现的 ...

  7. Cookies 初识 Dotnetspider EF 6.x、EF Core实现dynamic动态查询和EF Core注入多个上下文实例池你知道有什么问题? EntityFramework Core 运行dotnet ef命令迁移背后本质是什么?(EF Core迁移原理)

    Cookies   1.创建HttpCookies Cookie=new HttpCookies("CookieName");2.添加内容Cookie.Values.Add(&qu ...

  8. [转]在.NET Core 2.x中将多个强类型设置实例与命名选项一起使用

    自1.0版之前,ASP.NET Core已使用“ 选项”模式配置强类型设置对象.从那时起,该功能获得了更多功能.例如,引入了ASP.NET Core 1.1 IOptionsSnapshot,它允许您 ...

  9. 关于Segmentation fault (core dumped)几个简单问题的整理

    有的程序可以通过编译,但在运行时会出现Segment fault(段错误).这通常都是指针错误引起的.但这不像编译错误一样会提示到文件一行,而是没有任何信息.一种办法是用gdb的step, 一步一步寻 ...

随机推荐

  1. 2020-06-18:ZK的分布式锁怎么实现?

    福哥答案2020-06-18: Zk分布式锁有两种实现方式一种比较简单,应对并发量不是很大的情况.获得锁:创建一个临时节点,比如/lock,如果成功获得锁,如果失败没获得锁,返回false释放锁:删除 ...

  2. C#LeetCode刷题之#112-路径总和​​​​​​​(Path Sum)

    问题 该文章的最新版本已迁移至个人博客[比特飞],单击链接 https://www.byteflying.com/archives/4078 访问. 给定一个二叉树和一个目标和,判断该树中是否存在根节 ...

  3. 个人电脑搭建ftp----------------2

    个人电脑搭建ftp 从上一次搭建好的局域网继续完成我的后续. 打开windows10 控制面板 点击启用或关闭windows功能 找到Internet Information Services,开启所 ...

  4. CSS动画实例:移动的眼珠子

    适当地利用CSS的box-shadow可以构造图形,然后可以对构造的图形添加动画效果.下面我们通过移动的眼珠子.圆珠一二三.一分为四.四小圆旋转扩散等实例来体会box-shadow属性在动画制作中的使 ...

  5. iptables初步接触

    0.iptables命令选项输入顺序:iptables -t 表名 <-A/I/D/R> 规则链名 [规则号] <-i/o 网卡名> -p 协议名 <-s 源IP/源子网 ...

  6. 操作系统-存储管理(5)IA-32/Linux的地址转换

    IA-32/Linux按字节编址:在保护模式下,IA-32采用段页式虚拟存储管理方式,存储地址采用逻辑地址.线性地址和物理地址来进行描述. 逻辑地址由48位组成,包含16位段选择符(高13位为段表项的 ...

  7. 计算机网络-应用层(5)P2P应用

    P2P系统的索引:信息到节点位置(IP地址+端口号)的映射 在文件共享(如电驴中):利用索引动态跟踪节点所共享的文件的位置.节点需要告诉索引它拥有哪些文件.节点搜索索引从而获知能够得到哪些文件 在即时 ...

  8. Shell编程—图形化脚本

    1创建文本菜单 1.1普通的文本菜单 $ cat menu1 #!/bin/bash # simple script menu function diskspace { clear df -k } f ...

  9. better-scroll实现滚动

    通过better-scroll这个插件实现微信好友滚动列表 安装better-scroll npm i better-scroll 初始化better-scroll   //better-scroll ...

  10. IDEA下Maven项目搭建踩坑记----1.pom,xml文件下${spring-version}不能用

    因为pom.xml文件是直接复制别人配好的web环境,所以在粘贴进去的之后有一部分没有粘贴到,因此出现爆红 解决方法:↓↓↓↓ 代码: <project.build.sourceEncoding ...