首页 > 其他分享 >.NET8 WebApplication

.NET8 WebApplication

时间:2023-12-21 22:55:07浏览次数:28  
标签:IHost Run NET8 host ._ WebApplication public

.NET8 WebApplication剖析

 

​ WebApplication 是用于配置HTTP管道和路由的web应用程序,接来下我将一一拆解它的组成。

/// <summary>
/// The web application used to configure the HTTP pipeline, and routes.
/// </summary>
[DebuggerDisplay("{DebuggerToString(),nq}")]
[DebuggerTypeProxy(typeof (WebApplication.WebApplicationDebugView))]
public sealed class WebApplication : IHost,IDisposable,IApplicationBuilder,IEndpointRouteBuilder,IAsyncDisposable

IHost

​ 首先Web应用是一个程序,而 IHost 就是程序的抽象

public interface IHost : IDisposable
{
  IServiceProvider Services { get; }
  Task StartAsync(CancellationToken cancellationToken = default (CancellationToken));
  Task StopAsync(CancellationToken cancellationToken = default (CancellationToken));
}

​ 一个程序具备启动、停止生命周期,这很好理解。我要说的是 IServiceProvider ,他非常关键,后面会在依赖注入章节来详细解释。目前你只需要知道他是一个服务供应商就可以了,就可以通过他获取想要的服务,但前提是你在IOC容器中注册过。

​ Host StartAsync 代码流如下:

await host._hostLifetime.WaitForStartAsync(token1).ConfigureAwait(false); // 注册start程序
host.Services.GetService<IStartupValidator>()?.Validate(); // 校验
IHostedLifecycleService.StartingAsync
IHostedService.StartAsync
IHostedLifecycleService.StartedAsync
host._applicationLifetime.NotifyStarted();

​ StopAsync 类似,代码流如下:

IHostedLifecycleService.StoppingAsync
IHostedService.StopAsync
IHostedLifecycleService.StoppedAsync
this._logger.StoppedWithException((Exception) ex);

​ 值得注意的是 IStartupValidatorIHostedServiceIHostedLifecycleService 分别为我们提供不同的钩子,只需要向容器注册即可加入我们自定义的业务逻辑。

IApplicationBuilder

​ WebApplication 实现 IApplicationBuilder 具有pipeline机制。

IApplicationBuilder Use(Func<RequestDelegate, RequestDelegate> middleware);
RequestDelegate Build();

​ 这里要解释一下pipeline,管道是.NET中非常普及的一个概念,内核是切面编程,同样的在后续我们会有专门的章节来例举它。现在你只需要知道,他是一个洋葱模型。

​ 同时,IApplicationBuilder 从命名上就表达了这是一个构建者模式,因此 WebApplication 提供了 Build

public WebApplication Build()
{
  this._hostApplicationBuilder.Services.Add(this._genericWebHostServiceDescriptor);
  this.Host.ApplyServiceProviderFactory(this._hostApplicationBuilder);
  this._builtApplication = new WebApplication(this._hostApplicationBuilder.Build());
  return this._builtApplication;
}

​ 篇幅问题这里不展开讨论,但在Build方法中会有四个钩子被执行

public IHostBuilder ConfigureHostConfiguration(Action<IConfigurationBuilder> configureDelegate)
public IHostBuilder ConfigureAppConfiguration(Action<HostBuilderContext, IConfigurationBuilder> configureDelegate)
public IHostBuilder ConfigureServices(Action<HostBuilderContext, IServiceCollection> configureDelegate)
public IHostBuilder ConfigureContainer<TContainerBuilder>(Action<HostBuilderContext, TContainerBuilder> configureDelegate)

​ 最终服务容器会被标记成只读

IEndpointRouteBuilder

​ IEndpointRouteBuilder为程序定义路由构建的约定。

ICollection<EndpointDataSource> DataSources { get; }

​ 这是 WebApplication 中的实现,可以看到 EndpointDataSource 的实现会被组合进来。

public IReadOnlyList<Endpoint> Endpoints
{
  get
  {
    EndpointDataSource requiredService = this._webApplication.Services.GetRequiredService<EndpointDataSource>();
    return requiredService is CompositeEndpointDataSource endpointDataSource && endpointDataSource.DataSources.Intersect<EndpointDataSource>((IEnumerable<EndpointDataSource>) this._webApplication.DataSources).Count<EndpointDataSource>() != this._webApplication.DataSources.Count ? new CompositeEndpointDataSource((IEnumerable<EndpointDataSource>) this._webApplication.DataSources).Endpoints : requiredService.Endpoints;
  }
}

​ EndpointDataSource实际上就是一组 Endpoint,而 Endpoint 是 AspNetCore 下极其重要的一节,同样会在后续展开讲。现在你只需要知道,它表示一个处理 HTTP 请求的终点,包含了处理请求的逻辑和相关的元数据。

IAsyncDisposable

​ IAsyncDisposable 是 .NET Core 2.0 引入的一个接口,用于异步释放资源的模式。它是 IDisposable 接口的异步版本。某些资源的释放可能涉及到异步操作,使用 IDisposable 接口的同步释放模式可能会导致阻塞线程,影响应用程序的性能和响应性。

public interface IAsyncDisposable
{
  ValueTask DisposeAsync();
}

​ 在使用完该对象后,可以使用 await using语法糖或直接调用 ``DisposeAsync()` 方法来释放资源。

Run

​ Run 函数是 WebApplication 的启动按钮,你可以传递一个url,加入到监听列表

public void Run([StringSyntax("Uri")] string? url = null)
{
  this.Listen(url);
  // public static void Run(this IHost host) => host.RunAsync().GetAwaiter().GetResult();
  HostingAbstractionsHostExtensions.Run(this);
}

​ HostingAbstractionsHostExtensions.Run的源码相对简单,host的 StartAsyncWaitForShutdownAsync 在上面都介绍了,WebApplication 的 DisposeAsync 也在finally块中触发

public static async Task RunAsync(this IHost host, CancellationToken token = default (CancellationToken))
{
  try
  {
    ConfiguredTaskAwaitable configuredTaskAwaitable = host.StartAsync(token).ConfigureAwait(false);
    await configuredTaskAwaitable;
    configuredTaskAwaitable = host.WaitForShutdownAsync(token).ConfigureAwait(false);
    await configuredTaskAwaitable;
  }
  finally
  {
    if (host is IAsyncDisposable asyncDisposable)
      await asyncDisposable.DisposeAsync().ConfigureAwait(false);
    else
      host.Dispose();
  }
}

​ 上面有个很有意思的点是,为什么要在finally块中触发?这是因为Host的生命周期函数都用了联合取消令牌,这是一种安全取消协作模式,在令牌取消后会触发一个 OperationCanceledException 异常,进而在这种情况下还能够正常处理销毁工作,这是一种非常优秀的编程习惯。

标签:IHost,Run,NET8,host,._,WebApplication,public
From: https://www.cnblogs.com/Leo_wl/p/17920304.html

相关文章

  • net8获取泛微token以及访问api示例
    工作中涉及到调用泛微的场景,官方的示例又臭又长,抽空用NET8简化了写法,为了简化http访问,用了Flurl.Http这个库。在座各位大佬,我们直接就看代码了 usingSystem.Security.Cryptography;usingSystem.Text.Json;usingFlurl.Http;//请按照官方内容做好初始化工作https://e-c......
  • .net8.0 在docker下发布镜像的坑
    最近升级.net8.0,出现应该不能在挂载目录中建立文件的问题,在相应位置创建时报错,在docker中/app/Upload$>1.txtbash:1.txt:Permissiondenied 7.0是没有这个问题的,根据官方说法:.NET8.0ContainerImagesNowAvailable·dotnet/dotnet-docker·Discussion#4995·Gi......
  • .NET8 AOT和JIT的性能,谁更高呢?
    一:有人问:.NET8AOT和JIT的性能,谁更高呢?原文:.NET8AOT和JIT的性能,谁更高呢?其实这个答案非常明显,那就是JIT的性能更高。为什么?原因在哪?因为JIT是随时可能分层编译,动态PGO,CHRL,NonGCHeap,OSR。Quick等极致的优化措施(关于这些措施,可以参考公众号(jianghupt)之前的文章,有详细描......
  • AgileConfig 1.8.0 已适配 .NET8
    Hello大家好。本月圈子里最大的事莫过于.NET8正式release。群友们都在适配.NET8。抽个周末我也把AgileConfig升级到了.NET8。下面把升级的过程简单记录一下,其中有个小坑,对大家升级的时候可能有所帮助。升级升级.NET8修改所有项目的目标框架为.NET8.0升级nuget包......
  • NET8在CentOS7下无法执行的问题
    以二进制模式在CentOS7安装后,运行NET8报错误:#dotnet--list-sdksFailedtoload/usr/share/dotnet/host/fxr/8.0.0/libhostfxr.so,error:/lib64/libstdc++.so.6:version`GLIBCXX_3.4.20'notfound(requiredby/usr/share/dotnet/host/fxr/8.0.0/libhostfxr.so)Theli......
  • .NET8 极致性能优化 AOT
    前言.NET8对于性能的优化是方方面面的,所以AOT预编译机器码也是不例外的。本篇来看下对于AOT的优化。概述首先要明确一个概念,.NET里面的AOT它是原生的。什么意思呢?也就是说通过ILC编译器(AOT编译器,参考:.Net7新编译器ILC简析)编译出来的代码是各个平台上可以直......
  • .NET8极致性能优化AOT
    前言.NET8对于性能的优化是方方面面的,所以AOT预编译机器码也是不例外的。本篇来看下对于AOT的优化。原文:.NET8极致性能优化AOT详述首先明确一个概念,.NET里面的AOT它是原生的。什么意思呢?也就是说通过ILC编译器(AOT编译器,参考:.Net7新编译器ILC简析)编译出来的代码是各个平......
  • 在NET8中使用简化的 AddJwtBearer 认证
    开发环境系统版本:win10.NETSDK:NET8开发工具:vscode参考引用:使用dotnetuser-jwts管理开发中的JSONWeb令牌注意:以下示例中的端口、token等需替换成你的环境中的信息创建项目运行以下命令来创建一个空的Web项目,并添加Microsoft.AspNetCore.Authentication.JwtBea......
  • .NET8 依赖注入
    依赖注入(DependencyInjection,简称DI)是一种设计模式,用于解耦组件(服务)之间的依赖关系。它通过将依赖关系的创建和管理交给外部容器来实现,而不是在组件(服务)内部直接创建依赖对象。​ 咱就是通过IServiceCollection和IServiceProvider来实现的,他们直接被收入到了runtimelibrari......
  • springBoot项目启动卡在Root WebApplicationContext: initialization completed... (非
    通过源码启动排查发现,初始化连接池时创建了200次,通过配置文件中将initialSize值改为10,启动时间从1分钟变为了3秒。 ......