.NET 8 Host 的一些更新

.NET 8 Host 的一些更新

Intro

.NET 8 里针对 Host 做了一些更新,除了前面提到的 IHostedLifecycleService 之外,还支持的 HostedService 的并发地启动和停止,还抽象了在 .NET 7 开始支持的 HostApplicationBuilder 引入了 IHostApplicationBuilder API,并且引入了一个 Host.CreateEmptyApplicationBuilder 来简化配置一个空的 Host

Sample

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 是一起新增的,默认值是 falseStartupTimeout 是和前面介绍的 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 启动

8543997f05858334d3ba2b1a4f7956c2.png

再把他们加回来,并行启动试一下

ea969998180f220699e6a083dd1915f2.png

可以看到设置为 true 之后就可以正常启动起来了

More

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 方法,既然针对 IHostBuilderConfigureHostOptions 的扩展,针对 IHostApplicationBuilder 感觉也应该有这一扩展来简化 host 的配置,也提了一个 issue https://github.com/dotnet/runtime/issues/90478

目前两个 issue 的 milestone 都是 9.0,8.0 大概是不会有了

References

  • 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

  • .NET 8 中的 IHostedLifecycleService

  • .NET 7 中的 HostApplicationBuilder

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值