2012-03-05 29 views
3

我調度後臺任務以固定時間間隔運行,但由於tomcat運行在多個實例(即多個啓動Apache服務器; 3在我的情況),然後任務在每個間隔運行3次..我想它只運行一次(不管運行的Tomcat實例的數量是多少)。如何在多實例Tomcat環境中以固定間隔運行任務?

我跑在啓動時加載(在web.xml)一個servlet,這將引發我的任務:

<servlet> 
    <servlet-name>OnInit</servlet-name> 
    <servlet-class>box.OnInit</servlet-class> 
    <load-on-startup>1</load-on-startup> 
</servlet> 

的OnInit類發起類的單個實例:

public class BGTaskRefresh { 
    private static BGTaskRefresh refreshTaskFactory = null; 
    private final Timer timer = new Timer(); 

    public BGTaskRefresh() {} 
    public static void init() 
    { 
     if(refreshTaskFactory == null) 
     { 
      refreshTaskFactory = new BGTaskRefresh(); 
      refreshTaskFactory.start(); 
     } 
    } 

    public void start() 
    { 
     timer.schedule(
      new TimerTask() 
      { 
        public void run() 
        { 
         boxService box = new boxService(); 
         box.refreshMethod(); 
        } 
       },      
       5 * 60 * 1000, // 5-Min Delay for first run 
      60 * 60 * 1000); // 60-Mins (Interval between 2 runs)     
    } 
} 

回答

3

你可能想看看,特別是其clustering功能:

two muppets http://quartz-scheduler.org/images/documentation/2.x/quartz_cluster.png

這可能是一個矯枉過正的情況,但Quartz會負責僅在單個實例上運行作業(使用數據庫進行同步),並且會自動在空閒服務器上運行該作業。

另一個選項是以及它提供的分佈式鎖和隊列。

+0

看來我(我們?)在這裏失去了一些東西。是不是Java Timer內置的功能應該能夠處理它?我的意思是,固定間隔是相當常見的,並且讓您的應用程序服務器在多個實例中運行。 – Haim 2012-03-05 12:56:44

+0

@Haim:怎麼樣? ['Timer'](http://docs.oracle.com/javase/7/docs/api/java/util/Timer.html)只是一個管理少量線程的Java類。如果你有幾個JVM(可能在不同的機器上),那麼這個類怎麼知道其他實例呢?它們是完全獨立的 - 這就是爲什麼你的任務在其中每一個都被執行,這就是爲什麼你有答案提及Quartz,數據庫和文件鎖定 - 因爲你需要JVM之外的某種同步/協調。或者我錯過了什麼? – 2012-03-05 12:59:28

0

您將需要某種同步機制。儘管理想情況下您希望使用分佈式調度程序(例如Quartz集羣),但考慮到您的使用場景,您可能需要一些共享會話狀態機制或應用程序底層的共享數據庫;您可以簡單地記錄操作並獲取基於數據庫的鎖,以確保一次只有一個實例運行該命令(並且在鎖定之後進行仔細檢查,以確保您沒有兩次運行相同的任務)。

這裏有一個文章中,我與基於數據庫的鎖的技術發現:http://blog.udby.com/archives/15

相關問題