[英]What is causing my ASP.NET MVC app to stop emailing and recycling the app pool to immediately fix it?
[英]Are the benefits to using background workers in ASP.NET if there isn't app recycling?
背景:我有一个简单的 ASP.NET Core 3.1 站点。 在极少数情况下(每周三到四次),用户可能会填写一个触发 email 发送的表单。
我不想在运行“发送电子邮件”操作时延迟页面响应(即使只需要一两秒钟),所以从我读过的所有内容来看,似乎应该处理 email 的代码应该是后台工作人员/托管服务,并且 Razor 页面代码应将要发送的数据 object 放在由后台服务监控的集合中。
我不完全理解的是为什么这在现代ASP.NET 内核中是必要的。
如果我在普通的 C# 应用程序(不是 ASP)中执行此操作,我只需使“发送电子邮件”方法异步(它使用具有异步方法的 MailKit),并在不等待的情况下调用异步方法,允许工作在线程池上完成,同时允许响应线程继续。
但是现有的答案和博客文章说,在 ASP 中调用没有等待的异步方法是危险的,因为 IIS 可以重新启动 ASP 进程(应用程序池回收)。
然而,当 memory 泄漏很常见时,我读过的大多数内容都说应用程序回收是旧 ASP 的产物,而这在.Net Core 上并不是真正的事情。 此外,许多 ASP 应用程序甚至不再托管在 IIS 中。
此外,据我所知,IHostedService/Background Worker 对象并没有做任何特别的事情——它们似乎没有添加任何额外的线程; 它们看起来就像单例,有额外的环境启动和关闭通知。
所以:
编辑:我承认,当有可能终止操作时,开始一项任务并向用户报告成功是一种糟糕的形式。 收到关闭通知并能够完成任务是有好处的。
也许更好的问题是,现代 ASP 中是否仍然存在旧的循环行为(在 IIS 或 Kestrel 上)? 是否有其他原因可能会触发有序关闭(服务器关闭/手动停止除外)?
我仍然认为这是一种糟糕的做法。
这里和参考文章中的主要关注点主要是关于任务完成的 promise。
在不知道幽灵后台任务的情况下,运行时将无法通知任务正常停止。 这可能会也可能不会导致严重问题,具体取决于终止发生时的任务状态。
使用火忘记任务通常意味着,当进程重新启动时,您的任务有不得不重新开始的风险。 有时由于上下文丢失,这是不可能的。 想象一下,您的 fire-forget 任务正在调用另一个 web API ,其参数由 web 请求提供。 如果进程重新启动,这些参数可能会从 memory 中删除。
请记住,回收并不总是由 IIS / 服务器触发。 它也可能由人触发。 假设当您的应用程序遇到 memory 泄漏问题时,您可能希望每 1 小时回收一次应用程序进程作为临时缓解措施。 然后你需要确保你不会破坏你的后台任务。
在托管方面- 仍然可以在进程中托管 ASP.Net Core 应用程序,其中应用程序池在配置的时间段或默认 29 小时后由 IIS 回收。
就生命周期而言,托管服务是您向 DI 注册的类型,因此可以使用 DI 功能,例如, 此内置托管服务实现了IDisposable
,这意味着可以在关闭时进行适当的清理。
坦率地说,后台任务和托管服务都可以让您一劳永逸。 但是,当您需要可靠性和弹性时,托管服务会胜出。
为了回答您问题的后半部分,该应用程序将等待所有托管服务的StopAsync
方法完成,然后再关闭。 只要您在托管服务中await
您的Task
,这实际上意味着您可以假设您的Task
将被允许在应用程序关闭之前完成运行。 该应用程序仍然可以强制关闭,在这种情况下,不再有任何保证。
如果您需要有关后台任务的更多保证,则应将它们移动到单独的进程中运行。 您可以使用Runly之类的东西来更轻松地将功能分解为后台作业。 它还可以轻松地向用户提供实时反馈,这样当您在后台运行时说“一切都已完成”时,您就不会对用户撒谎。
全面披露:我共同创立了 Runly。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.