2016-08-18 1 views
2

Ich habe eine Java EE-Anwendung auf Glassfish 3.1.2 in einer geclusterten Umgebung ausgeführt.Wie jede Nacht Methode auf JEE-Cluster ausgeführt wird

Ich möchte eine bestimmte Methode einmal am Tag ausführen (d. H. Einige Einträge aus der Datenbank löschen).

habe ich einen Timer:

@Singleton 
public class TimerService { 
    @Schedule(second = "0", minute = "0", hour = "0", persistent=false) 
    public void runEveryDay() { 
     LOG.info("### runEveryDay"); 
    } 

Wenn ich die Protokolle prüfen, wird das Verfahren auf beiden Clusterknoten ausgeführt. Ich befürchte, dass es bei der gleichzeitigen Ausführung der Methode auf beiden Knoten zu Problemen aufgrund veralteter Daten kommen kann.

Gibt es eine Möglichkeit, dass die Methode nur auf einem Knoten ausgeführt wird? Oder kann ich die Methoden irgendwie synchronisieren?

+0

Ich hatte dieses Problem auch. Eine bessere Lösung wäre es, den nächtlichen Batch getrennt vom Java EE-Container zu planen, der vom Betriebssystem geplant wird. – duffymo

Antwort

1

Stellen Sie Ihren Timer auf persistent ein. Es sollte dann nur auf einem Serverknoten im Cluster ausgeführt werden.

0

Sie können sich gegen gleichzeitige Ausführung schützen, indem Sie eine vorgeladene Datenbankzeile als Transaktionssperre verwenden.

schreiben JobLockService so etwas wie:

@Stateless 
public class JobLockService { 

    @Resource 
    private DataSource serializableDS; 

    @TransactionAttribute(REQUIRES_NEW) 
    public boolean jobLockAcquired() { 
      // select jobLock record for update when flag = 0 and set flag 
      return true if record selected otherwise false 
    } 

    @TransactionAttribute(REQUIRES_NEW) 
    public void releaseJobLock() { 
      // reset jobLock record flag back to 0 
    } 

} 

und es dann Singleton bieten:

@Singleton 
public class TimerService { 

    @EJB 
    private JobLockService jobLockService; 

    @Schedule(second = "0", minute = "0", hour = "0", persistent=false) 
    public void runEveryDay() { 
     if (jobLockService.jobLockAcquired()) { 
      try { 
       LOG.info("### runEveryDay"); 
      } finally { 
       jobLockService.releaseJobLock(); 
      } 
     } else { 
      log.info("Job already running elsewhere"); 
     } 
    } 

Konfigurieren eines speziellen Datenquelle in Ihrem Server, der mit ihm ist Transaktionsisolationsstufe auf TRANSACTION_SERIALIZABLE konfiguriert ist, in um Nebenläufigkeitsprobleme zu vermeiden. (Normalerweise würden Sie diese Einstellung nicht verwenden, da die gleichzeitige Ausführung von Hochlast zu hohen Kosten führt.)

Die Verwendung von REQUIRES_NEW Transaktionen in den JobLockService-Methoden verhindert Blockierungsprobleme.

Verwandte Themen