在Java Web应用程序中运行常规后台事件
在第15个播客中,杰夫提到他在Twitter上发布了有关如何在后台运行常规事件的推特,但不幸的是,这似乎是正常功能,我似乎无法通过Twitter找到它。现在,我需要做类似的事情,并将这个问题提交给大众。
我当前的计划是,当第一个用户(可能是我)进入站点时,它会启动一个后台线程,该线程等待直到分配的时间(每小时一小时),然后启动阻止其他人的事件(我是Windows程序员)我认为就事件和WaitOnMultipleObjects而言,直到完成为止。
Jeff是如何在Asp.Net中做到这一点的,并且他的方法适用于Java Web应用程序世界吗?
解决方案
回答
Jeff的机制是创建某种缓存对象,ASP.Net将按某种间隔自动重新创建它。这似乎是ASP.Net特定的解决方案,因此在Java世界中可能对我们(或者我)没有多大帮助。
参见https://stackoverflow.fogbugz.com/default.asp?W13117
Atwood: Well, I originally asked on Twitter, because I just wanted something light weight. I really didn't want to like write a windows service. I felt like that was out of band code. Plus the code that actually does the work is a web page in fact, because to me that is a logical unit of work on a website is a web page. So, it really is like we are calling back into the web site, it's just like another request in the website, so I viewed it as something that should stay inline, and the little approach that we came up that was recommended to me on Twitter was to essentially to add something to the application cache with a fixed expiration, then you have a call back so when that expires it calls a certain function which does the work then you add it back in to the cache with the same expiration. So, it's a little bit, maybe "ghetto" is the right word.
我的方法一直是必须操作系统(例如Cron或者Windows任务计划程序)以一定的间隔加载特定的URL,然后在该URL上设置页面以检查其队列,并执行所需的任何任务,有兴趣了解是否有更好的方法。
从成绩单看,FogBugz似乎也在使用Windows服务加载URL方法。
Spolsky: So we have this special page called heartbeat.asp. And that page, whenever you hit it, and anybody can hit it at anytime: doesn't hurt. But when that page runs it checks a queue of waiting tasks to see if there's anything that needs to be done. And if there's anything that needs to be done, it does one thing and then looks in that queue again and if there's anything else to be done it returns a plus, and the entire web page that it returns is just a single character with a plus in it. And if there's nothing else to be done, the queue is now empty, it returns a minus. So, anybody can call this and hit it as many times, you can load up heartbeat.asp in your web browser you hit Ctrl-R Ctrl-R Ctrl-R Ctrl-R until you start getting minuses instead of pluses. And when you've done that FogBugz will have completed all of its maintenance work that it needs to do. So that's the first part, and the second part is a very, very simple Windows service which runs, and its whole job is to call heartbeat.asp and if it gets a plus, call it again soon, and if it gets a minus call it again, but not for a while. So basically there's this Windows service that's always running, that has a very, very, very simple task of just hitting a URL, and looking to see if it gets a plus or a minus and, and then scheduling when it runs again based on whether it got a plus or a minus. And obviously you can do any kind of variation you want on this theme, like for example, uh you could actually, instead of returning just a plus or minus you could say "Okay call me back in 60 seconds" or "Call me back right away I have more work to be done." And that's how it works... so that maintenance service it just runs, you know, it's like, you know, a half page of code that runs that maintenance service, and it never has to change, and it doesn't have any of the logic in there, it just contains the tickling that causes these web pages to get called with a certain guaranteed frequency. And inside that web page at heartbeat.asp there's code that maintains a queue of tasks that need to be done and looks at how much time has elapsed and does, you know, late-night maintenance and every seven days delete all the older messages that have been marked as spam and all kinds of just maintenance background tasks. And uh, that's how that does that.
回答
他们在StackOverflow.com上的操作方法如下:
http://blog.stackoverflow.com/2008/07/easy-background-tasks-in-aspnet/
回答
我认为开发用于运行后台任务的自定义解决方案并不总是值得的,因此我建议在Java中使用Quartz Scheduler。
在情况下(需要在Web应用程序中运行后台任务),可以使用分发中包含的ServletContextListener在Web容器启动时初始化引擎。
之后,我们有多种可能性来启动(触发)后台任务(工作),例如我们可以使用日历或者类似cron的表达式。在情况下,我们很可能应该使用SimpleTrigger来解决该问题,该技术可以使我们以固定的固定间隔运行作业。
作业本身也可以在Quartz中轻松描述,但是我们尚未提供有关所需运行内容的任何详细信息,因此我无法在该领域提供建议。
回答
如前所述,Quartz是一种标准解决方案。如果我们不关心重新启动时后台任务的群集或者持久性,则可以使用内置的ThreadPool支持(在Java 5,6中)。如果使用ScheduledExecutorService,则可以将Runnables放入后台线程池中,这些线程在执行之前要等待特定的时间。
如果我们确实关心集群和/或者持久性,则可以使用JMS队列进行异步执行,尽管我们仍然需要某种方式来延迟后台任务(可以使用Quartz或者ScheduledExecutorService来执行此操作)。
回答
我们将jtcron用于计划的后台任务。
它运作良好,而且,如果我们了解cron,对我们来说应该很有意义。