Heartbeat
Hinweis: Langzeitverbindungen müssen Heartbeats verwenden, da die Verbindung sonst aufgrund fehlender Kommunikation über längere Zeiträume von Routern getrennt werden kann.
Die Hauptfunktionen des Heartbeats sind zwei:
-
Der Client sendet regelmäßig einige Daten an den Server, um zu verhindern, dass die Verbindung aufgrund fehlender Kommunikation für längere Zeit von Firewalls bestimmter Knoten geschlossen wird, was zu Verbindungsabbrüchen führen kann.
-
Der Server kann durch Heartbeats feststellen, ob der Client online ist. Wenn der Client innerhalb der festgelegten Zeit keine Daten sendet, wird angenommen, dass der Client offline ist. Dadurch können Ereignisse erkannt werden, bei denen der Client aus extremen Gründen (z. B. Stromausfall, Netzwerkunterbrechung usw.) offline geht.
Empfohlener Heartbeat-Intervall:
Es wird empfohlen, dass der Client einen Heartbeat-Intervall von weniger als 60 Sekunden sendet, z. B. 55 Sekunden.
Das Datenformat des Heartbeats ist nicht festgelegt, solange der Server es erkennen kann.
Beispiel für Heartbeat
<?php
use Workerman\Worker;
use Workerman\Timer;
use Workerman\Connection\TcpConnection;
require_once __DIR__ . '/vendor/autoload.php';
// Heartbeat-Intervall 55 Sekunden
define('HEARTBEAT_TIME', 55);
$worker = new Worker('text://0.0.0.0:1234');
$worker->onMessage = function(TcpConnection $connection, $msg) {
// Setze eine temporäre lastMessageTime-Eigenschaft für die Verbindung, um die Zeit der letzten empfangenen Nachricht zu speichern
$connection->lastMessageTime = time();
// Weitere Geschäftslogik...
};
// Setze einen Timer, der alle 10 Sekunden ausgeführt wird, nachdem der Prozess gestartet wurde
$worker->onWorkerStart = function($worker) {
Timer::add(10, function()use($worker){
$time_now = time();
foreach($worker->connections as $connection) {
// Es ist möglich, dass diese Verbindung noch keine Nachrichten empfangen hat; daher lastMessageTime auf die aktuelle Zeit setzen
if (empty($connection->lastMessageTime)) {
$connection->lastMessageTime = $time_now;
continue;
}
// Wenn der Zeitraum seit der letzten Kommunikation größer als das Heartbeat-Intervall ist, wird davon ausgegangen, dass der Client offline ist und die Verbindung wird geschlossen
if ($time_now - $connection->lastMessageTime > HEARTBEAT_TIME) {
$connection->close();
}
}
});
};
Worker::runAll();
Die obige Konfiguration bedeutet, dass der Server die Verbindung schließt und das onClose-Ereignis auslöst, wenn der Client mehr als 55 Sekunden keine Daten an den Server sendet.
Wiederverbindung (wichtig)
Egal, ob der Client Heartbeats sendet oder der Server, es besteht jederzeit die Möglichkeit, dass die Verbindung getrennt wird. Beispielsweise kann bei minimierten Browsern das JS pausiert werden, beim Wechsel zu anderen Tabs kann das JS pausiert werden, der Computer kann in den Energiesparmodus wechselt, Mobilgeräte können das Netzwerk wechseln, das Signal kann schwächer werden, das Mobilgerät kann in den Ruhezustand wechseln, Anwendungen können in den Hintergrund wechseln, Routerfehler können auftreten, und es kann zu absichtlichen Trennungen kommen. Insbesondere in komplexen externen Umgebungen werden viele Routerverbindungen, die innerhalb einer Minute nicht aktiv sind, automatisch bereinigt, was auch der Grund ist, warum der Heartbeat-Intervall von weniger als einer Minute empfohlen wird.
Verbindungen können in externen Umgebungen leicht getrennt werden, weshalb eine Wiederverbindung eine notwendige Funktion für Langzeitverbindungen ist (Wiederverbindungen können nur vom Client durchgeführt werden; der Server kann dies nicht umsetzen). Beispielsweise muss der Websocket des Browsers das onclose-Ereignis überwachen und bei Eintreffen eines onclose ein neues Verbindung herstellen (um Abstürze zu vermeiden, sollte das neue Verbindung verzögert hergestellt werden). Strenger betrachtet sollte der Server ebenfalls regelmäßig Heartbeat-Daten senden, und der Client muss regelmäßig überwachen, ob die Heartbeat-Daten des Servers rechtzeitig eintreffen. Wenn die festgelegte Zeit überschritten wird und keine Heartbeat-Daten des Servers empfangen wurden, sollte die Verbindung als getrennt angesehen werden, und es sollte die close-Methode aufgerufen werden, um die Verbindung zu schließen und erneut eine neue Verbindung herzustellen.