Cœur
Note : Les applications à connexion persistante doivent ajouter un cœur, sinon la connexion peut être forcée à se déconnecter par un nœud de routage en raison d'une absence de communication prolongée.
La fonction principale du cœur est double :
-
Le client envoie régulièrement des données au serveur pour éviter que la connexion ne soit fermée par le pare-feu de certains nœuds en raison d'une absence prolongée de communication.
-
Le serveur peut utiliser le cœur pour déterminer si le client est en ligne ; si le client n’envoie aucune donnée dans le délai imparti, le serveur considère que le client est hors ligne. Cela permet de détecter les événements où le client devient hors ligne en raison de circonstances extrêmes (coupure de courant, perte de réseau, etc.).
Valeur suggérée pour l'intervalle de cœur :
Il est recommandé que le client envoie un cœur avec un intervalle de moins de 60 secondes, par exemple 55 secondes.
Il n'y a pas d'exigence sur le format des données du cœur, tant que le serveur peut les reconnaître.
Exemple de cœur
<?php
use Workerman\Worker;
use Workerman\Timer;
use Workerman\Connection\TcpConnection;
require_once __DIR__ . '/vendor/autoload.php';
// Intervalle de cœur de 55 secondes
define('HEARTBEAT_TIME', 55);
$worker = new Worker('text://0.0.0.0:1234');
$worker->onMessage = function(TcpConnection $connection, $msg) {
// Temporarily set a lastMessageTime property for the connection to record the last received message time
$connection->lastMessageTime = time();
// Other business logic...
};
// After the process starts, set a timer that runs every 10 seconds
$worker->onWorkerStart = function($worker) {
Timer::add(10, function()use($worker){
$time_now = time();
foreach($worker->connections as $connection) {
// The connection may not have received a message yet, so set lastMessageTime to the current time
if (empty($connection->lastMessageTime)) {
$connection->lastMessageTime = $time_now;
continue;
}
// If the last communication time interval is greater than the heartbeat interval, consider the client offline and close the connection
if ($time_now - $connection->lastMessageTime > HEARTBEAT_TIME) {
$connection->close();
}
}
});
};
Worker::runAll();
La configuration ci-dessus indique que si le client n’envoie aucune donnée au serveur pendant plus de 55 secondes, le serveur considère que le client est hors ligne, ferme la connexion et déclenche onClose.
Reconnexion (important)
Que ce soit le client qui envoie un cœur ou le serveur qui envoie un cœur, il est possible que la connexion se rompe. Par exemple, le JavaScript peut être suspendu lorsque le navigateur est minimisé, lorsqu'il passe à un autre onglet, lorsque l'ordinateur entre en mode veille, lorsque le mobile change de réseau, lorsque le signal devient faible, lorsque l'écran du téléphone se met en veille, lorsque l'application mobile passe en arrière-plan, en cas de défaillance du routeur, ou lorsqu'une déconnexion est initiée par le service. En particulier, dans un environnement externe complexe, de nombreux nœuds de routage nettoient les connexions inactives après une minute, c’est pourquoi il est recommandé d'avoir un intervalle de cœur de moins d'une minute.
La connexion peut facilement être rompue dans un environnement externe, donc la reconnexion est une fonctionnalité indispensable pour les applications à connexion persistante (la reconnexion ne peut être effectuée que par le client, le serveur ne peut pas l'implémenter). Par exemple, le WebSocket du navigateur doit écouter l'événement onclose ; lorsqu'un onclose se produit, une nouvelle connexion doit être établie (afin d'éviter des interruptions, la connexion peut être établie avec un délai). Plus strictement, le serveur devrait également initier régulièrement des données de cœur, et le client doit régulièrement surveiller si les données de cœur du serveur ont expiré ; si aucune donnée de cœur du serveur n'est reçue dans le délai imparti, la connexion doit être considérée comme rompue, nécessitant l'exécution de close pour fermer la connexion et établir une nouvelle connexion.