背景
当我们做项目的时候,有时候希望自己的ASP.NET Core应用在启动前执行一些初始化逻辑。例如,你希望验证配置是否合法,填充缓存数据,或者运行数据库迁移脚本。在本篇博客中,我将介绍几种可选的方案,并且通过展示一些简单的方法和扩展点来说明我想要解决的问题。
开始我将先描述一下ASP.NET Core内置的解决方案,使用IStartupFilter
来运行同步任务。然后我将描述几种可选的执行异步任务的方案。你可以(但是可能不应该这样做)使用IStartupFilter
或者IApplicationLifetime
事件来执行异步任务。你也可以使用IHostService
接口来运行一次性任务且不会阻塞ASP.NET Core应用启动。最后唯一合理的方案是在program.cs
文件中手动运行任务。在下一篇博客中,我会展示一个可以简化这个流程的推荐方案。
为什么我们需要在程序启动时运行异步任务?
在程序启动,开始监听请求之前,运行一些初始化代码是非常普遍的。对于一个ASP.NET Core应用程序,启动前有许多任务需要运行,例如:
- 确定当前的托管环境
- 从appsetting.json文件和环境变量中读取配置
- 配置依赖注入容器
- 构建依赖注入容器
- 配置中间件管道
以上几步都四发生在应用程序引导时。然而有些一次性任务需要在WebHost
启动,监听请求前运行。例如
- 检查强类型配置是否合法
- 使用数据库或者API填充缓存
- 运行数据库迁移脚本(这通常不是一个很好的方案,但是对于一些应用来说够用了)
有些时候,一些任务并不是非要在程序启动,监听请求前运行。这里我们以填充缓存为例,如果它是设计的比较好的话,在程序启动前是否填充缓存数据是无关紧要的。但是,相对的,你肯定也希望在应用程序开始监听请求之前,迁移你的数据库!
其实ASP.NET Core框架自己也需要运行一些一次性初始化任务。这个最好的例子就是数据保护,它常用来做数据加密,这个模块必须要在应用启动前初始化。为了实现初始化,它们使用了IStartupFilter
。
使用IStartupFilter
来运行同步任务
在之前的博客中,我已经介绍过IStartupFilter
, 它是一个自定义ASP.NET Core应用的强力接口。
如果你是第一次接触Filter, 我建议你去我之前的博客,这里我只会提供一个简短的总结。
IStartupFilter
会在配置中间件管道的进程中被执行(通常在Startup.Configure()
中完成)。它们允许你通过插入额外的中间件,分叉或执行任何其他操作来自定义应用程序实际创建的中间件管道。例如下面代码展示的AutoRequestServiceStartupFilter
public class AutoRequestServicesStartupFilter : IStartupFilter
{
public Action<IApplicationBuilder> Configure(Action<IAppl