Jak zmusić klaster do uruchomienia zadania tylko raz?

13

Jeśli masz zadanie, które chcesz uruchomić tylko raz na klastrze serwerów, w regularnych odstępach czasu jaki byłby najlepszy sposób na osiągnięcie tego? Definicja klastra w tym przypadku to 2 lub więcej identycznych serwerów z sesjami rozproszonymi za modułem równoważenia obciążenia.

Przypadek użycia: Masz zadanie, które jest drogie do uruchomienia, które powinno być uruchamiane tylko raz na X godzin. To zadanie może na przykład powtarzać wiele rekordów i aktualizować ich status.

  • W najgorszym przypadku dwukrotne uruchomienie zadania unieważnia dane.
  • Najlepszy scenariusz to wykorzystanie zasobów na wszystkich serwerach.

Podsumowanie wymagań:

  1. Zadanie musi nadal działać, nawet jeśli jeden z węzłów nie działa.
  2. Zadanie można uruchomić tylko raz zgodnie z harmonogramem.
  3. Jeśli zaplanowano wiele zadań jednocześnie lub w nakładających się czasach, liczba uruchomionych zadań jest równo rozdzielona między serwery.
  4. Maszyny muszą mieć tę samą bazę kodu i być zsynchronizowane przez NTP.
  5. Konfiguracja może się różnić między węzłami i węzłami, w zależności od zmiennych środowiskowych.
  6. Zadanie musi rozpocząć się na czas lub w określonym przedziale czasu. (na przykład 5 minut)

Możliwe rozwiązania

  • Ustaw jeden węzeł jako węzeł główny, to nie działa, ponieważ narusza 1 powyżej.
  • Złóż wniosek o wyważenie modułu równoważenia obciążenia, aby rozpocząć pracę. Niestety ma to taki efekt uboczny, że jeśli masz wiele zadań uruchomionych w tym samym czasie, wszystkie mogą być uruchomione na tym samym komputerze.

Musiałoby to działać w Javie, w kontenerze serwletu. Jednak nie koduje zadań, których szukam.

Z pewnością jest to rozwiązany problem ze znanym najlepszym rozwiązaniem.


Powiązane pytanie. /programming/5949038/schedule-job-executes-twice-on-cluster

Nie jest to duplikat, ponieważ rozwiązanie jest niewystarczające zgodnie z 5 powyższymi wymaganiami. Najbardziej uprzywilejowane rozwiązanie ma problem z rasą, a drugie rozwiązanie narusza wymaganie 3

Wes
źródło

Odpowiedzi:

16

Czy masz wspólną bazę danych? Zrobiłem to za pomocą bazy danych jako arbitra w przeszłości.

Zasadniczo każde „zadanie” jest reprezentowane jako wiersz w bazie danych. Zaplanuj zadanie, dodając wiersz do bazy danych z czasem, w którym chcesz go uruchomić, a następnie każdy serwer:

SELECT TOP 1 *
FROM jobs
WHERE state = 'NotRun'
ORDER BY run_time ASC

W ten sposób wszyscy wybiorą zadanie, które ma zostać uruchomione jako następne . Wszyscy śpią, aby obudzić się, gdy zadanie ma się rozpocząć. Następnie wszyscy to robią:

UPDATE jobs
SET state = 'Running'
WHERE job_id = :id
  AND state = 'NotRun'

Gdzie :idjest identyfikator zadania, które dostałeś w powyższym kroku. Ponieważ aktualizacja jest atomowa, tylko jeden z serwerów faktycznie zaktualizuje wiersz, możesz sprawdzić kod stanu bazy danych „liczba aktualizacji wierszy”, aby ustalić, czy to ty byłeś serwerem, który faktycznie zaktualizował wiersz, a zatem czy jesteś serwerem który może uruchomić zadanie.

Jeśli nie „wygrałeś” i nie wykonujesz zadania, natychmiast wróć do kroku 1. Jeśli „wygrałeś”, zaplanuj wykonanie zadania w innym wątku, a następnie poczekaj kilka sekund, zanim wrócisz do kroku 1. W ten sposób serwery, które tym razem nie dostały zadania, częściej podejmują pracę które zaplanowano uruchomić natychmiast.

Dean Harding
źródło
1
Jakiego poziomu izolacji używasz tutaj? Czytaj popełnione czy serializować?
Maverick Riz,
2

Kilka serwerów aplikacji ma funkcję „singletonowych usług obejmujących cały klaster”.

Na przykład Weblogic ma funkcję Singleton Service, która jest konfigurowana za pomocą internetowej konsoli administracyjnej.

Musisz napisać klasę implementującą weblogic.cluster.singleton.SingletonService i użyć jej do zadeklarowania usługi w konsoli administracyjnej. Klaster zajmuje się tworzeniem instancji klasy i powiadamianiem o uruchomieniu lub zatrzymaniu usługi. Interfejs SingletonService ma metodę aktywacji () i dezaktywacji ().

Wywołania Weblogic aktywują się (), gdy po raz pierwszy uruchamia usługę w jednym z węzłów klastra. Jeśli wybrany węzeł ulegnie awarii, serwer administracyjny „przenosi” usługę na inny serwer, wywołując tam funkcję enable ().

http://docs.oracle.com/cd/E12839_01/apirefs.1111/e13952/taskhelp/clusters/ConfigureSingletonService.html

Alfred Faltiska
źródło