如何在ASP.NET Core程序启动时运行异步任务(3)

原文:Running async tasks on app startup in ASP.NET Core (Part 3)

作者:Andrew Lock

译者:Lamond Lu

之前我写了两篇有关在ASP.NET Core中运行异步任务的博文,本篇博文是对之前两篇博文中演示示例和实现方法的简短跟进。

你可以通过以下链接查看之前的博文。

  • 如何在ASP.NET Core程序启动时运行异步任务(1)

  • 如何在ASP.NET Core程序启动时运行异步任务(2)

启动任务的例子

在之前博客中,我收到的最常见的反馈是关于我在描述问题时使用的例子。在我最初的博客中,我列举了3种可能场景,在这3种场景中,你希望在ASP.NET Core应用启动时运行一些异步任务。

  • 检查强类型配置是否合法

  • 使用数据库或者API填充缓存

  • 运行数据库迁移

对于前两种场景,没有任何问题,但是对于数据库迁移,一些博友提出了一些疑问。其实在两篇博文中我一直都反复说明,数据库迁移作为启动任务不是一个很好的方案,这里我只是想用它作为一个说明如何在ASP.NET Core程序启动时运行异步任务的例子。现在来看,当时使用这个例子是非常失败的。

数据库迁移是一个糟糕的选择

那么为什么在ASP.NET Core应用启动时,运行数据库迁移任务会是一个问题呢?毕竟,在应用程序开始处理请求之前,你肯定要完成数据库迁移!

其实这里其实有3个问题:

  1. 数据库迁移是应该是单线程的

  2. 迁移数据库需要更多的权限

  3. 开发人员不太喜欢直接运行数据库迁移

下面我们依次说明一下。

数据库迁移应该是单线程的

扩展一个Web应用最常用的方式之一是进行横向扩展,启动多个运行实例并使用负载均衡分发请求

640?wx_fmt=png

这种Web集群扩展的方案是非常有效的,特别是当当前应用是无状态的(请求被分发到各个应用程序中,如果一个应用程序崩溃,其他的Web应用实例依然可以处理请求)。

但是不幸的是,如果尝试将数据库迁移作为应用启动任务,你很可能就会遇到问题。如果有超过1个以上的实例同时启动,多个数据库迁移任务将同时运行。

虽然并不能保证你一定会遇到麻烦,但除非你非常小心地确保幂等更新和错误处理,否则你很可能会陷入困境。

你肯定不希望使用这种方法,因为它可能产生的数据库完整性问题。 这里一个更好的选择是先启动单个实例完成迁移操作。 这样数据库迁移任务变成一个单线程任务,自然也就避开最严重的危险。


640?wx_fmt=png


这种方法比将数据库迁移作为启动任务运行更有意义,但它更安全,更容易实现。

当然,这不是唯一的选择。 如果你对启动任务迁移的想法有所了解,那么你可以使用分布式锁来确保只有一个应用程序实例来运行迁移脚本。 然而,这并没有解决第二个问题......

迁移通常需要更多的权限

通常来说,最佳实践是你必须限制你的应用程序,以便他们只有权访问和修改所需的资源。 如果报表应用只需要读取销售数据,那么它应该无法修改它们,或者更改数据库表结构! 为指定的连接字符串配置可操作的权限,可以防止在的的应用出现安全问题时产生大量影响。

如果你正在使用Web应用程序本身来运行数据库迁移,那么该Web应用程序自然需要数据库权限才能执行高风险活动,例如修改数据库表结构,更改权限或更新/删除数据。 你真的希望您的Web应用程序能够删除你的学生表吗?


640?wx_fmt=png


同样,你可以使用一些特定的实现,例如,与正常的数据库访问相比,使用不同的连接字符串进行迁移。 但是,如果使用外部迁移过程,你根本无法锁定Web应用程序进程。

开发人员不习惯直接运行EF Core迁移

这是一个不那么明显的观点,但是很多人表示在生产环境中使用EF Core迁移工具可能不是一个好主意。

就个人而言,我已经有1年多没有在生产环境中使用EF Core迁移了,到目前为止迁移工具肯定已经有所改善。 话虽如此,我仍然看到一些问题:

  • 使用EF Core全局工具进行迁移需要安装.NET Core SDK,这在生产服务器上是不需要的。

  • 如果你想安全地更新数据库,你可能还是必须对生成的脚本进行一些编辑。 迁移后的数据库结构应与现有(运行)应用程序兼容,以避免停机。

  • 微软官方文档中暗示在应用启动时运行EF Core迁移不是一个好主意!

就我自己而言,我经常使用DbUp和FluentMigrator,而不会使用EF Core迁移。我发现它们都运行良好。

因此,如果数据库迁移任务不适合应用启动任务示例,那么哪些任务才是比较适合的呢?

比较适合作为启动任务的一些例子

虽然在之前的博文中我已经反复提到了一些例子,但我还是将在下面再次描述它们。这里其他博友还给我一些有趣的补充。

  • 检查强类型配置是否有效。ASP.NET Core 2.2引入了配置验证,但它只在首次访问IOptions <T>类时执行此操作。 正如我在之前文章中所描述的那样,你可能希望在应用启动时进行验证,以确保你的环境和配置有效。

  • 填充缓存。 你的应用程序可能需要来自文件系统或远程服务的数据,它只需要加载一次,但加载需要耗费相当多的资源,所以在应用程序启动之前加载此数据可减少请求延迟。

  • 预连接到数据库和/或外部服务。 以类似的方式,你可以通过连接到数据库或其他外部服务来填充数据库连接池。 这些通常是相对昂贵的操作,因此是很好的用例。

  • 预编译加载应用中所有的单例服务。我认为这个一个非常有趣的想法,通过预加载依赖注入容器中注册的单例服务,你可以减少请求的响应时间。

使用健康检查来完成启动任务

我完全同意有关数据库迁移的反馈。 当这不是一个好主意时,将它们用作启动任务的示例有点误导,特别是因为我个人不使用我所描述的方法!

然而,很多人都同意我所描述的另外一种方法 - 在启动Kestrel服务器和处理请求之前运行启动任务。

这里Damian Hickey针对这个方案提出了一个问题,他建议尽快启动Kestrel服务器。 他建议在所有启动任务完成后,使用运行健康检查向负载均衡器发出信号,表明应用程序已准备好开始接收请求。 与此同时,所有非健康检查流量(如果负载均衡器正在执行此任务,则不应该有任何流量)将收到503服务不可用。

这种方法的主要好处是它可以避免网络超时。 一般来说,应用程序最好能尽快的针对请求返回错误代码,而不是根本不响应请求,并导致客户端超时。 这减少了客户端所需的资源数量。 通过较早启动Kestrel服务器,应用程序可以更早地开始响应请求,即使响应是“未就绪”响应。

这实际上与我在第一篇文章中描述的方法非常相似,但是我没有选用它了,因为它太复杂了,而且没有达到我设定的目标。 从技术上来说,在那篇文章中,我只是关注在Kestrel服务器启动之前运行任务的方法,健康检查方法不能完成这个功能。

然而,Damian提出的问题让我再次思考。 在我下一篇博客中,我将描述如何使用ASP.NET Core 2.2的健康检查功能向负载均衡器发送信号,表明应用程序已经完成了所有启动任务。

总结

在这篇文章中,我分享了我之前关于在ASP.NET Core应用程序启动时运行异步任务的一些反馈。 这里最大的问题是我选择使用EF Core数据库迁移作为启动任务的示例。 数据库迁移不适合在应用程序启动时运行,因为它们通常需要由单个进程运行,并且需要比更多的数据库权限。

我提供了一些比较适合作为的启动任务的场景,并且描述了Damian给出的建议 - 尽快启动Kestrel服务器,并使用运行状况检查来指示任务何时完成。 我将在下一篇文章中描述如何实现这一功能。


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/317285.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【NET CORE微服务一条龙应用】应用部署

简介本章主要介绍https://github.com/q315523275/FamilyBucket上微服务一条龙应用&#xff0c;在实际使用中的应用部署&#xff0c;以原始方式部署非docker部署应用主要包括&#xff1a;1、网关应用部署2、授权认证应用部署3、配置中心查询服务端应用部署4、综合管理应用部署5、…

手工修复Azure DevOps无法连接到Azure的问题

点击上方蓝字关注“汪宇杰博客”今天我在为一个从TFVC迁移到Git的老项目重新配置发布到Azure App Service的CI/CD管线的时候&#xff0c;Azure DevOps竟然爆了。这是一个微软已知的bug&#xff0c;目前还未修复&#xff0c;我来带大家看看如何手工workaround这个问题。首先&…

NC14732 锁

NC14732 锁 题意&#xff1a; n个居民&#xff0c;门上有k把锁&#xff0c;每个居民有若干钥匙&#xff0c;为1到k的一个子集&#xff0c;如果几名居民的钥匙的并集是1到k&#xff0c;即他们拥有全部锁的对应钥匙。 求最小的k&#xff0c;使得可以适当地给居民们每人若干钥匙…

.NET Core实战项目之CMS 第十七章 CMS网站系统的部署

目前我们的.NET Core实战项目之CMS系列教程基本走到尾声了&#xff0c;通过这一系列的学习你应该能够轻松应对.NET Core的日常开发了&#xff01;当然这个CMS系统的一些逻辑处理还需要优化&#xff0c;如没有引入日志组件以及缓存功能&#xff0c;权限目前只支持控制到菜单&…

如何用EFCore Lazy Loading实现Entity Split

α角 与 β角支持 现实生活 的 计算机系统&#xff0c;总有着两大偏差&#xff0c;第一个是 现实生活 与 计算机系统 的α角&#xff0c;另外一个是计算机系统的 逻辑设计 与 物理设计 的β角。举个栗子&#xff1a;α角&#xff1a;假设某个公司的商业流程&#xff0c;我们在做…

.NET Core 开源项目 Anet 在路上

今天给大家介绍我刚开源的一个 .NET Core 项目&#xff1a;Anet。Anet 的目标是实现一个 .NET Core 通用库、通用框架和通用模板。我给它的定义是&#xff1a;A .NET Core Common Lib, Framework and Boilerplate.它的取名正是来自于这句话的前面四个字母&#xff1a;ANET。Ane…

模板:后缀自动机(SAM)

所谓后缀自动机&#xff0c;就是通过后缀建立的自动机 &#xff08;逃&#xff09; 请允许我先介绍一下后缀家族&#xff1a; &#xff08;又逃&#xff09; 前言 OI生涯目前为止学习的最为难以理解的算法&#xff0c;没有之一。 到现在也没有完全的理解。 qwq 概念 定义&…

.NET 开源项目 Anet 介绍

使用 Anet 有一段时间了&#xff0c;已经在我的个人网站&#xff08;如 bookist.cc&#xff09;投入使用&#xff0c;目前没有发现什么大问题&#xff0c;所以才敢写篇文章向大家介绍。GitHub 地址&#xff1a;https://github.com/anet-team/anetAnet 是一个 .NET Core 通用框架…

我的十年创业路

记十年创业的心路历程和我的创业思辨导读1 为什么写这篇文章2 详细的总结和思辨 2.01 感恩 2.02 为什么创业 2.03 十年流水账 2.04 经历了哪些失败 2.05 重要的职场基础 2.06 持续的学习和进步 2.07 创业与兴趣 2.08 价值观的碰撞和选择 2.09 合作与…

DotNetty 实现 Modbus TCP 系列 (一) 报文类

Modbus TCP/IP 报文报文最大长度为 260 byte (ADU 7 byte MBAP Header 253 byte PDU)Length Unit Identifier 长度 PDU 长度MBAP HeaderPDUPDU 由两部分构成&#xff1a;Function Code(功能码) 和 Data 组成Function Code部分功能码&#xff1a;报文类ModbusHeaderModbusHe…

专题突破三之并查集Ⅰ——Portal,parity,食物链,程序自动分析,Almost Union-Find,洞穴勘测

文章目录Portalparity[NOI2001] 食物链程序自动分析UVA11987 Almost Union-Find[SDOI2008] 洞穴勘测Portal source 百度翻译简直就是个鬼…(((m -__-)m 离线 将边和询问按权值排序&#xff0c;指针&#xff0c;将所有权值不超过当前询问iii的边全加进去 答案路径自然是不连…

C# 未来新特性:静态委托和函数指针

C# 每发布一次新版本&#xff0c;都会增加一些底层相关的新特性&#xff0c; 这些特性对大多数商业程序来说并没什么实际用处&#xff0c;主要用于那些对性能有很高要求的代码&#xff0c;如图形处理、机器学习以及数学工具包&#xff0c;等等。接下来的两个提案&#xff0c;主…

JavaWeb --第一章Web基本概念

JavaWeb --第一章Web基本概念 文章目录基本概念前言web开发&#xff1a;web应用程序静态web动态webweb服务器技术讲解web服务器基本概念 前言 web开发&#xff1a; web&#xff0c;网页的意思静态web a. html&#xff0c;css b. 提供给所有人看的数据始终不会发生改变动态we…

DotNetty 实现 Modbus TCP 系列 (二) ModbusFunction 类图及继承举例

DotNetty 实现 Modbus TCP 系列 (一) 报文类ModbusFunction 类图如下&#xff1a;如前文所述&#xff0c;所有请求/相应的 PDU 均继承自 ModbusFunction&#xff0c;其子类传入对应的 Function Code 并实现三个方法&#xff1a;CalculateLength&#xff1a;Data 部分的长度(该方…

专题突破三之并查集Ⅱ——星球大战,In Touch,方格染色,Junk-Mail Filter,关押罪犯,Silver Woods,Must Be Rectangular!

文章目录[JSOI2008]星球大战In Touch方格染色Junk-Mail Filter[NOIP2010 提高组] 关押罪犯Silver WoodsMust Be Rectangular![JSOI2008]星球大战 source 非常套路的&#xff0c;正着打击星球&#xff0c;逆着就是添加星球以及关系&#xff0c;并查集维护此时连通块个数 就是…

JavaWeb --第二章 Tomact详情

JavaWeb --第二章 Tomact详情 文章目录Tomcat安装TomcatTomcat启动和配置配置发布一个web网站Tomcat 安装Tomcat 去官方下载 https://tomcat.apache.org Tomcat启动和配置 文件夹作用&#xff1a; 启动/关闭 Tomcat&#xff1a; 文件夹bin/startup.bat 开启 网址&#x…

开源的类似于Apache ab的压力测试命令行工具SuperBenchmarker

SuperBenchmarker 是ㄧ个开源的类似于Apache ab的压力测试命令行工具。可以在 .NET 4.52 或者 .NET Core 2.0 平台上运行。可支持Get、Post、Put、Delete这些调用方式&#xff0c;调用时能指定Concurrent user、Request数、Header template…等。可以从Github、Chocolatey这两种…

如何优雅的利用Windows服务来部署ASP.NET Core程序

上一篇文章中我给大家讲述了五种部署ASP.NET Core网站的方法&#xff0c;其中有一种方式是通过Windows服务来进行部署&#xff0c;这样既可以做到开启自启动&#xff0c;又不会因为iis的反向代理而损失部分性能。但是美中不足的是需要借助第三方软件nssm来进行&#xff0c;那么…

JavaWeb --第四章Maven详解

JavaWeb --第四章Maven详解 文章目录MavenMaven架构管理工具下载安装Maven配置环境变量阿里云镜像本地仓库在IDEA中使用Maven创建一个普通的Maven项目在IDEA中标记文件夹功能在IDEA中配置tomcatpom文件IDEA操作解决遇到的问题Maven 为什么要学这个技术&#xff1f; 在javaweb…

用StyleCop规范团队代码

前言编码风格&#xff0c;每个人都是有不同的特点&#xff0c;风格各异&#xff0c;而且一个人在不同的时期&#xff0c;编码风格的差异也可能是非常大的&#xff0c;好比学生时代&#xff0c;刚工作的时候&#xff0c;工作一段时间后等。在一个团队中&#xff0c;或一个项目中…