2017-11-19 4 views
0

Ich habe eine Schleife, A, läuft alle n Sekunden (wahrscheinlich wird ca. 0,5 oder 1 Sekunden oder so). Ich habe eine andere Aufgabe, B, die ungefähr alle Sekunden passiert, aber diese Aufgabe tritt in einer völlig separaten Umgebung und Server.Wie können NTP/Interrupts Timer beeinflussen?

Ich muss sicherstellen, dass Task A mindestens einmal zwischen den Zeiten passiert, in denen Task B auftritt. Allerdings mache ich mir Sorgen über die folgenden Fälle:

  • NTP-Anpassungen mit der Zeit auf beiden Servern Unordnung.
  • Interrupts oder GC, die Task A ausführen und verlangsamen, verzögern die Ausführung.

Gibt es eine Möglichkeit, diese potenziellen Fehlerpunkte zu beheben?

Diese werden in Java implementiert, aber ich würde mir vorstellen, dass es ziemlich unabhängig von der Sprache ist.

+0

Wie wichtig ist es, dass B nicht zweimal läuft ohne dass A dazwischen läuft? Ich kann mir keinen Weg vorstellen, dies ohne einen Koordinierungsdienst zu gewährleisten, um sicherzustellen, dass die Aufträge transaktional ausgeführt werden. – teppic

Antwort

0

Es kann nicht garantiert werden, dass Task B nicht ausgeführt wird, wenn Task A nicht ausgeführt wurde, ohne einen koordinierenden Service zu verwenden. Neben den Problemen mit Clock Skew und Prozessausfällen können andere Probleme auftreten. Was passiert, wenn Task A aufgrund von Hardware-/Ressourcenfehlern fehlschlägt? Was ist mit Service-Neustarts?

Die einfachste Lösung wäre, Task B für den Fall tolerant zu machen, in dem Task A nicht ausgeführt wurde. Wenn dies nicht möglich ist, müssen Sie einen Dienst zum Verfolgen des Status von Task A bereitstellen. Die einfachste Möglichkeit, dies zu implementieren, besteht darin, jeden Lauf von A mit einer eindeutigen ID auszugeben und vor der Ausführung von B zu überprüfen.

Etwas wie:

public class TaskA implements Runnable { 
    @Resource 
    private TaskService taskService; 

    @Override 
    public void run() { 
     // Run task A 
     // ... 

     // Set run ID for task B to retrieve 
     taskService.setRunId("A", UUID.randomUUID().toString()); 
    } 
} 

public class TaskB implements Runnable { 
    private static final Logger log = LoggerFactory.getLogger(TaskB.class); 

    @Resource 
    private TaskService taskService; 

    private String lastId; 

    @Override 
    public void run() { 
     String nextId = taskService.getRunId("A"); 
     if (this.lastId == null) { 
      log.info("First run. Not executing"); 
     } else if (lastId.equals(nextId)) { 
      log.warn("Task A has not run. Refusing to execute"); 
     } else { 
      log.info("Executing"); 
      // Run task B 
      // ... 
     } 
     this.lastId = nextId; 
    } 
} 

ich habe eine UUID in dem obigen Beispiel verwendet, um die Notwendigkeit für einen persistenten Speicher zu vermeiden, eindeutige IDs zu gewährleisten. Sie können eine Datenbank verwenden, wenn Sie eine in der Umgebung haben. Ich würde die Verwendung von Zeitstempeln aus den von Ihnen genannten Gründen vermeiden (Taktversatz usw.).

Verwandte Themen