2008-09-07 108 views
8

在播客#15中,Jeff提到他在关于如何在后台运行常规事件,好像这是一个正常功能 - 很不幸,我似乎无法通过twitter 。现在我需要做一个类似的事情,并且会把问题提交给群众。在Java Web应用程序中运行常规后台事件

我目前的计划是当第一个用户(可能是我)进入网站时,它启动一个后台线程,等待分配时间(小时小时),然后开始阻止其他人的事件(我是Windows程序员通过交易,所以我认为在事件和WaitOnMultipleObjects方面),直到它完成。

Jeff是如何在Asp.Net中完成的,他的方法是否适用于Java Web应用程序世界?

回答

12

我认为开发运行的后台任务并不总是值得的定制解决方案,所以我建议使用在Quartz Scheduler Java的。

在您的情况下(需要在Web应用程序中运行后台任务),您可以使用包含在initialize the engine at the startup of your web container分配中的ServletContextListener。

之后,您有很多可能性来启动(触发)您的后台任务(作业),例如,您可以使用日历或类似cron的表达式。在你的情况下,你很可能应该用SimpleTrigger来解决,让你以固定的时间间隔运行工作。

在Quartz中,作业本身也可以很容易地描述,但是你还没有提供任何关于你需要运行的细节,所以我不能提供这方面的建议。

3

Jeff的机制是创建某种缓存对象,ASP.Net会在某种间隔时自动重新创建 - 它似乎是一个ASP.Net特定的解决方案,因此可能无法帮助您(或我)很多在Java世界。

https://stackoverflow.fogbugz.com/default.asp?W13117

阿特伍德:嗯,我本来要求在Twitter上,因为我想要的东西,重量轻。我真的不想写一个Windows服务。我觉得那是带外代码。再加上实际上这项工作的代码实际上是一个网页,因为对我而言,这是一个网站上的逻辑工作单位,就是一个网页。所以,这就好像我们回到网站上,就像网站上的另一个请求一样,所以我认为它应该保持内联,并且我们在Twitter上推荐给我们的那种小方法本质上是要在应用程序缓存中添加一些固定到期的应用程序,然后你有一个回调,所以当它过期时,它会调用一个特定的函数来完成这项工作,然后你将它添加到缓存中,并且过期时间相同。所以,这是一点点,也许“贫民窟”是正确的话。

我的做法一直是有操作系统(即cron或Windows任务调度程序)在某个区间在那个URL加载一个特定的URL,然后设置一个网页,以检查它的队列,并执行任何任务是需要,但我很想听听有没有更好的方法。

从成绩单,它看起来像FogBugz也使用加载URL方法的Windows服务。

Spolsky:所以我们有这个特殊的页面叫做heartbeat.asp。那页,每当你打它,任何人都可以在任何时候打它:不伤。但是当页面运行时,它会检查一个等待任务队列,看看是否有任何需要完成的任务。如果有任何需要完成的事情,它会做一件事,然后再次查看该队列,如果还有其他事情要做,它会返回一个加号,并且它返回的整个网页只是一个带有加号的单个字符在里面。如果没有其他工作要做,队列现在是空的,它返回一个减号。所以,任何人都可以调用它并多次点击它,你可以在你的网页浏览器中加载heartbeat.asp,你按Ctrl-R Ctrl-R Ctrl-R Ctrl-R直到你开始变得不重要。当你完成后,FogBugz将完成它需要完成的所有维护工作。所以这是第一部分,第二部分是一个非常非常简单的Windows服务,它的全部工作是调用heartbeat.asp,如果它得到一个加号,很快再调用它,并且如果它得到一个减号调用它再次,但不是一段时间。所以基本上这个Windows服务总是在运行,它有一个非常非常非常简单的任务,只需点击一个URL,并查看它是否得到一个加号或一个减号,然后根据是否再次运行它有一个加号或一个减号。显然你可以在这个主题上做任何你想要的变体,比如,例如,你实际上可以,而不是只返回一个加号或减号,你可以说“好吧,在60秒内给我回电话”或者“我有更多的工作要做。“这就是它的工作原理...所以它只是运行维护服务,你知道,它就像是运行维护服务的代码的半页,它永远不会改变,它没有任何的逻辑,它只包含使得这些网页以某种保证的频率被调用的挠痒痒。在heartbeat.asp的网页中,有一些代码需要维护一个需要完成的任务队列,并查看已经过了多少时间,并且您知道,深夜维护和每七天都会删除所有旧的消息已被标记为垃圾邮件和各种维护后台任务。呃,那就是这样。

5

如前所述,Quartz是一个标准的解决方案。如果您不关心跨重新启动时的后台任务的集群或持久性,您可以使用内置的ThreadPool支持(Java 5,6)。如果您使用ScheduledExecutorService,则可以将Runnables放入后台线程池,该池在执行之前会等待特定时间。

如果您关心集群和/或持久性,您可以使用JMS队列进行异步执行,尽管您仍然需要某种延迟后台任务的方式(您可以使用Quartz或ScheduledExecutorService来执行此操作)。

2

我们使用jtcron作为我们的预定后台任务。 它运作良好,如果你了解cron,它应该对你有意义。