Protocolo Heartbeat escrito em Java, funcionando em UDP
O protocolo heartbeat está estruturado em uma notificação contínua de um datagrama UDP com atraso de 1000 milissegundos. O campo de carga útil contém o ID do identificador do cliente que pode consistir em uma string como o endereço MAC das placas de rede em uso atual pela origem do ping ou um identificador como um nome de usuário. O servidor ouvirá os vários ping classificando-os de acordo com o identificador e gerenciando os vários estados que eles próprios definirão. Sempre que o servidor perceber que após um atraso de 3000 milissegundos não recebeu nenhum ping do cliente notificará através de um evento o usuário deste protocolo da provável perda de conexão aconselhando a limitar ou interromper a troca de dados através de qualquer outra conexão- protocolo dependente, como TCP. Se dentro de 5.000 milissegundos você receber com este identificador o cliente será conectado novamente, ou seja, é possível restaurar o canal de comunicação de dados. Caso contrário o cliente será considerado totalmente offline. Tudo isso será notificado conforme mencionado acima através de um gerenciamento de eventos conforme mostrado abaixo:
@ 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 ());
}
O código de exemplo acima mostra a captura de diversos eventos nos estados de um cliente, caberá então a quem implementa o listener a decisão sobre o que fazer ao capturar um determinado tipo de evento conforme abaixo:
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 ());
}
}
O evento gerado além de conter o payload também conterá o atraso passado em relação ao anterior com seu próprio identificador de payload e o timestamp da recepção atual do ping.
A utilização deste protocolo permitirá uma melhor gestão do estado das ligações entre cliente e servidor e um maior controlo dos possíveis erros.