2009-04-02 14 views
4

J'ai un programme Java fonctionnant sous Windows (une machine Citrix), qui envoie une requête aux serveurs d'applications Java sous Linux; Ce mécanisme de répartition est entièrement personnalisé.(sockets réseau) octets bloqués dans la file d'attente d'envoi pendant 15 minutes; Pourquoi?

Le programme Windows Java (appelons-le W) ouvre un socket d'écoute sur un port donné par le système d'exploitation, disons 1234 pour recevoir les résultats. Ensuite, il appelle un service "dispatch" sur le serveur avec une "requête métier". Ce service divise la requête et l'envoie aux autres serveurs (appelons-les S1 ... Sn), et renvoie le nombre de tâches au client de manière synchrone. Dans mes tests, 13 tâches ont été envoyées à plusieurs serveurs et en 2 secondes, tous les serveurs ont fini de traiter leurs tâches et de renvoyer les résultats au socket de W.

Je peux voir dans les journaux que 9 travaux sont reçus par W (ce nombre varie d'un test à l'autre). Donc, j'essaie de chercher les 4 emplois restants. Si je fais un netstat sur cette case Windows, je vois que 4 prises sont ouvertes:

TCP W:4373  S5:48197 ESTABLISHED 
TCP W:4373  S5:48198 ESTABLISHED 
TCP W:4373  S6:57642 ESTABLISHED 
TCP W:4373  S7:48295 ESTABLISHED 

Si je fais une décharge de fil de W, je vois 4 fils essayant de lire à partir de ces prises, et apparemment coincé dans java.net.SocketInputStream.socketRead0(Native Method) .

Si je vais sur chacune des boîtes S et fais un netstat, je vois que quelques octets sont toujours dans la file d'attente d'envoi. Ce nombre d'octets ne bouge pas pendant 15 minutes. (Ce qui suit est l'agrégation des netstat s sur les différentes machines):

Proto Recv-Q Send-Q Local Address    Foreign Addr State 
tcp  0 6385 S1:48197       W:4373 ESTABLISHED 
tcp  0 6005 S1:48198       W:4373 ESTABLISHED 
tcp  0 6868 S6:57642       W:4373 ESTABLISHED 
tcp  0 6787 S7:48295       W:4373 ESTABLISHED 

Si je fais une décharge de fil des serveurs, je vois les fils sont également coincés dans java.net.SocketInputStream.socketRead0(Native Method). Je m'attendrais à une écriture, mais peut-être qu'ils attendent un ACK? (Pas sûr ici, est-ce que ça apparaitrait en Java?)

Maintenant, la chose la plus étrange est: après 15 minutes (et c'est toujours 15 minutes), les résultats sont reçu, les prises sont fermées, et tout continue comme d'habitude.

Cela fonctionnait toujours avant. Les serveurs S ont été déplacés vers un autre centre de données. Par conséquent, W et S ne se trouvent plus dans le même centre de données. En outre, S est derrière un pare-feu. Tous les ports devraient être autorisés entre S et W (on me dit). Le mystère est vraiment le délai de 15 minutes. Je pensais que cela pourrait être une protection contre DDOS?

Je ne suis pas un expert du réseau, j'ai donc demandé de l'aide, mais personne n'est disponible pour m'aider. J'ai passé 30 minutes avec un gars capturant des paquets avec Wireshark (anciennement Ethereal), mais pour des "raisons de sécurité", je ne peux pas regarder le résultat. Il doit analyser cela et revenir à moi. J'ai demandé les journaux du pare-feu; même histoire.

Je ne suis pas root ou administrateur sur ces boites, maintenant je ne sais pas quoi faire ... Je ne m'attends pas à une solution de votre part, mais quelques idées sur la façon de progresser seraient géniales!

+0

Je remarque que vous avez accepté ma réponse (merci). Alors avez-vous déjà résolu cela? Quel était le problème? –

+0

Il s'est avéré être un problème de routage - ce que je soupçonnais tout au long. Malheureusement, l'équipe du réseau n'a pas partagé avec moi les détails, je sais juste qu'ils ont changé la route par défaut pour éviter de passer par un routeur "suspect". –

Répondre

3

Si cela a fonctionné correctement dans votre réseau local, alors je ne prévois pas que ce soit un problème de programmation (par exemple les commentaires flush()).

La connectivité réseau entre les deux machines est-elle normale? Pouvez-vous transférer des quantités similaires de données via (par exemple) FTP sans problème. Pouvez-vous répliquer ce problème en associant un script client/serveur pour envoyer des blocs de données de taille appropriée? c'est-à-dire que la connectivité réseau est bonne entre W et S?

Une autre question. Vous avez maintenant un pare-feu entre. Cela pourrait-il être un goulot d'étranglement possible qui n'existait pas auparavant? (Je ne sais pas comment cela expliquerait le retard conséquent de 15m si).

Question finale. Quels sont les paramètres de configuration TCP configurés (sur W et S - je pense aux paramètres du niveau OS). Y a-t-il quelque chose qui suggérerait ou conduirait à un chiffre de 15m?

Vous ne savez pas si c'est utile.

1

Un flush() du côté S est-il manquant après l'envoi de la réponse?

+0

Non, le même code est exécuté pour les autres, et cela fonctionne bien. Cela fonctionne également sur d'autres environnements. Cela a bien fonctionné dans le passé aussi. C'est définitivement un problème de réseau. –

1

Droite. Si vous utilisez un BufferedOutputStream, vous devez appeler flush() à moins d'atteindre la taille maximale du buffer.

+0

Flush est appelé. –

1

En plus d'essayer que Brian a dit, vous pouvez également vérifier les points suivants

1) Exécutez tcpdump sur l'un des serveurs, et voir la séquence des flux de messages à partir du moment où un travail est initié à après la délai, lorsque tout le traitement est terminé. Cela vous indiquera de quel côté est le retard (W ou S). Vérifiez s'il y a des retransmissions, des accusés de réception manqués, etc.

2) Y a-t-il une sorte de fragmentation entre W et S?

3) Quelles sont les conditions de charge du réseau sur les serveurs sur lesquels les octets sont bloqués? Une charge importante provoque-t-elle des erreurs de sortie, entraînant le non-vidage des files d'attente des sockets? (Il peut également y avoir un bug NIC, où après avoir rencontré une condition d'erreur, les tampons NIC ne sont pas vidés ou ne reprennent pas la transmission, et une telle condition est effacée par un chien de garde)

Plus d'informations sur les deux ci-dessus aideraient certainement.

+0

N'ayez pas suffisamment de privilèges pour exécuter tcpdump, mais c'est ce que j'essaie de faire avec les gars du réseau. Vous n'êtes pas sûr des conditions réseau.Sur les sous-réseaux où W et S sont, la charge est faible, mais il peut y avoir un goulot d'étranglement dans un routeur où les paquets passent. –

0

Etes-vous sûr que les threads bloqués dans les appels en lecture sont les mêmes threads qui envoyaient les données? Est-il possible que les threads réellement impliqués soient à la place bloqués sur une autre activité, et votre stackdump montre d'autres threads innocents qui font juste des socket i/o? Cela fait un moment que j'ai travaillé avec Java, mais je me souviens vaguement de la JVM utilisant des sockets pour IPC.

Je voudrais examiner tout le côté de réception pour voir si l'un d'eux est le récepteur prévu et fait plutôt quelque chose d'autre pendant 15 minutes. Le fait que cela fonctionne dans un emplacement par rapport à un autre indique généralement une erreur de synchronisation d'application, pas un problème de centre de données.

+0

Oui, j'en suis sûr. Les threads en question sont dans un pool d'unités d'exécution dédié et sont nommés différemment. Je ne comprends pas la logique derrière la synchronisation menant à l'application. Mais je suis d'accord 15 minutes c'est beaucoup pour un timeout réseau. –

+0

hmm, vérifiez la fermeture des fenêtres TCP de réception; cela indique un problème d'application. Reniflez physiquement chaque hôte pour obtenir la véritable image du trafic de bout en bout. casser l'application Windows dans un débogueur pendant 20 min pour voir si les autres serveurs finissent quand même. –