程序化创建的EJB Timer在群集中执行的频率是多少?

时间:2012-07-04 07:39:56

标签: java java-ee timer cluster-computing

在集群JEE6环境(Glassfish 3.1.2)中,可以在每个集群节点上创建@Singleton bean。如果这个Singleton Bean在@PostConstruct上注册一个编程定时器 - @Timeout方法执行的频率是多少? - 只有一个单身人士(每个蜱),或每个Singeton注册一个计时器一次(每个蜱)?

代码下面是这个问题对此代码意味着什么的一个例子。

@Singleton
public class CachedService {

@Resource
private TimerService timerService;

    private static final long CACHE_TIMEOUT_DURATION_MS = 60 * 60 * 1000;

    @PostConstruct
    void initResetTimer() {
        this.timerService.createIntervalTimer(CACHE_TIMEOUT_DURATION_MS,
            CACHE_TIMEOUT_DURATION_MS,
            new TimerConfig("current user cache timeout", false));
    }

    @Timeout
    public void executeResetTimer() {
        this.clearCache();
    }
}

示例:应用程序在群集中的3个节点上运行。假设Singleton在每个节点上实例化,因此initResetTimer总共完成3次(每个节点一次)。那么问题是:是否每小时清除一次所有节点上的缓存(executeResetTimer被调用)?

(我知道计时器不会在所有节点上同时打勾,因为Singleton会在不同时间实例化,但这不是问题/问题。)

3 个答案:

答案 0 :(得分:3)

首先,确保按照here所述,为外部共享XA数据源设置定时器服务。

过去深入研究过你的问题,我记得邮件列表中的开发人员some explanation,Glassfish的实现如下:

  

假设您在群集中有节点A,B和C.持久计时器已创建   在节点A处由节点A“拥有”(即计时器事件被传递到   节点A)。如果节点A出现故障,则其定时器可以迁移到另一个实时节点   节点

拥有Glassfish doesn't support群集范围@Singletons,您最终会获得与initResetTimer()调用一样多的计时器。此外,每个服务器重新启动/重新部署可能会为每个群集节点创建一个新的计时器实例,此外还有旧的未删除的计时器,所以不要忘记取消以编程方式创建的计时器:)为了避免这种情况,请使用声明式@Schedule(...)方法和Glassfish将创建计时器 once across cluster ,并希望在失败时自动迁移它们。

希望这有帮助。

更新:

以编程方式创建的计时器(持久性或非持久性)将在其创建的JVM /节点中触发,而不管集群设置与否。您可以粗略总结:独立计时器实例的数量等于timer.createXxxTimer()

的调用次数

答案 1 :(得分:2)

我看了EJB 3.1规范的第18章“定时器服务”。应用程序应根据规范独立于群集运行。

我的理解是,如果在群集中调用createIntervalTimer一次,则计时器应该独立地触发群集中的节点数。由于每个单例bean(根据您的问题)调用createIntervalTimer,因此它将执行 n 次。它类似于creating timers in ServletContextListener

但这是理论。我会仔细检查您定位的特定应用服务器。在glassfish中,cluster-wide timer需要使用外部数据库配置计时器池。

答案 2 :(得分:1)

即使它不是直接的,这也无论如何都有帮助:每个集群环境只配置一个实例的一种方法是将单例ejb暴露为MXbean。 您必须公开一个托管的接口,甚至可能是空的,然后在@PostCostruct标记的方法中将您的ejb注册到jmx服务。最后,您必须提供@PreDestroy挂钩以从jmx服务取消注册。 这是Java冠军Adam Bien建议的方式。