作者: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-04-08:为什么TCP握手需要三次?

    假想一下,如果我们去掉了第三次呢?如果只是第二次建立的话,服务端和客户端就已经建立,但是如果客户端没有收到服务端的回应?这个时候,客户端认为没有建立,服务端却为认为建立成功,并保存了必要的资源,如果出 ...

  2. JavaScript map+parseInt 容易产生的误区

    map /** * 语法: * var new_array = arr.map(function callback(currentValue[,index[,array]]){ * // return ...

  3. JMeter软件测试工具介绍及基本安装教程

    一.工具介绍 (一)简介 Apache JMeter是Apache组织开发的基于Java的压力测试工具.用于对软件做压力测试,它最初被设计用于Web应用测试,但后来扩展到其他测试领域. 它可以用于测试 ...

  4. 微信小程序携带参数跳转页面/获取页面栈

    页面跳转携带参数(以传递两个参数为例) a.wxml 页面传递 1 <navigator url="/pages/b/b?id=1&sid='289'"> &l ...

  5. 《Windows程序设计(第5版 珍藏版)》配书光盘

    https://pan.baidu.com/s/1ro72qQja_xTbf-Ik8b06Ng

  6. Istio Routing 实践掌握virtualservice/gateway/destinationrule/AB版本发布/金丝雀发布

    原文 在学习像 Istio 这样的新技术时,看一下示例应用程序总是一个好主意. Istio repo 有一些示例应用程序,但它们似乎有各种不足. 文档中的 BookInfo 是一个很好的示例. 但是, ...

  7. Java泛型详解,通俗易懂只需5分钟

    转载出处:http://www.weixueyuan.net/view/6321.html 我们知道,使用变量之前要定义,定义一个变量时必须要指明它的数据类型,什么样的数据类型赋给什么样的值. 假如我 ...

  8. openvswitch 监听端口变化

    命令: ovsdb-client monitor Interface name,ofport,external_ids --format=json 运行效果: [root@ostack1 ~]# ov ...

  9. django学习(一)

    1.django版本的选择问题 在学习django之前,我们先做一个基本问题的讨论,这个问题是关于django版本的问题.我们进入官网,可以查看django版本的情况. 关于django的版本的问题, ...

  10. Netty之旅二:口口相传的高性能Netty到底是什么?

    高清思维导图原件(xmind/pdf/jpg)可以关注公众号:一枝花算不算浪漫 回复netty01即可. 前言 上一篇文章讲了NIO相关的知识点,相比于传统IO,NIO已经做得很优雅了,为什么我们还要 ...