2012-07-04 51 views
4

在羣集JEE6環境(Glassfish 3.1.2)中,可以在每個羣集節點上創建一個@Singleton bean。如果這個Singleton Bean在其@PostConstruct上註冊了編程定時器 - @Timeout方法執行的頻率如何? - 只有一個單身人士(每個勾號),或者一個(每個勾號)每個註冊一個定時器的Singeton?在羣集中多久執行一次編程創建的EJB定時器?

下面的代碼是這個問題對這段代碼的意義。

@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在每個節點上實例化,所以總共完成3次(每個節點一次)。那麼問題是:緩存是否每小時清除一次(所有節點上都會調用executeResetTimer)?

(我知道,計時器滴答不是在同一時間的所有節點上,因爲辛格爾頓是在不同的時間實例化,但這不是問題/問題。)

回答

2

首先,請確保您已按照here所述設置了定時器服務到外部共享XA數據源。

已經挖成過去你的問題,我記得some explanation通過郵件列表開發者,即GlassFish的實現如下:

說你有節點A,B和C的集羣。在節點A創建的持久定時器 由節點A「擁有」(即定時器事件傳遞到節點A的 )。如果節點A出現故障,則其定時器可以遷移到另一個活動的節點 節點。

有了這樣的Glassfish doesn't support羣集範圍@Singletons,你最終獲得儘可能多的計時器作爲呼叫initResetTimer()。此外,每個服務器的重新啓動/重新部署可能會爲每個羣集節點創建一個新的實例,除了舊的未刪除的節點以外,所以不要忘記取消以編程方式創建的計時器。爲避免這一切使用聲明式@Schedule(...)方法,Glassfish將會創建計時器once across cluster,並希望在失敗時自動遷移它們。

希望這會有所幫助。

UPDATE:

甲編程方式創建計時器,持續性或非持久性,將在JVM /節點被解僱它被創建,而不管羣集設置的或沒有。大致可以概括爲:獨立計時器實例的數量等於timer.createXxxTimer()

+0

這個答案非常有用,它回答了其他問題:http://stackoverflow.com/questions/11244608/how-to-run -a-scheduled-in-a-cluster-for-one-node-and-for-all - 但是仍然有一個懸而未決的問題:在上面的例子中,編程計時器不是永久的 - 是否會被執行在非常節點(這是我想實現的)? – Ralph

+0

是的,對'timerService.createXXXTimer(...)'的編程調用是相互獨立的,請參閱更新以回答。 – Tair

2

我看看在EJB 3.1規範的第18章「定時器服務」中。應用程序應該按照規範行事,而不依賴於羣集。

我的理解是,如果createIntervalTimer在羣集中被調用一次,那麼定時器應該獨立激發羣集中一些節點的數量。由於每個單獨bean(根據你的問題)調用createIntervalTimer,它將執行n次。它類似於creating timers in ServletContextListener

雖然這是理論。我會仔細檢查你的目標應用服務器。在glassfish中,cluster-wide timer需要使用外部數據庫配置定時器池。

1

即使它不是一個直接的amswer,無論如何這可能會有所幫助:一種在每個集羣環境中只配置一個實例的方法是將singleton ejb公開爲MXbean。 你應該公開一個管理接口,甚至可以是空的,然後在@PostCostruct標記的方法中將你的ejb註冊到jmx服務。最後,你將不得不提供一個@PreDestroy掛鉤來註銷jmx服務。 這是Java Champion Adam Bien建議的方式。

+0

的呼叫數這是一個很好的勾號,但我不明白它與我的問題有什麼關係? – Ralph

+0

你能鏈接到Adam Bien如何描述這個嗎? – DavidS

+0

http://www.adam-bien.com/roller/abien/entry/singleton_the_simplest_possible_jmx – JayZee