2016-06-30 11 views
3

Meine App läuft auf 3 Servern hinter einem Load Balancer. Daher ist es zustandslos, alle Daten sind in redis und MySQL gespeichert.Laravel-Zeitpläne auf verteilten App

Wenn meine Maschinen den Handwerkercron-Scheduler laufen lassen, nehme ich an, dass die gleiche Aufgabe 3 Mal ausgeführt wird. Einmal auf jeder Maschine, da es keine Kenntnis darüber gibt, was zwischen ihnen ausgeführt wurde, aka eine Datenbanktabelle.

Was sind die Lösungen?

+0

Ist die redis Datenbank über den Servern gemeinsam genutzt? – GiamPy

+0

Ja, es ist geteilt, geclustert – AndrewMcLagan

Antwort

3

edit: In den letzten Versionen von Laravel, this is now built-in.

$schedule->command('foo:bar')->onOneServer(); 

Wir tun dies in Artisan Befehle, die nur auf einem Server pro cron Ausführung ausgeführt werden soll:

public function handle() 
    if(!Cache::add(get_class($this), true, 0.5)) { 
     return false; 
    } 

Cache::add synchron und wird falsch zurück, wenn der Schlüssel bereits vorhanden, so dass selbst wenn alle drei Server werden genau zur selben Mikrosekunde ausgeführt, nur ein Server wird mit dem Rest der Aufgabe fortfahren.

Eine weitere häufige Option ist das Aktivieren des Cron auf nur einem einzelnen Server im Cluster oder das Bereitstellen eines dedizierten Servers für Cron selbst.

+0

Was ist mit einem Server, Pings nach einem Zeitplan? Könnte das auch funktionieren? – AndrewMcLagan

+0

@AndrewMcLagan Ich bin nicht klar, was Sie mit "Pings" meinen. – ceejayoz

+0

Pingt eine Route, ruft eine Route auf. Auf dieser Route starte ich den Handwerker-Scheduler – AndrewMcLagan

2

Wenn Ihr Redis-Server auf den Servern freigegeben ist, können Sie eine Logik erstellen, z. B. die Auswahl eines Leader-Anwendungsservers.

Ihre App-Logik sollte den Leader vor der Verarbeitung überprüfen. Probe-Schnipsel:

if(redis.get("LEADER").equals(currentappserver)) 
process(); 
else if(redis.get("LEADER")==null && selectLeader()) -> a lua script call. 
process(); 

Da redis ist single threaded eine Logik wie diese Schnipsel in einem Lua Script schreiben:

selectLeader() 
if redis.get("LEADER")==null 
redis.set("LEADER",current_node) 
return true; 
else 
return false; 

Es wird atomarer und nur ein Führer Thread wird immer verfügbar sein.

Ps.S: Codes, die ich zur Verfügung gestellt habe, sind Vauge Pseudocode nicht den genauen Code.

+0

Das ist ziemlich ordentlich. – ceejayoz

0

Laravel 5.4 unterstützt Multi-Server-Setups mit Scheduler, wenn das Upgrade eine Option ist.

Es verwendet eine ähnliche Methode wie die angenommene Antwort von Ceejayoz.

Anstatt das Dateisystem zum Speichern einer Sperrdatei zu verwenden, verwenden wir den Cache-Speicher, damit jeder Server geplante Ereignisse sperren/überprüfen kann.

https://github.com/laravel/internals/issues/69

Verwandte Themen