欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

(16)ASP.NET Core 通用主机(HostBuilder)

程序员文章站 2022-03-22 14:36:34
1.前言 ASP.NET Core应用程序可以配置和启动主机(Host)。主机负责应用程序启动和生命周期管理。通用主机用于无法处理HTTP请求的应用程序。通用主机的用途是将HTTP管道从Web主机API中分离出来,从而启用更多的主机方案。 基于通用主机的消息、后台任务和其他非HTTP工作负载可从横切 ......

1.前言

asp.net core应用程序可以配置和启动主机(host)。主机负责应用程序启动和生命周期管理。通用主机用于无法处理http请求的应用程序。通用主机的用途是将http管道从web主机api中分离出来,从而启用更多的主机方案。 基于通用主机的消息、后台任务和其他非http工作负载可从横切功能(如配置、依赖关系注入[di]和日志记录)中受益。通用主机是asp.net core 2.1中的新增功能,不适用于web承载方案。对于web承载方案,请使用web主机。通用主机将在未来版本中替换web主机,并在http和非http方案中充当主要的主机api。

2.介绍

ihostedservice是执行代码的入口点。每个ihostedservice实现都按照configureservices中服务注册的顺序执行。主机启动时,每个ihostedservice上都会调用startasync,主机正常关闭时,以反向注册顺序调用stopasync。

3.设置主机

ihostbuilder是供库和应用程序初始化、生成和运行主机的主要组件:

public static async task main(string[] args)
{
    var host = new hostbuilder().build();
    await host.runasync();
}

4.选项

hostoptions配置ihost的选项。

4.1关闭超时值

shutdowntimeout设置stopasync的超时值。默认值为5秒。program.main中的以下选项配置将默认值为5秒的关闭超时值增加至20秒:

var host = new hostbuilder().configureservices((hostcontext, services) =>
    {
        services.configure<hostoptions>(option =>
        {
            option.shutdowntimeout = system.timespan.fromseconds(20);
        });
    })
    .build();

5.默认服务

在主机初始化期间注册以下服务:
●环境 (ihostingenvironment)
●hostbuildercontext
●配置 (iconfiguration)
●iapplicationlifetime (applicationlifetime)
●ihostlifetime (consolelifetime)
●ihost
●选项 (addoptions)
●日志记录 (addlogging)

6.主机配置

主机配置的创建方式如下:
●调用ihostbuilder上的扩展方法以设置“内容根”和“环境”。
●从configurehostconfiguration中的配置提供应用程序读取配置。
●应用程序键(名称)、内容根、环境配置方式我就不多说了,跟上一篇web主机配置是一样的。

6.1configurehostconfiguration

configurehostconfiguration使用iconfigurationbuilder来为主机创建iconfiguration。主机配置用于初始化ihostingenvironment,以供在应用程序的构建过程中使用。可多次调用configurehostconfiguration,并得到累计结果。必须在configurehostconfiguration中显式指定应用程序所需的任何配置提供自身,包括:
●文件配置(例如,来自hostsettings.json文件)。
●环境变量配置。
●命令行参数配置。
●任何其他所需的配置提供程序。
通过使用setbasepath指定应用程序的基本路径,然后调用其中一个文件配置提供应用程序,可以启用主机的文件配置。示例应用使用json文件hostsettings.json,并调用addjsonfile来使用文件的主机配置设置。要添加主机的环境变量配置,请在主机生成器上调用 addenvironmentvariables。addenvironmentvariables接受用户定义的前缀(可选)。示例应用程序使用前缀prefix_。当系统读取环境变量时,便会删除前缀。配置示例应用程序的主机后,prefix_environment的环境变量值就变成environment密钥的主机配置值。示例hostbuilder配置使用configurehostconfiguration:

var host = new hostbuilder().configurehostconfiguration(confighost =>
    {
        confighost.setbasepath(directory.getcurrentdirectory());
        confighost.addjsonfile("hostsettings.json", optional: true);
        confighost.addenvironmentvariables(prefix: "prefix_");
        confighost.addcommandline(args);
    })

6.2configureappconfiguration

通过在ihostbuilder实现上调用configureappconfiguration创建应用程序配置。configureappconfiguration使用iconfigurationbuilder来为应用程序创建iconfiguration。可多次调用configureappconfiguration,并得到累计结果。应用程序使用上一次在一个给定键上设置值的选项。hostbuildercontext.configuration中提供configureappconfiguration创建的配置,以供进行后续操作和在services中使用。应用程序配置会自动接收configurehostconfiguration提供的主机配置。示例应用配置使用configureappconfiguration:

var host = new hostbuilder().configureappconfiguration((hostcontext, configapp) =>
    {
        configapp.setbasepath(directory.getcurrentdirectory());
        configapp.addjsonfile("appsettings.json", optional: true);
        configapp.addjsonfile(
            $"appsettings.{hostcontext.hostingenvironment.environmentname}.json",
            optional: true);
        configapp.addenvironmentvariables(prefix: "prefix_");
        configapp.addcommandline(args);
    })

6.3configureservices

configureservices将服务添加到应用程序的依赖关系注入容器。可多次调用configureservices,并得到累计结果。托管服务是一个类,具有实现ihostedservice接口的后台任务逻辑。示例应用程序使用addhostedservice扩展方法向自身添加生命周期事件 lifetimeeventshostedservice和定时后台任务timedhostedservice服务:

var host = new hostbuilder()
    .configureservices((hostcontext, services) =>
    {
        if (hostcontext.hostingenvironment.isdevelopment())
        {
            // development service configuration
        }
        else
        {
            // non-development service configuration
        }
        services.addhostedservice<lifetimeeventshostedservice>();
        services.addhostedservice<timedhostedservice>();
})

6.4configurelogging

configurelogging添加了一个委托来配置提供的iloggingbuilder。可以利用相加结果多次调用 configurelogging。

var host = new hostbuilder().configurelogging((hostcontext, configlogging) =>
    {
        configlogging.addconsole();
        configlogging.adddebug();
    })
6.4.1useconsolelifetime

useconsolelifetime侦听ctrl+c/sigint或sigterm并调用stopapplication来启动关闭进程。useconsolelifetime解除阻止runasync和waitforshutdownasync等扩展。consolelifetime预注册为默认生命周期实现,使用注册的最后一个生命周期。

var host = new hostbuilder().useconsolelifetime()

7.容器配置

主机可以接受iserviceproviderfactory<tcontainerbuilder>。提供工厂不属于di容器注册,而是用于创建具体di容器的主机内部函数。useserviceproviderfactory(iserviceproviderfactory<tcontainerbuilder>)重写用于创建应用程序的服务提供程序的默认工厂。configurecontainer方法托管自定义容器配置。configurecontainer提供在基础主机api的基础之上配置容器的强类型体验。可以利用相加结果多次调用configurecontainer。

为应用程序创建服务容器并提供服务容器工厂:

public class generichostsample
{
    internal class servicecontainerfactory : iserviceproviderfactory<servicecontainer>
    {
        public servicecontainer createbuilder(iservicecollection services)
        {
            return new servicecontainer();
        }
        public iserviceprovider createserviceprovider(servicecontainer containerbuilder)
        {
            throw new notimplementedexception();
        }
    }
}

使用该工厂并为应用程序配置自定义服务容器:

var host = new hostbuilder().useserviceproviderfactory<servicecontainer>(new servicecontainerfactory())
    .configurecontainer<servicecontainer>((hostcontext, container) =>{
})

8.扩展性

在ihostbuilder上使用扩展方法实现主机扩展性。应用程序建立usehostedservice扩展方法,以注册在t中传递的托管服务:

public static class extensions
{
    public static ihostbuilder usehostedservice<t>(this ihostbuilder hostbuilder)
        where t : class, ihostedservice, idisposable
    {
        return hostbuilder.configureservices(services =>
            services.addhostedservice<t>());
    }
}

9.管理主机

ihost实现负责启动和停止由服务容器中注册的ihostedservice实现。

9.1run

run运行应用程序并阻止调用线程,直到关闭主机:

public class program
{
    public void main(string[] args)
    {
        var host = new hostbuilder().build();
        host.run();
    }
}

9.2runasync

runasync运行应用程序并返回在触发取消令牌或关闭时完成的task:

public class program
{
    public static async task main(string[] args)
    {
        var host = new hostbuilder().build();
        await host.runasync();
    }
}

9.3runconsoleasync

runconsoleasync启用控制台、生成和启动主机,以及等待ctrl+c/sigint或sigterm关闭。

public class program
{
    public static async task main(string[] args)
    {
        var hostbuilder = new hostbuilder();
        await hostbuilder.runconsoleasync();
    }
}

9.4start和stopasync

start同步启动主机。stopasync尝试在提供的超时时间内停止主机。

public class program
{
    public static async task main(string[] args)
    {
        var host = new hostbuilder().build();
        using (host)
        {
            host.start();
            await host.stopasync(timespan.fromseconds(5));
        }
    }
}

9.5startasync和stopasync

startasync启动应用程序。stopasync停止应用程序。

public class program
{
    public static async task main(string[] args)
    {
        var host = new hostbuilder().build();
        using (host)
        {
            await host.startasync();
            await host.stopasync();
        }
    }
}

9.6waitforshutdown

waitforshutdown通过ihostlifetime触发,例如consolelifetime(侦听ctrl+c/sigint或sigterm)。waitforshutdown调用stopasync。

public class program
{
    public void main(string[] args)
    {
        var host = new hostbuilder().build();
        using (host)
        {
            host.start();
            host.waitforshutdown();
        }
    }
}

9.7waitforshutdownasync

waitforshutdownasync返回在通过给定的令牌和调用stopasync来触发关闭时完成的task。

public class program
{
    public static async task main(string[] args)
    {
        var host = new hostbuilder().build();
        using (host)
        {
            await host.startasync();
            await host.waitforshutdownasync();
        }
    }
}

9.8external control(外部控件)

public class program
{
    private ihost _host;
    public program()
    {
        _host = new hostbuilder()
            .build();
    }
    public async task startasync()
    {
        _host.startasync();
    }
    public async task stopasync()
    {
        using (_host)
        {
            await _host.stopasync(timespan.fromseconds(5));
        }
    }
}

在startasync开始时调用waitforstartasync,在继续之前,会一直等待该操作完成。它可用于延迟启动,直到外部事件发出信号。

10.ihostingenvironment、iapplicationlifetime接口

该两个接口类型跟上一篇web主机ihostingenvironment、iapplicationlifetime接口类型是一样的,详情就不在这多讲了,想要了解的请移步到上一篇web主机文章。

参考文献:
asp.net core 通用主机