2009-03-24 4 views
3

Nous avons une application cliente RMI écrite en Java qui doit envoyer des messages périodiques "rester en vie" à une application serveur. Nous l'avons implémenté comme un thread de pulsation distinct, qui envoie le message stay alive au serveur, puis dort pendant 15 secondes en utilisant Thread.sleep().Comment puis-je garantir que le rythme cardiaque «reste en vie» est envoyé?

Le fil est défini comme priorité:

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

Cependant, lorsque la case sur laquelle le client est en cours d'exécution est en utilisant beaucoup de CPU, nous constatons que les battements de coeur sont manqués, ce qui provoque le serveur à assumer notre application client est morte.

Nous avons ajouté des appels Thread.yield() dans mon thread principal, même si cela n'a pas permis de résoudre le problème.

Est-il possible de garantir que les pulsations sont envoyées à temps lorsque mon application est en cours d'exécution?

Répondre

1

Vous pouvez implémenter le threading en mode utilisateur dans un environnement non threaded en diffusant généreusement une fonction "yield" auto-écrite dans votre code.De même, vous pouvez disperser généreusement les appels de fonction de vérification du rythme cardiaque dans votre code. Renoncer au thread, appelez simplement régulièrement une fonction de battement de coeur qui vérifie si un battement de coeur doit encore être envoyé.

C'est une solution brute, mais étant donné que vous avez essayé la bonne solution et que cela ne fonctionne pas, c'est peut-être quelque chose à laquelle vous devez vous rabattre.

En fait ce que vous pouvez faire est de placer une macro au début de chaque appel de fonction, qui effectue une vérification rapide de l'heure et appelle la fonction de pulsation lorsque cela est nécessaire.

(Ah, avez-vous des macros en Java? Je ne pense pas - mais vous avez l'idée).

3

Vous ne pouvez pas vraiment le garantir. Vous pouvez envoyer le signal de présence dans un thread différent pour éviter le temps nécessaire pour envoyer le signal de présence ajouté à votre délai. Il peut également être conseillé de définir le délai entre deux pulsations à la moitié du temps que le serveur utilise pour décider qu'un client est mort, c'est-à-dire que si votre serveur expire après 15 secondes, essayez d'envoyer une pulsation toutes les 7,5 secondes.

+0

Merci pour la réponse. Nous envoyons déjà des battements de cœur dans un fil séparé, et le serveur nous coupe après aucun battement de cœur pendant 90 secondes, donc l'envoi toutes les 15 secondes semblait conservateur. –

+1

Il est très conservateur, en effet. Mais si vous ne parvenez pas à envoyer un battement de cœur pendant 90 secondes lorsque vous essayez d'en envoyer un toutes les 15 secondes, votre boîte est sérieusement surchargée et votre client devrait peut-être vraiment être considéré comme mort. Voir la réponse de Pete. – Bombe

2

Cela dépend du processus utilisé par la CPU.

Si ce n'est pas votre processus, et que le processus client ne répond vraiment pas, alors il est à toutes fins utiles non-vivant, donc ne pas envoyer un heartbeart est approprié. Avoir un message de battement de cœur qui dit «Je suis prêt et peut traiter les messages» lorsque la boîte est trop chargée pour le faire serait trompeur. Si l'intention du message de pulsation est de dire «ce processus est en cours, mais il peut s'écouler une demi-heure avant que je ne vous revienne», tout ce qui est en train de faire ce traitement envoie ce message au serveur. Ou définissez le délai d'attente à un délai qui correspond à la réactivité du client.

+0

Nice! – Learning

0

La meilleure solution serait peut-être d'utiliser le scheduleAtFixedRate de Timer. Avec ceci, si une exécution retarde (qui ne peut pas être évitée en Java), les appels ultérieurs ne seront pas affectés.

0

Si vous souhaitez que le serveur annonce qu'il est actif, il est peut-être préférable de présenter un socket ouvert. Sur votre client, lisez simplement depuis cette prise. Il va bloquer (puisque votre serveur n'écrit rien), et si le serveur disparaît/s'éteint, votre client recevra une exception IOException indiquant que le socket/port du serveur a disparu.

Cela ne dépendra pas du fait que le serveur fournisse des pulsations en temps opportun. Il utilise peu de ressources (un port TCP à la fin du serveur et à côté de la bande passante) et il est opportun de révéler quand le serveur (ou la machine serveur) devient indisponible.

+0

Est-ce que cela ne fait pas que suivre le serveur lui-même? Le processus cible pourrait avoir planté (ou au moins transformé en zombie) sans que la pile TCP/IP soit plus sage. –

+0

Non. Le système d'exploitation s'en occupera. Il va suivre si le processus parent de la combinaison socket/port est en hausse –

1

Vous devez configurer le nombre de "battements de cœur manqués" que le serveur attend avant de décider que le client est indisponible. Par exemple, si votre intervalle de pulsation est de 15 secondes et que le nombre de battements de cœur manqués est de 4, le serveur attendra jusqu'à 60 secondes (1 minute) avant de décider que le client est injoignable.

Questions connexes