2009-03-24 6 views
3

Wir haben eine RMI-Client-Anwendung in Java geschrieben, die periodische "am Leben bleiben" Nachrichten an eine Server-Anwendung senden muss. Wir haben dies als separaten Heartbeat-Thread implementiert, der die Nachricht "Stay Alive" an den Server sendet und dann 15 Sekunden lang mit Thread.sleep() schläft.Wie kann ich garantieren, dass ein "am Leben bleiben" Herzschlag gesendet wird?

Der Faden wird mit hohen Priorität sein:

Thread heartbeatThread = new Thread(new HeartbeatRunnable(server)); 
heartbeatThread.setPriority(Thread.MAX_PRIORITY); 
heartbeatThread.start(); 

Wenn jedoch das Feld, auf das der Client mit vielen CPU ausgeführt wird, finden wir, dass Herzschlag verpaßt werden, die den Server veranlasst, anzunehmen, unsere Kundenanwendung ist gestorben.

Wir haben Thread.yield() Aufrufe in meinem Hauptthread hinzugefügt, obwohl dies das Problem nicht beseitigt hat.

Gibt es irgendeine Möglichkeit zu garantieren, dass die Herzschläge rechtzeitig gesendet werden, während meine Anwendung noch läuft?

Antwort

1

Sie können das Benutzermodus-Threading in einer Umgebung ohne Threads implementieren, indem Sie eine selbstgeschriebene "Yield" -Funktion in Ihrem Code großzügig streuen.

In ähnlicher Weise könnten Sie großzügig Herzschlag überprüfen Funktionsaufrufe in Ihrem Code. Auf den Thread verzichten, rufen Sie einfach regelmäßig eine Heartbeat-Funktion auf, die prüft, ob noch ein Heartbeat gesendet werden muss.

Es ist eine grobe Lösung, aber wenn Sie die richtige Lösung ausprobiert haben und es nicht funktioniert, ist es vielleicht etwas, auf das Sie zurückgreifen müssen.

In der Tat, was Sie tun könnten, ist ein Makro am Anfang jedes Funktionsaufrufs, der eine schnelle Überprüfung der Zeit und ruft die Heartbeat-Funktion bei Bedarf.

(Ah, haben Sie Makros in Java? Ich denke nicht - aber Sie bekommen die Idee).

3

Sie können es nicht wirklich garantieren. Sie könnten den Heartbeat in einem anderen Thread senden, um zu verhindern, dass die Zeit zum Senden des zu Ihrer Verzögerung hinzugefügten Heartbeats vergeht. Es kann auch ratsam sein, die Verzögerung zwischen zwei Heartbeats auf die Hälfte der Zeit einzustellen, die der Server benötigt, um zu entscheiden, dass ein Client tot ist, d. H. Wenn Ihr Server nach 15 Sekunden den Client abmeldet (versuchen Sie), alle 7,5 Sekunden einen Heartbeat zu senden.

+0

Danke für die Antwort. Wir senden bereits Herzschläge in einem separaten Thread, und der Server unterbricht uns nach 90 Sekunden ohne Herzschläge, so dass das Senden alle 15 Sekunden konservativ schien. –

+1

Es ist in der Tat sehr konservativ. Aber wenn Sie es nicht schaffen, einen Herzschlag für 90 Sekunden zu senden, wenn Sie versuchen, einen alle 15 Sekunden zu senden, ist Ihre Box ernsthaft überlastet und Ihr Client sollte vielleicht wirklich als tot betrachtet werden. Siehe Pete's Antwort. – Bombe

2

Es hängt davon ab, welcher Prozess die CPU verwendet.

Wenn es nicht Ihr Prozess ist, und so der Client-Prozess wirklich nicht reagiert, dann ist es in jeder Hinsicht nicht lebendig, also ist das Senden eines Heartbeart nicht angemessen. Wenn eine Heartbeat-Nachricht mit der Meldung "Ich bin wach und kann Nachrichten verarbeiten" angezeigt wird, wenn die Box zu geladen ist, wäre dies irreführend.

Wenn die Absicht der Heartbeat-Nachricht ist zu sagen "Dieser Prozess läuft, aber es könnte eine halbe Stunde dauern, bis ich zurück zu Ihnen", dann haben, was diese Verarbeitung tut, diese Nachricht an den Server senden. Oder setzen Sie den Timeout auf einen Wert, der zu der Reaktionszeit des Clients passt.

+0

Schön! – Learning

0

Vielleicht wäre die beste Lösung, Timer's scheduleAtFixedRate zu verwenden. Wenn eine Ausführungsverzögerung auftritt (was in Java nicht vermieden werden kann), werden die nachfolgenden Aufrufe nicht beeinträchtigt.

0

Wenn Sie möchten, dass der Server anzeigt, dass er aktiv ist, können Sie besser einen offenen Socket präsentieren. Auf Ihrem Client einfach von diesem Sockel lesen. Es blockiert (da Ihr Server nichts schreibt), und wenn der Server verschwindet oder herunterfährt, wird Ihr Client eine IOException erhalten, die anzeigt, dass der Server Socket/Port verschwunden ist.

Dies hängt nicht davon ab, dass der Server zeitnahe Heartbeats liefert. Es verwendet nur wenige Ressourcen (einen TCP-Port am Serverende und fast keine Bandbreite) und es wird rechtzeitig angezeigt, wenn der Server (oder Server-Computer) nicht mehr verfügbar ist.

+0

Verfolgt das nicht nur, ob der Server selbst lebt? Der Zielprozess könnte abgestürzt sein (oder zumindest zu einem Zombie geworden sein), ohne dass der TCP/IP-Stack klüger ist. –

+0

Nein. Das Betriebssystem wird sich darum kümmern. Es verfolgt, ob der Elternprozess der Socket/Port-Kombination aktiv ist –

1

Sie sollten die Anzahl der "verpassten Heartbeats" konfigurieren, die der Server wartet, bevor er entscheidet, dass der Client nicht verfügbar ist.

Wenn Ihr Herzschlagintervall beispielsweise 15 Sekunden beträgt und die Anzahl fehlender Herzschläge 4 beträgt, wartet der Server bis zu maximal 60 Sekunden (1 Minute), bevor er entscheidet, dass der Client nicht erreichbar ist.

Verwandte Themen