How often is a programmatic created EJB Timer executed in a cluster?

陌路散爱 提交于 2019-12-12 09:44:24

问题


In a clustered JEE6 environment (Glassfish 3.1.2), a @Singleton bean is/can be created on every cluster node. If this Singleton Bean registers a programmatic timer on its @PostConstruct - how often is the @Timeout method executed? -- on only one of that singletons (per tick), or once (per tick) for each Singeton that registered that a timer?

Below the code is an example what this question mean to this code.

@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();
    }
}

Example: The application runs on 3 nodes in a cluster. Assume the Singleton is instantiated on every node, so the initResetTimer is done 3 times in total (once per node). Then the question is: is the cache cleared (executeResetTimer is invoked) on all nodes once per hour or not?

(I know that the timer ticks not at the same time on all nodes, because the Singleton is instantiated at different times, but this is not the problem/question.)


回答1:


First, make sure you have setup timer-service to external shared XA datasource as described here.

Having digged into your question in past, I remember some explanation by devs in mailing-lists, that Glassfish's implementation is as follows:

Say you have node A, B and C in a cluster. Persistent timers created at node A are "owned" by node A (that is timer-events are delivered to node A). If node A fails, then its timers can be migrated to another live node.

Having that Glassfish doesn't support cluster-wide @Singletons, you end up with as many timers as calls to initResetTimer(). Moreover, each server restart/redeploy will possibly create a new instance of timer per cluster node, in additions to old uncancelled ones, so don't forget to cancel your programmatically created timers :) To avoid this alltogether use declarative @Schedule(...) approach and Glassfish will create the timer once across cluster and, hopefully, automatically migrate them on failure.

Hope this helps.

UPDATE:

A programmatically created timer, persistent or non-persistent, will be fired in the JVM/node it was created, regardless of clustered setup or not. You can sum up roughly: number of independent timer instances is equal to the number of calls to timer.createXxxTimer()




回答2:


I had a look at chapter 18 "Timer Service" of the EJB 3.1 spec. The app should behave according to the spec independently of clustering.

My understanding is that if createIntervalTimer is called once in a cluster, the timer should fire once independently on the number of nodes in the cluster. Since each singleton bean (according to your question) calls createIntervalTimer, the it will be execute n times. It is similar to creating timers in ServletContextListener.

This is theory, though. I would double-check for the specific app server you target. In glassfish, cluster-wide timer require to configure the timer pool with an external database.




回答3:


Even if it is not a direct amswer this could help anyway : One way that would configure only one instance per clustered environment would be to expose the singleton ejb as MXbean. You should have to expose a managed imterface, that could even be empty , then register your ejb to the jmx service in the @PostCostruct marked method. At last you would have to provide a @PreDestroy hook to deregister from the jmx service. This is the way suggested by the Java Champion Adam Bien.



来源:https://stackoverflow.com/questions/11324514/how-often-is-a-programmatic-created-ejb-timer-executed-in-a-cluster

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!