长期运行ASP.NET的任务 [英] Long-running ASP.NET tasks

查看:196
本文介绍了长期运行ASP.NET的任务的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我知道有一堆这样做的API在那里,但我也知道,托管环境(即ASP.NET)提出限制你可以在一个单独的线程做得可靠。

I know there's a bunch of APIs out there that do this, but I also know that the hosting environment (being ASP.NET) puts restrictions on what you can reliably do in a separate thread.

我可能是完全错误的,所以请纠正我,如果我是,这不过是什么,我想我知道了。

I could be completely wrong, so please correct me if I am, this is however what I think I know.


  • 请求通常为120秒后超时(这是可配置),但最终ASP.NET运行时将封杀的时间太长完成要求。

  • 托管环境,通常是IIS,使用过程中回收和可以在任何时候决定回收您的应用程序。当这种情况发生的所有线程都中止和应用程序重新启动。我但不知道它是如何咄咄逼人,这将是一种愚蠢的假设,它会中止正在进行正常的HTTP请求,但我希望它中止线程,因为它不知道有关的任何单位一个线程的工作

  • A request typically timeouts after 120 seconds (this is configurable) but eventually the ASP.NET runtime will kill a request that's taking too long to complete.
  • The hosting environment, typically IIS, employs process recycling and can at any point decide to recycle your app. When this happens all threads are aborted and the app restarts. I'm however not sure how aggressive it is, it would be kind of stupid to assume that it would abort a normal ongoing HTTP request but I would expect it to abort a thread because it doesn't know anything about the unit of work of a thread.

如果你必须创建一个编程模式,可轻松,可靠,理论上把长时间运行的任务,那将不得不好几天跑,你将如何从ASP.NET应用程序中做到这一点?

If you had to create a programming model that easily and reliably and theoretically put a long running task, that would have to run for days, how would you accomplish this from within an ASP.NET application?

以下是我对这个问题的看法:

我一直在想在Win32服务托管WCF服务的长行。并通过WCF交谈的服务。但是,这是不是很实用,因为我会选择这样做的唯一原因,是从几个不同的Web应用程序发送任务(工作单位)。然后我终于问状态更新服务,并采取相应的行动。我与这个最大的担心是,它不会是一个特别伟大的经验,如果我不得不每一项工作部署,以服务为它能够执行一些指令。还有输入的这个问题,我将如何养活这个服务的数据,如果我有一个大的数据集,并通过它来咀嚼需要的?

I've been thinking a long the line of hosting a WCF service in a win32 service. And talk to the service through WCF. This is however not very practical, because the only reason I would choose to do so, is to send tasks (units of work) from several different web apps. I'd then eventually ask the service for status updates and act accordingly. My biggest concern with this is that it would NOT be a particular great experience if I had to deploy every task to the service for it to be able to execute some instructions. There's also this issue of input, how would I feed this service with data if I had a large data set and needed to chew through it?

我通常做的,现在是这样的。

What I typically do right now is this

SELECT TOP 10 * 
FROM WorkItem WITH (ROWLOCK, UPDLOCK, READPAST)
WHERE WorkCompleted IS NULL

这允许我使用一个SQL Server数据库作为工作队列,并定期与此查询工作轮询数据库。如果工作项目成功完成,我将其标记为已完成,并继续,直到没有什么更多的事情。我不喜欢的是,我可以在理论上在任何时候被中断,如果我在两者之间的成功和其标记为已完成,我可能最终处理相同的工作项目的两倍。我可能是有点偏执,这可能是所有罚款,但据我了解有没有保证,这不会发生...

It allows me to use a SQL Server database as a work queue and periodically poll the database with this query for work. If the work item completed with success, I mark it as done and proceed until there's nothing more to do. What I don't like is that I could theoretically be interrupted at any point and if I'm in-between success and marking it as done, I could end up processing the same work item twice. I might be a bit paranoid and this might be all fine but as I understand it there's no guarantee that that won't happen...

我知道有过类似的问题,在此之前,但非真正与一个明确的答案的答案。这是一个非常平常的事,但在ASP.NET宿主环境状态不好具备处理长期运行的工作。

I know there's been similar questions on SO before but non really answers with a definitive answer. This is a really common thing, yet the ASP.NET hosting environment is ill equipped to handle long-running work.

请分享你的看法。

推荐答案

约翰,

我同意ASP.NET不适合作为你描述他们的异步任务,也不应该。它被设计成一个网络托管平台,而不是房子处理器的背面。

I agree that ASP.NET is not suitable for Async tasks as you have described them, nor should it be. It is designed as a web hosting platform, not a back of house processor.

我们已经在过去类似的情况,我们已经采用了类似于你描述了一个解决方案。总之,让你的WCF服务ASP.NET下,使用队列表Windows服务的QueueProcessor。客户端应该轮询以查看是否工作完成(或用短信通知客户端)。

We have had similar situations in the past and we have used a solution similar to what you have described. In summary, keep your WCF service under ASP.NET, use a "Queue" table with a Windows Service as the "QueueProcessor". The client should poll to see if work is done (or use messaging to notify the client).

我们使用了包含进程表和它的信息(如InvoicingRun)。该表是一个状态(待定,正在运行,已完成,失败)。客户端将提交一份新的InvoicingRun与待定的状态。 Windows服务(处理器)将查询数据库中得到任何运行,在未决阶段(您也可以使用SQL通知,所以你不需要查询。如果发现挂起来看,这将它移动到运行,做加工,然后将其移动到已完成/失败。

We used a table that contained the process and it's information (eg InvoicingRun). On that table was a status (Pending, Running, Completed, Failed). The client would submit a new InvoicingRun with a status of Pending. A Windows service (the processor) would poll the database to get any runs that in the pending stage (you could also use SQL Notification so you don't need to poll. If a pending run was found, it would move it to running, do the processing and then move it to completed/failed.

在其中过程致命故障的情况下(例如,DB下来,过程杀死),运行将被留在运行状态,并且需要人工干预。如果进程在非致命的状态(异常错误)失败,这个过程将移至失败,可以选择重试或者有人类intervantion。

In the case where the process failed fatally (eg DB down, process killed), the run would be left in a running state, and human intervention was required. If the process failed in an non-fatal state (exception, error), the process would be moved to failed, and you can choose to retry or have human intervantion.

如果有多个处理器,第一个将其移动到运行状态得到那份工作。您可以使用此方法prevent工作被运行两次。备选是做选择,然后更新到一个事务下运行。请确保以下任一交易更大的事务之外。样品(粗糙)SQL:

If there were multiple processors, the first one to move it to a running state got that job. You can use this method to prevent the job being run twice. Alternate is to do the select then update to running under a transaction. Make sure either of these outside a transaction larger transaction. Sample (rough) SQL:

UPDATE InvoicingRun
SET Status = 2 -- Running
WHERE ID = 1
    AND Status = 1 -- Pending

IF @@RowCount = 0
    SELECT Cast(0 as bit)
ELSE
    SELECT Cast(1 as bit)

罗布

这篇关于长期运行ASP.NET的任务的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆