作者: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. C#设计模式之23-访问者模式

    访问者模式(Vistor Pattern) 该文章的最新版本已迁移至个人博客[比特飞],单击链接 https://www.byteflying.com/archives/431 访问. 访问者模式属于 ...

  2. C#LeetCode刷题之#263-丑数(Ugly Number)

    问题 该文章的最新版本已迁移至个人博客[比特飞],单击链接 https://www.byteflying.com/archives/3862 访问. 编写一个程序判断给定的数是否为丑数.丑数就是只包含 ...

  3. C#LeetCode刷题之#599-两个列表的最小索引总和​​​​​​​​​​​​​​(Minimum Index Sum of Two Lists)

    问题 该文章的最新版本已迁移至个人博客[比特飞],单击链接 https://www.byteflying.com/archives/3802 访问. 假设Andy和Doris想在晚餐时选择一家餐厅,并 ...

  4. 汇编 | x86汇编指令集大全(带注释)

    做mit-6.828的时候遇到了很多汇编知识,但是无奈学校还没学汇编,只能狠心啃啃硬骨头,在网上查到了很多的资料,归档!方便查看 ----------------------------------- ...

  5. Express Response 之 end /send 傻傻分不清楚

    Express是一个轻量的经典的Node.js开启服务和快速路由管理的库.开启服务的方式也是非常的简单 只需要简单的,安装 $ npm install express   -------> 引入 ...

  6. windows下Nacos集群搭建与nginx集成

    前言: nacos集群至少需要三个(一般为奇数个)nacos实 例,其前面顶nginx,外界入口从nginx入 一.windows下Nacos集群搭建 将Nacos的解压包复制分成3份,分别是: na ...

  7. 在.NET Core中使用MongoDB明细教程(3):Skip, Sort, Limit, Projections

    到目前为止,我们已经讨论了创建文档, 检索文档,现在让我们来研究一下文档排序,指定要跳过或限制返回的文档数量,以及如何进行投影.此篇文章中的实例代码摘录自原文,未像前几篇文章一样进行实际代码的验证. ...

  8. IDEA_Shelve代码搁置与恢复

    日常开发中,经常会遇到在当前分支开发到一半,但是需要Checkout上个版本解决bug或调查问题的情况.这个时候,我们是将代码提到Push远程?还是直接Rollback? 最理想的做法,就是将当前的开 ...

  9. Promise 解析

    Promise 由于js的语言特性(用户交互)和工作环境(浏览器脚本),决定了它是单线程工作,所以两段脚本不能同时运行,但为了实现功能,所以人们使用了事件和回调来初步解决这个问题,例如(addEven ...

  10. 原生js实现 vue的数据双向绑定

    原生js实现一个简单的vue的数据双向绑定 vue是采用数据劫持结合发布者-订阅者模式的方式,通过Object.defineProperty()来劫持各个属性的setter,getter,在数据变动时 ...