赞
踩
.NET 8 里针对 Host 做了一些更新,除了前面提到的 IHostedLifecycleService
之外,还支持的 HostedService
的并发地启动和停止,还抽象了在 .NET 7 开始支持的 HostApplicationBuilder
引入了 IHostApplicationBuilder
API,并且引入了一个 Host.CreateEmptyApplicationBuilder
来简化配置一个空的 Host
- var hostBuilder = Host.CreateEmptyApplicationBuilder(null);
- hostBuilder.ConfigureHostOptions(x =>
- {
- x.ServicesStartConcurrently = true;
- x.ServicesStopConcurrently = true;
- x.StartupTimeout = TimeSpan.FromMilliseconds(100);
- });
- hostBuilder.Services.AddHostedService<DelayService>();
- hostBuilder.Services.AddHostedService<ReportTimeService>();
- var host = hostBuilder.Build();
- await host.RunAsync(cancellationToken);
Host.CreateEmptyApplicationBuilder
是 .NET 8 里新增的一个 API 会创建一个空的 Host,不会注册 json,环境变量等配置,不会注册默认的服务如日志配置等
这里的 ConfigureHostOptions
是自己做了一个封装,为了类似于 IHostBuilder
一样简化 HostOptions
的配置,实现如下:
- public static IHostApplicationBuilder ConfigureHostOptions(this IHostApplicationBuilder hostBuilder, Action<HostOptions> configureOptions)
- {
- hostBuilder.Services.Configure(configureOptions);
- return hostBuilder;
- }
HostOptions
里的 ServicesStartConcurrently
/ServicesStopConcurrently
以及 StartupTimeout
是 .NET 8 里新增的配置,两个 Concurrently
是一起新增的,默认值是 false
,StartupTimeout
是和前面介绍的 IHostedLifecycleService
一起新增的,上次没有提起觉得放在这里更加合适,默认没有限制
DelayService 实现如下:
- file class DelayService : IHostedService
- {
- public async Task StartAsync(CancellationToken cancellationToken)
- {
- await Task.Delay(TimeSpan.FromMilliseconds(60), cancellationToken);
- }
-
- public Task StopAsync(CancellationToken cancellationToken)
- {
- return Task.CompletedTask;
- }
- }
-
- file sealed class Delay2Service : DelayService
- {
- }
为了更好查看效果,增加一个报告时间的后台服务,每秒钟打印一次时间:
- file sealed class ReportTimeService : BackgroundService
- {
- protected override async Task ExecuteAsync(CancellationToken stoppingToken)
- {
- using var timer = new PeriodicTimer(TimeSpan.FromSeconds(1));
- while (await timer.WaitForNextTickAsync(stoppingToken))
- {
- Console.WriteLine(DateTimeOffset.Now);
- }
- }
- }
前面示例我们设置的启动超时时间是 100ms,两个 delay service 分别是 60ms,如果串行启动的话则会超时,并行启动的话应该不会超时,我们来测试一下,首先我们把两个 concurrently 的配置去掉使用默认值 false
启动
再把他们加回来,并行启动试一下
可以看到设置为 true 之后就可以正常启动起来了
Host.CreateEmptyApplicationBuilder
这个方法是为了 AOT,之前的方法会加载一系列的配置导致 AOT 变得困难,尤其是 console logging 相关的组件影响,并且这一方法也是 asp.net 里新加的 WebApplication.CreateSlimBuilder()
/WebApplication.CreateEmptyBuilder()
的基础,这两个方法也是为了 AOT 的需求,这两个方法和原来的 WebApplication.CreateBuilder()
我们后面有机会再单独介绍一下
ServicesStartConcurrently
/ServicesStopConcurrently
默认是 false
,如果项目里有比较多的 HostedService
影响服务启动的时候可以考虑这一配置,但是如果想要设置为 true
需要考虑一下有没有启动顺序的要求,如果有启动顺序的要求则不适合使用这一配置,前面介绍的 IHostedLifecycleService
也会受这两个参数的影响,如果设置为 true 的话他们也是并发执行
针对 Host.CreateEmptyApplicationBuilder
这一方法,方法签名如下:
public static HostApplicationBuilder CreateEmptyApplicationBuilder(HostApplicationBuilderSettings? settings)
觉得既然 settings
参数允许为 null
, 应该有个默认值 null
,这样也就不需要像前面示例一样还要显式的传递一个 null
,提了一个 issue 希望能够增加一个没有参数的重载或者设置一个默认值 https://github.com/dotnet/runtime/issues/90477
另外一个就是前面的 ConfigureHostOptions
方法,既然针对 IHostBuilder
有 ConfigureHostOptions
的扩展,针对 IHostApplicationBuilder
感觉也应该有这一扩展来简化 host 的配置,也提了一个 issue https://github.com/dotnet/runtime/issues/90478
目前两个 issue 的 milestone 都是 9.0,8.0 大概是不会有了
IHostApplicationBuilder: https://github.com/dotnet/runtime/issues/85486
https://github.com/dotnet/runtime/pull/86974
Concurrent startup/stop: https://github.com/dotnet/runtime/issues/68036
https://github.com/dotnet/runtime/pull/84048
https://github.com/dotnet/runtime/pull/85191
https://github.com/dotnet/runtime/pull/87335
Host.CreateEmptyApplicationBuilder: https://github.com/dotnet/runtime/issues/81280
https://github.com/dotnet/runtime/pull/81728
https://github.com/dotnet/runtime/issues/90479
https://github.com/dotnet/runtime/issues/90478
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。