ASP.NETCore源码解读
提前准备下载
Vs 2019
.Net Core SDK
这⾥我选⽤Vs 创建,先选⼀个⽂件夹例如
可以通过可视化界⾯创建,也可以通过命令⾏创建
我这⾥选择命令⾏创建
第⼀次打开C#时,会⾃动帮你下载omnisharp和debugger,在线下载安装需要等待安装完成
先介绍查看源码的⽅式F12
VS2019-⼯具-⽂本编辑器-C#-⾼级-勾选⽀持导航到反编译
⽬前只开源了 Core2.X,3.X的暂时还看不到
图片下载站源码
Program类
⾸先介绍Main⽅法⼊⼝,0个引⽤说明是被框架调⽤
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
前期准备WebHostBuild()
CreateHostBuilder创建WebHost,默认配置
Host是⼀个静态类,⾥⾯有⼀个⽅法,我们去看源码
这⾥实例化了⼀个WebHostBuilder类进去看看
private readonly HostingEnvironment _hostingEnvironment;
private readonly List<Action<WebHostBuilderContext, IServiceCollection>> _configureServicesDelegates;
private IConfiguration _config;
private WebHostOptions _options;
private WebHostBuilderContext _context;
private bool _webHostBuilt;
private List<Action<WebHostBuilderContext, IConfigurationBuilder>> _configureAppConfigurationBuilderDelegates;
public WebHostBuilder()//默认构造函数
{
_hostingEnvironment = new HostingEnvironment();
_configureServicesDelegates = new List<Action<WebHostBuilderContext, IServiceCollection>>();
_configureAppConfigurationBuilderDelegates = new List<Action<WebHostBuilderContext, IConfigurationBuilder>>();
_config = new ConfigurationBuilder().AddEnvironmentVariables("ASPNETCORE_").Build();
if (string.IsNullOrEmpty(GetSetting(WebHostDefaults.EnvironmentKey)))
{
UseSetting(WebHostDefaults.EnvironmentKey, Environment.GetEnvironmentVariable("Hosting:Environment") ?? Environment.GetEnvironmentVariable("ASPNET_ENV")); }
if (string.IsNullOrEmpty(GetSetting(WebHostDefaults.ServerUrlsKey)))
{
UseSetting(WebHostDefaults.ServerUrlsKey, Environment.GetEnvironmentVariable("ASPNETCORE_SERVER.URLS"));
}
_context = new WebHostBuilderContext
{
Configuration = _config
}//
这⾥不就是实现依赖注⼊吗(构造函数实例化对象)
WebHost前期需要准备默认配置,这些配置它需要⽤到⼀些参数和⼀些变量通过注⼊的⽅式。
它具体需要配置那些地⽅呢
1.UseContentRoot
WebHostBuilder webHostBuilder = new WebHostBuilder();
if (string.IsNullOrEmpty(webHostBuilder.GetSetting(WebHostDefaults.ContentRootKey)))
{
{
webHostBuilder.UseContentRoot(Directory.GetCurrentDirectory());
}
指定了Web主机所使⽤的内容、站点根⽬录
因为前期就要将那些wwwroot静态⽂件,静态⽹页、配置⽂件读取到,所以先指定⽬录
2.UseConfiguration
if (args != null)
{
webHostBuilder.UseConfiguration(new ConfigurationBuilder().AddCommandLine(args).Build());
}
传的控制台命令args就在这⾥执⾏
3.UseKestrel
webHostBuilder.UseKestrel(delegate (WebHostBuilderContext builderContext, KestrelServerOptions options)
{
options.Configure(builderContext.Configuration.GetSection("Kestrel"));
}
配置Kestrel服务器
4.ConfigureAppConfiguration
ConfigureAppConfiguration(delegate (WebHostBuilderContext hostingContext, IConfigurationBuilder config)
{
IHostingEnvironment hostingEnvironment = hostingContext.HostingEnvironment;
config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true).AddJsonFile("appsettings." + hostingEnvironment.EnvironmentName + ".json", optional: true, reloadOnChange: true);
if (hostingEnvironment.IsDevelopment())
{
Assembly assembly = Assembly.Load(new AssemblyName(hostingEnvironment.ApplicationName));
if (assembly != null)
{
config.AddUserSecrets(assembly, optional: true);//在开发环境使⽤UserSecrets
}
}
config.AddEnvironmentVariables();//⾃动获取环境变量
if (args != null)
{
config.AddCommandLine(args);//命令⾏参数
}
}
⾸先配置了appsettings.json,然后规定在开发环境使⽤UserSecrets,UserSecrets是个⼈的密钥,项⽬中是不会推送⾄远程仓库,该怎么创建呢5.ConfigureLogging
ConfigureLogging(delegate (WebHostBuilderContext hostingContext, ILoggingBuilder logging)
{
//添加服务的地⽅Logging配置
logging.AddConfiguration(hostingContext.Configuration.GetSection("Logging"));
logging.AddConsole();//控制台
logging.AddDebug();//Debug
logging.AddEventSourceLogger();//事件
}
配置⽇志
6.ConfigureServices
ConfigureServices(delegate (WebHostBuilderContext hostingContext, IServiceCollection services)
{
ConfigureServices(delegate (WebHostBuilderContext hostingContext, IServiceCollection services)
{
services.PostConfigure(delegate (HostFilteringOptions options)
{
if (options.AllowedHosts == null || options.AllowedHosts.Count == 0)
{
string[] array = hostingContext.Configuration["AllowedHosts"]?.Split(new char[1]
{
';'
}, StringSplitOptions.RemoveEmptyEntries);
options.AllowedHosts = ((array != null && array.Length != 0) ? array : new string[1]
{
"*"
});
}
});
services.AddSingleton((IOptionsChangeTokenSource<HostFilteringOptions>)new
ConfigurationChangeTokenSource<HostFilteringOptions>(hostingContext.Configuration));
services.AddTransient<IStartupFilter, HostFilteringStartupFilter>();
}
ConfigureServices是Startup⽅法⾥⾯的,会⾃动把我们的⼀些服务进⾏默认配置,我们提前写好的配置服务,在WebHostBuilder⾥⾯构建,进⾏服务注⼊。
最后返回⼀个WebHostBuilder,就完成构建了。
我们在默认配置的时候是默认不包含我们⾃⼰创建的Startup的服务,⽽是系统默认的服务。
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
}
Build()-构建
构建⼀个Microsoft.AspNetCore.Hosting,托管Web应⽤程序的WebHost,⼀个⽅法只会执⾏⼀次
Run()-构启动
发现run⽅法下⾯是⼀个异步⽅法
public static void Run(this IWebHost host)
{
host.RunAsync().GetAwaiter().GetResult();
}
public static async Task RunAsync(this IWebHost host, CancellationToken token = default(CancellationToken))
{
if (token.CanBeCanceled)
{
await host.RunAsync(token, null);
return;
}
ManualResetEventSlim done = new ManualResetEventSlim(initialState: false);
using (CancellationTokenSource cts = new CancellationTokenSource())
{
AttachCtrlcSigtermShutdown(cts, done, host.Services.GetRequiredService<WebHostOptions>().SuppressStatusMessages ? string.Empty : "Application is ");
try
{
await host.RunAsync(cts.Token, "Application started. Press Ctrl+C to shut down.");
}
finally
{
done.Set();
}
}
}
private static async Task RunAsync(this IWebHost host, CancellationToken token, string shutdownMessage)
{
using (host)
{
await host.StartAsync(token);
IHostingEnvironment service = host.Services.GetService<IHostingEnvironment>();
if (!host.Services.GetRequiredService<WebHostOptions>().SuppressStatusMessages)
{
Console.WriteLine("Hosting environment: " + service.EnvironmentName);
Console.WriteLine("Content root path: " + service.ContentRootPath);
ICollection<string> collection = host.ServerFeatures.Get<IServerAddressesFeature>()?.Addresses;
if (collection != null)
{
foreach (string item in collection)
{
Console.WriteLine("Now listening on: " + item);
Console.WriteLine("Now listening on: " + item);
}
}
if (!string.IsNullOrEmpty(shutdownMessage))
{
Console.WriteLine(shutdownMessage);
}
}
await host.WaitForTokenShutdownAsync(token);
}
}
因此显⽰以下信息
进程是指IIS Worker Process⼯作进程
启动IIS运⾏ Core项⽬可以在任务管理器中看到,结束项⽬运⾏进程消失
进程内托管就是指的这个
进程外托管就是,打开⽹页可以看到服务器
双击项⽬
AspNetCoreHostingModel配置了托管模式。InProcess指定进程内,OutProcess指定进程外
1.当AspNetCoreHostingModel设置InProcess进程内托管,启动IIS,任务管理器这时候有IIS Worker Process,⽹页服务器显⽰IIS
2.当AspNetCoreHostingModel设置InProcess进程内托管,启动项⽬,任务管理器这时候没有IIS Worker Process,⽹页服务器显⽰IIS
3.当AspNetCoreHostingModel设置OutProcess进程外托管,启动IIS,任务管理器这时候还是有IIS W
orker Process,⽹页服务器显⽰Kestrel
4.当AspNetCoreHostingModel设置OutProcess进程外托管,启动项⽬,任务管理器没有IIS Worker Process,⽹页服务器显⽰Kestrel
这是怎么回事,怎么进程内外都会启动IIS Worker Process,进程内外到底有什么区别
原因分析:蓝⾊字体第1、3点进程内外的IIS服务都会启动,不过启动的作⽤确实不⼀样的
1.进程内启动IIS是当作服务器
2.进程外也启动IIS,是Kestrel配合IIS,将IIS当作反向代理服务器使⽤,不是作为整个项⽬的应⽤服务器了
以前是请求通过IIS监听,通过IIS托管代码响应直接完成
ASP.NET Core不同的是 靠ASP.NET Core Module把HTTP请求转发
IIS这个时候等同于Nginx反向代理,本⾝不再处理了
ASP.NET Core内置Kestrel服务器等价于IIS--Webserver
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论