Protocolo Heartbeat escrito en Java, trabajando sobre UDP
El protocolo heartbeat se estructura en una notificación continua de un datagrama UDP con un retraso de 1000 milisegundos. El campo de carga útil contiene el identificador del cliente que puede consistir en una cadena como la dirección MAC de las tarjetas de red actualmente utilizadas por la fuente de ping o un identificador como un nombre de usuario. El servidor escuchará los distintos ping clasificándolos según el identificador y gestionando los distintos estados que ellos mismos definirán. Siempre que el servidor observe que después de un retraso de 3000 milisegundos no ha recibido ningún ping del cliente notificará mediante un evento al usuario de este protocolo de la probable pérdida de conexión aconsejando limitar o detener el intercambio de datos a través de cualquier otra conexión. protocolo dependiente como TCP. Si dentro de 5.000 milisegundos recibes este identificador, el cliente se conectará nuevamente, por lo que es posible restablecer el canal de comunicación de datos. De lo contrario, se considerará que el cliente está completamente desconectado. Todo esto será notificado como se mencionó anteriormente a través de una gestión de eventos como se muestra a continuación:
@ Override
public void onHeartbeat ( HeartbeatEvent event ) {
LOGGER . log ( Level . INFO , () -> "Received heartbeat from " + event . getSource () + " in " + event . getTimeFromPreviousBeat () + " at " + event . getBeatTimeStamp ());
}
@ Override
public void onDeath ( HeartbeatEvent event ) {
LOGGER . log ( Level . INFO , () -> event . getSource () + " died after " + event . getTimeFromPreviousBeat () + " at " + event . getBeatTimeStamp ());
}
@ Override
public void onLossCommunication ( HeartbeatEvent event ) {
LOGGER . log ( Level . INFO , () -> "Communication lost of " + event . getSource () + " in " + event . getTimeFromPreviousBeat () + " at " + event . getBeatTimeStamp ());
}
@ Override
public void onReacquiredCommunication ( HeartbeatEvent event ) {
LOGGER . log ( Level . INFO , () -> "Communication reacquired of " + event . getSource () + " in " + event . getTimeFromPreviousBeat () + " at " + event . getBeatTimeStamp ());
}
@ Override
public void onAcquiredCommunication ( HeartbeatEvent event ) {
LOGGER . log ( Level . INFO , () -> event . getSource () + " connected at " + event . getBeatTimeStamp ());
}
El código de muestra anterior muestra la captura de varios eventos en los estados de un cliente, luego será tarea de quienes implementen el oyente la decisión sobre qué hacer al capturar un determinado tipo de evento como se muestra a continuación:
public class ServerStart implements HeartbeatListener {
private static final ServerStart thisInstance = new ServerStart ();
public static void main ( String [] args ) {
HeartbeatProtocolManager heartbeatProtocolManager = new HeartbeatProtocolManager ( thisInstance );
heartbeatProtocolManager . addHost ( "Test" , 43210 ); //identifier, port
heartbeatProtocolManager . addHost ( "Test1" , 43211 );
}
@ Override
public void onHeartbeat ( HeartbeatEvent event ) {
LOGGER . log ( Level . INFO , () -> "Received heartbeat from " + event . getSource () + " in " + event . getTimeFromPreviousBeat () + " at " + event . getBeatTimeStamp ());
}
@ Override
public void onDeath ( HeartbeatEvent event ) {
LOGGER . log ( Level . INFO , () -> event . getSource () + " died after " + event . getTimeFromPreviousBeat () + " at " + event . getBeatTimeStamp ());
}
@ Override
public void onLossCommunication ( HeartbeatEvent event ) {
LOGGER . log ( Level . INFO , () -> "Communication lost of " + event . getSource () + " in " + event . getTimeFromPreviousBeat () + " at " + event . getBeatTimeStamp ());
}
@ Override
public void onReacquiredCommunication ( HeartbeatEvent event ) {
LOGGER . log ( Level . INFO , () -> "Communication reacquired of " + event . getSource () + " in " + event . getTimeFromPreviousBeat () + " at " + event . getBeatTimeStamp ());
}
@ Override
public void onAcquiredCommunication ( HeartbeatEvent event ) {
LOGGER . log ( Level . INFO , () -> event . getSource () + " connected at " + event . getBeatTimeStamp ());
}
}
El evento generado además de contener la carga útil también contendrá el retraso pasado respecto al anterior con su propio identificador de carga útil y la marca de tiempo de la recepción actual del ping.
El uso de este protocolo permitirá una mejor gestión del estado de las conexiones entre cliente y servidor y un mayor control de los posibles errores.