asp.net core 3.x控制ihostedservice启动顺序浅探 -凯发k8官方网
想写好中间件,这是基础。
今天这个内容,基于于asp.net core 3.x。
从3.x开始,asp.net core使用了通用主机模式。它将webhostbuilder放到了通用的ihost之上,这样可以确保kestrel可以运行在ihostedservice中。
我们今天就来研究一下这个启动方式和启动顺序。
通常情况下,ihostedservice的任何实现在添加到startup.configureservices()后,都会在genericwebhostservice之前启动。
这是微软官方给出的图。
这个图展示了在ihost上调用runasync()时的启动顺序(后者又调用startasync())。对我们来说,最重要的部分是启动的ihostedservices。从图上也可以看到,自定义ihostedservices先于genericwebhostsevice启动。
我们来看一个简单的例子:
public class startuphostedservice : ihostedservice {private readonly ilogger _logger;public startuphostedservice(ilogger我们做一个简单的ihostedservice。希望加到startup.cs中:
public class startup {public void configureservices(iservicecollection services){services.addhostedservice运行代码:
info: demo.startuphostedservice[0] # 这是上边的startuphostedservicestarting ihostedservice registered in startup info: microsoft.hosting.lifetime[0] # 这是genericwebhostsevicenow listening on: https://localhost:5001 info: microsoft.hosting.lifetime[0]application started. press ctrl c to shut down.正如预期的那样,ihostedservice首先执行,然后是genericwebhostsevice。applicationlifetime事件在所有ihostedservices执行之后触发。无论在什么地方注册了startup.configureservices()中的ihostedservice, genericwebhostsevice都在最后启动。
那么问题来了,为什么genericwebhostsevice在最后启动?
先看看多个ihostedservice的情况。
当有多个ihostedservice的实现加入到startup.configureservices()时,运行次序取决于它被加入的次序。
看例子:
public class service1 : ihostedservice {private readonly ilogger _logger;public service1(iloggerstartup.cs:
public class startup {public void configureservices(iservicecollection services){services.addhostedservice运行:
info: demo.service1[0] # 这是service1starting service1 info: demo.service2[0] # 这是service2starting service2 info: microsoft.hosting.lifetime[0] # 这是genericwebhostsevicenow listening on: https://localhost:5001 info: microsoft.hosting.lifetime[0]application started. press ctrl c to shut down.那么,genericwebhostsevice是什么时候注册的?
我们看看另一个文件program.cs:
public class program {public static void main(string[] args){createhostbuilder(args).build().run();}public static ihostbuilder createhostbuilder(string[] args) =>host.createdefaultbuilder(args).configurewebhostdefaults(webbuilder => # 这是genericwebhostsevice注册的位置{webbuilder.usestartupconfigurewebhostdefaults扩展方法调用configurewebhost方法,该方法执行startup.configureservices(),然后注册genericwebhostservice。整理一下代码,就是下面这个样子:
public static ihostbuilder configurewebhost(this ihostbuilder builder, action这样可以确保genericwebhostservice总是最后运行,以保持通用主机实现和webhost(已弃用)实现之间的行为一致。
因此,可以采用同样的方式,让ihostedservice在genericwebhostservice后面启动。
在大多数情况下,在genericwebhostservice之前启动ihostedservices就可以满足常规的应用。但是,genericwebhostservice还负责构建应用程序的中间件管道。如果ihostedservice依赖于中间件管道或路由,那么就需要将它的启动延迟到genericwebhostservice完成之后。
根据上面的说明,在genericwebhostservice之后执行ihostedservice的唯一方法是将它添加到genericwebhostservice之后的di容器中。这意味着你必须跳出startup.configureservices(),在调用configurewebhostdefaults之后,直接在ihostbuilder上调用configureservices():
public class programhostedservice : ihostedservice {private readonly ilogger _logger;public programhostedservice(ilogger加到program.cs中:
public class program {public static void main(string[] args){createhostbuilder(args).build().run();}public static ihostbuilder createhostbuilder(string[] args) =>host.createdefaultbuilder(args).configurewebhostdefaults(webbuilder => # 这是genericwebhostsevice注册的位置{webbuilder.usestartup看输出:
info: demo.startuphostedservice[0] # 这是startuphostedservicestarting ihostedservice registered in startup info: microsoft.hosting.lifetime[0] # 这是genericwebhostsevicenow listening on: https://localhost:5001 info: demo.programhostedservice[0] # 这是programhostedservicestarting programhostedservice registered in program info: microsoft.hosting.lifetime[0]application started. press ctrl c to shut down.同样,在关闭应用时,ihostedservices被反向停止,所以programhostedservice首先停止,接着是genericwebhostsevice,最后是startuphostedservice:
info: microsoft.hosting.lifetime[0]application is shutting down... info: demo.programhostedservice[0]stopping programhostedservice registered in program info: demo.startuphostedservice[0]stopping ihostedservice registered in startup最后总结一下:
ihostedservices的执行顺序与它们在startup.configureservices()中添加到di容器中的顺序相同。运行侦听http请求的kestrel服务器的genericwebhostsevice总是注册的ihostedservices之后运行。
要在genericwebhostsevice之后启动ihostedservice,需要在program.cs中的ihostbuilder上的configureservices()扩展方法中进行注册。
(全文完)
本文的代码在:https://github.com/humornif/demo-code/tree/master/0024/demo
总结
以上是凯发k8官方网为你收集整理的的全部内容,希望文章能够帮你解决所遇到的问题。
- 上一篇: .net core 下的爬虫利器
- 下一篇: