2014-10-27 57 views
2

我有一个Play 2.3项目,我需要安排一个动作,每整整一个小时一次,所以我使用Akka将其安排在Global.onStart中。这个动作完全需要不到1个小时的时间(它会检查数据库中的潜在更新,然后根据它们执行一些Web请求)。Play Framework/Akka调度器延迟漂移

但是,每次除第一次运行外,都会延迟1秒。所以在60小时/更新之后,它会延迟一整分钟,大概在9个月后它会被延迟一个小时。

起初我试着将频率设置为(60 * 60) - 1秒,它起初工作,但有时它会抵消,最终它运行得太晚。

看来,频率不开始倒计时(可以这么说),直到行动完成,这导致了这种延迟,所以我能做些什么来防止这种漂移?

这里我要计算延迟和调度操作的代码:

// Time until next full hour 
static public FiniteDuration getDelay() 
{ 
    Calendar currentCalendar = Calendar.getInstance(); 

    long minute = currentCalendar.get(Calendar.MINUTE); 
    long second = currentCalendar.get(Calendar.SECOND); 
    long ms = currentCalendar.get(Calendar.MILLISECOND); 

    minute = (60L - minute) * 60 * 1000; 
    second = (60 - second) * 1000; 
    ms = 1000L - ms; 

    long delay = minute + second + ms; 

    return FiniteDuration.create(delay, TimeUnit.MILLISECONDS); 
} 

// Update once every 60 minutes 
static public FiniteDuration getFrequency() 
{ 
    return FiniteDuration.create(60, TimeUnit.MINUTES); 
} 

Akka.system().scheduler() 
    .schedule(getDelay(), getFrequency(), 
    Publisher.makeRunnable(), Akka.system().dispatcher()); 
+0

这个答案http://stackoverflow.com/questions/14145186/akka-scheduler-is-late-on-every-repeat这似乎是关于相同的问题声称,这是一个问题已被修复阿卡2.1 ,但我使用的是Play 2.3(不知道如何检查我使用的Akka版本,但我相信这是更晚的版本),而且这个问题仍然存在。 – tacospice 2014-10-27 08:50:51

+0

玩2.3使用Akka 2.3,所以你应该提交一个错误或确保你的初始延迟计算正确。 – 2014-10-27 09:03:42

+0

似乎最初的延迟不应该有很大的差异,频率应该仍然是第一次动作后,但它不是 – tacospice 2014-10-28 05:02:23

回答

1

的阿卡调度并不声称是其调度准确,因为它只是维持一个任务队列,它会检查每个“打勾”(请参阅​​this page上的警告)。如果您想要准确定位您的工作,我建议您使用类似cron的库,例如Quartz,以便您可以在正确的时间发出消息。这使您可以根据挂钟时间更精确地安排工作,而不是依赖Akka的“打勾”概念。

+0

似乎你是对的。石英做到了。谢谢! – tacospice 2014-10-30 23:05:57

+0

很高兴为你效劳! – 2014-10-31 14:31:27

0

看来你的延迟计算到最近的整点没有考虑到结转:

说,目前的时间是3:58:49.999的diff来4:00:00.000是 00:01:10.001。但是,运行您的代码将是00:02:11.001