运行计划任务的最佳方式
今天,我们构建了一个控制台应用程序来运行 ASP.NET 网站的计划任务。但我认为这种方法有点容易出错并且难以维护。如何执行计划任务(在 Windows/IIS/ASP.NET 环境中)
更新:
任务示例:
- 从数据库中的电子邮件队列发送电子邮件 从数据库中
- 删除过时的对象 从
- Google AdWords 检索统计信息并填充表格在数据库中。
Today we have built a console application for running the scheduled tasks for our ASP.NET website. But I think this approach is a bit error prone and difficult to maintain. How do you execute your scheduled task (in an windows/IIS/ASP.NET environment)
Update:
Examples of tasks:
- Sending email from an email-queue in the database
- Removing outdated objects from the database
- Retrieving stats from Google AdWords and fill a table in the database.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(16)
Jeff Atwood 为 Stackoverflow 开发的这项技术是我遇到过的最简单的方法穿过。它依赖于 ASP.NET 缓存系统中内置的“缓存项已删除”回调机制
更新:Stackoverflow 已经无法满足此方法的需求。它仅在网站运行时起作用,但这是一种非常简单的技术,对很多人来说都很有用。
另请查看 Quartz.NET
This technique by Jeff Atwood for Stackoverflow is the simplest method I've come across. It relies on the "cache item removed" callback mechanism build into ASP.NET's cache system
Update: Stackoverflow has outgrown this method. It only works while the website is running but it's a very simple technique that is useful for many people.
Also check out Quartz.NET
我的网站的所有任务(需要安排)都保存在网站内,并从一个特殊页面调用。然后我编写了一个简单的 Windows 服务,它经常调用此页面。一旦页面运行,它就会返回一个值。如果我知道还有更多工作要做,我会立即再次运行该页面,否则我会稍后运行它。这对我来说非常有效,并将我的所有任务逻辑与网络代码保持在一起。在编写简单的Windows服务之前,我使用Windows调度程序每x分钟调用一次页面。
运行此功能的另一种便捷方法是使用监控服务,例如 Pingdom。将他们的 http 检查指向运行您的服务代码的页面。让页面返回结果,然后可以在出现问题时触发 Pingdom 发送警报消息。
All of my tasks (which need to be scheduled) for a website are kept within the website and called from a special page. I then wrote a simple Windows service which calls this page every so often. Once the page runs it returns a value. If I know there is more work to be done, I run the page again, right away, otherwise I run it in a little while. This has worked really well for me and keeps all my task logic with the web code. Before writing the simple Windows service, I used Windows scheduler to call the page every x minutes.
Another convenient way to run this is to use a monitoring service like Pingdom. Point their http check to the page which runs your service code. Have the page return results which then can be used to trigger Pingdom to send alert messages when something isn't right.
创建自定义 Windows 服务。
我将一些关键任务设置为预定的控制台应用程序,但发现它们很难维护。我创建了一个带有“心跳”的 Windows 服务,它每隔几分钟检查一次数据库中的计划。效果非常好。
话虽如此,我仍然使用计划的控制台应用程序来执行大多数非关键维护任务。如果它没有坏,就不要修理它。
Create a custom Windows Service.
I had some mission-critical tasks set up as scheduled console apps and found them difficult to maintain. I created a Windows Service with a 'heartbeat' that would check a schedule in my DB every couple of minutes. It's worked out really well.
Having said that, I still use scheduled console apps for most of my non-critical maintenance tasks. If it ain't broke, don't fix it.
我发现这对于所有相关人员来说都很容易:
使用这种方法,所有业务逻辑都包含在您的 Web 应用程序中,但您可以使用 Windows 任务管理器或任何其他商业任务管理器来启动它并记录任何返回信息(例如执行报告)。使用 Web 服务而不是发布到页面有一些优势,因为从 Web 服务获取返回数据更容易。
I've found this to be easy for all involved:
Using this methodology all of the business logic is contained in your web app, but you have the reliability of the windows task manager, or any other commercial task manager to kick it off and record any return information such as an execution report. Using a web service instead of posting to a page has a bit of an advantage because it's easier to get return data from a webservice.
为什么要重新发明轮子,使用Threading和Timer类。
Why reinvent the wheel, use the Threading and the Timer class.
使用 Windows Scheduler 运行网页。
为了防止恶意用户或搜索引擎蜘蛛运行它,当您设置计划任务时,只需使用查询字符串调用网页,即: mypage.aspx?from=scheduledtask
然后在页面加载中,只需使用一个条件:
if (Request.Querystring["from"] == "scheduledtask")
{
//执行任务
这样
,搜索引擎蜘蛛或恶意用户将无法执行您的计划任务。
Use Windows Scheduler to run a web page.
To prevent malicous user or search engine spiders to run it, when you setup the scheduled task, simply call the web page with a querystring, ie : mypage.aspx?from=scheduledtask
Then in the page load, simply use a condition :
if (Request.Querystring["from"] == "scheduledtask")
{
//executetask
}
This way no search engine spider or malicious user will be able to execute your scheduled task.
这个图书馆很有魅力
http://www.codeproject.com/KB/cs/tsnewlib.aspx
它允许您直接通过 .NET 代码管理 Windows 计划任务。
This library works like a charm
http://www.codeproject.com/KB/cs/tsnewlib.aspx
It allows you to manage Windows scheduled tasks directly through your .NET code.
此外,如果您的应用程序使用 SQL SERVER,您可以使用 SQL 代理来安排您的任务。这是我们通常放置数据驱动的重复出现代码的地方(电子邮件提醒、计划维护、清除等)。 SQL 代理内置的一个很棒的功能是失败通知选项,它可以在关键任务失败时向您发出警报。
Additionally, if your application uses SQL SERVER you can use the SQL Agent to schedule your tasks. This is where we commonly put re-occurring code that is data driven (email reminders, scheduled maintenance, purges, etc...). A great feature that is built in with the SQL Agent is failure notification options, which can alert you if a critical task fails.
我不确定你指的是哪种计划任务。如果您的意思是“每小时刷新 foo.xml”类型的任务,那么请使用 Windows 计划任务系统。 (“at”命令,或通过控制器。)让它运行控制台应用程序或请求启动进程的特殊页面。
编辑:我应该补充一点,这也是让 IIS 应用程序按计划运行的好方法。因此,假设您希望每 30 分钟检查一次数据库,并向用户发送有关某些数据的电子邮件提醒,您可以使用计划任务来请求此页面,从而让 IIS 处理事务。
如果您的需求更复杂,您可以考虑创建一个 Windows 服务并让它运行一个循环来执行您需要的任何处理。这还具有出于扩展或管理目的而分离代码的好处。不利的一面是,您需要处理 Windows 服务。
I'm not sure what kind of scheduled tasks you mean. If you mean stuff like "every hour, refresh foo.xml" type tasks, then use the Windows Scheduled Tasks system. (The "at" command, or via the controller.) Have it either run a console app or request a special page that kicks off the process.
Edit: I should add, this is an OK way to get your IIS app running at scheduled points too. So suppose you want to check your DB every 30 minutes and email reminders to users about some data, you can use scheduled tasks to request this page and hence get IIS processing things.
If your needs are more complex, you might consider creating a Windows Service and having it run a loop to do whatever processing you need. This also has the benefit of separating out the code for scaling or management purposes. On the downside, you need to deal with Windows services.
如果您拥有服务器,则应该使用 Windows 任务计划程序。使用AT /?从命令行查看选项。
否则,在基于 Web 的环境中,您可能必须做一些令人讨厌的事情,例如设置不同的计算机以按时间间隔向特定页面发出请求。
If you own the server you should use the windows task scheduler. Use AT /? from the command line to see the options.
Otherwise, from a web based environment, you might have to do something nasty like set up a different machine to make requests to a certain page on a timed interval.
我已经在 ASP.NET 项目中成功使用了 Abidar (这里有一些背景信息)。
此方法的唯一问题是,如果从内存中卸载 ASP.NET Web 应用程序(即由于使用率低),任务将不会运行。我尝试过的一件事是创建一个任务,每 5 分钟访问一次 Web 应用程序,使其保持活动状态,但这似乎工作不可靠,所以现在我使用 Windows 调度程序和基本控制台应用程序来执行此操作。
理想的解决方案是创建 Windows 服务,尽管这可能是不可能的(即,如果您使用的是共享托管环境)。从维护的角度来看,将事物保留在 Web 应用程序中也让事情变得更容易。
I've used Abidar successfully in an ASP.NET project (here's some background information).
The only problem with this method is that the tasks won't run if the ASP.NET web application is unloaded from memory (ie. due to low usage). One thing I tried is creating a task to hit the web application every 5 minutes, keeping it alive, but this didn't seem to work reliably, so now I'm using the Windows scheduler and basic console application to do this instead.
The ideal solution is creating a Windows service, though this might not be possible (ie. if you're using a shared hosting environment). It also makes things a little easier from a maintenance perspective to keep things within the web application.
这是另一种方法:
1) 创建一个“心跳”Web 脚本,负责在任务到期或逾期启动时启动任务。
2) 在某处(最好在同一 Web 服务器上)创建一个计划进程,该进程会命中 Web 脚本并强制其定期运行。 (例如,使用 IE 或 Whathaveyou 悄悄启动 heatbeat 脚本的 Windows 计划任务)
任务代码包含在 Web 脚本中的事实纯粹是为了将代码保留在 Web 应用程序代码中 - base(假设两者相互依赖),这对于 Web 开发人员来说更容易管理。
另一种方法是创建一个可执行的服务器脚本/程序,它本身完成所有计划工作,并将可执行文件本身作为计划任务运行。这可以实现 Web 应用程序和计划任务之间的根本解耦。因此,如果您需要计划的任务即使在 Web 应用程序/数据库可能已关闭或无法访问的情况下也能运行,您应该采用这种方法。
Here's another way:
1) Create a "heartbeat" web script that is responsible for launching the tasks if they are DUE or overdue to be launched.
2) Create a scheduled process somewhere (preferrably on the same web server) that hits the webscript and forces it to run at a regular interval. (e.g. windows schedule task that quietly launches the heatbeat script using IE or whathaveyou)
The fact that the task code is contained within a web script is purely for the sake of keeping the code within the web application code-base (the assumption is that both are dependent on each other), which would be easier for web developers to manage.
The alternate approach is to create an executable server script / program that does all the schedule work itself and run the executable itself as a scheduled task. This can allow for fundamental decoupling between the web application and the scheduled task. Hence if you need your scheduled tasks to run even in the even that the web app / database might be down or inaccessible, you should go with this approach.
您可以使用“ThreadPool.RegisterWaitForSingleObject”方法轻松创建一个定期运行代码的 Windows 服务。它真的很光滑而且很容易设置。与使用框架中的任何计时器相比,此方法是一种更简化的方法。
请查看下面的链接以获取更多信息:
使用 Windows 服务在 .NET 中运行定期进程:
http://allen-conway -dotnet.blogspot.com/2009/12/running-periodic-process-in-net-using.html
You can easily create a Windows Service that runs code on interval using the 'ThreadPool.RegisterWaitForSingleObject' method. It is really slick and quite easy to get set up. This method is a more streamlined approach then to use any of the Timers in the Framework.
Have a look at the link below for more information:
Running a Periodic Process in .NET using a Windows Service:
http://allen-conway-dotnet.blogspot.com/2009/12/running-periodic-process-in-net-using.html
我们也使用控制台应用程序。如果您使用 Log4net 等日志记录工具,您可以正确监控它们的执行情况。另外,我不确定它们如何比网页更难维护,因为如果设计正确的话,您可能会在两者之间共享一些相同的代码库。
如果您反对定时运行这些任务,您可以在网站的管理部分设置一个网页来充当队列。用户发出运行任务的请求,它又在 MyProcessQueue 表中插入一条空白日期戳记录,并且您的计划任务每 X 分钟检查一次 MyProcessQueue 中的新记录。这样,它仅在客户希望它运行时运行。
希望这些建议有所帮助。
We use console applications also. If you use logging tools like Log4net you can properly monitor their execution. Also, I'm not sure how they are more difficult to maintain than a web page, given you may be sharing some of the same code libraries between the two if it is designed properly.
If you are against having those tasks run on a timed basis, you could have a web page in your administrative section of your website that acts as a queue. User puts in a request to run the task, it in turn inserts a blank datestamp record on MyProcessQueue table and your scheduled task is checking every X minutes for a new record in MyProcessQueue. That way, it only runs when the customer wants it to run.
Hope those suggestions help.
一种选择是设置一个 Windows 服务并让它调用您的计划任务。
在 winforms 中,我使用了计时器,但认为这在 ASP.NET 中效果不佳
One option would be to set up a windows service and get that to call your scheduled task.
In winforms I've used Timers put don't think this would work well in ASP.NET
用于 .NET 的新任务计划程序类库
注意:自创建此库以来,Microsoft 为 Windows Vista 引入了新的任务计划程序 (Task Scheduler 2.0)。该库是任务计划程序 1.0 界面的包装器,该界面在 Vista 中仍然可用,并且与 Windows XP、Windows Server 2003 和 Windows 2000 兼容。
http://www.codeproject.com/KB/cs/tsnewlib.aspx
A New Task Scheduler Class Library for .NET
Note: Since this library was created, Microsoft has introduced a new task scheduler (Task Scheduler 2.0) for Windows Vista. This library is a wrapper for the Task Scheduler 1.0 interface, which is still available in Vista and is compatible with Windows XP, Windows Server 2003 and Windows 2000.
http://www.codeproject.com/KB/cs/tsnewlib.aspx