Java raccroche?

introduction

Java du côté serveur se bloque-t-il vaguement sans réponse pour accéder à partir du navigateur? Peut être demandé. Pourquoi vous méfiez-vous de Java VM? Je voudrais dire </ FONT>, mais il semble que la raison en soit que je veuille poursuivre l’enquête dans l’ordre suivant.

  • Nécessite l'avis du personnel d'assistance en tant que VM Java ou middleware fonctionnant
  • S'il n'y a pas de problème, la réponse à cet effet est OK
  • Avec l'avis du personnel de soutien, je souhaite contacter le personnel du réseau ou de la base de données au besoin.

Je publierai un exemple courant de cette situation.

Dump de thread Java

Au moment où vous pouvez obtenir le vidage de thread Java, la fonction Java VM fonctionne correctement, on peut donc dire que la machine virtuelle Java elle-même n'est pas dans une situation bloquée, mais examinons d'abord le contenu.

** Dump de thread de la partie problématique **

"default task-4" #116 prio=5 os_prio=0 tid=0x0000000003ba3800 nid=0x7894 runnable [0x00007f58c80c7000]
   java.lang.Thread.State: RUNNABLE
        at java.net.SocketInputStream.socketRead0(Native Method)
        at java.net.SocketInputStream.socketRead(SocketInputStream.java:116)
        at java.net.SocketInputStream.read(SocketInputStream.java:171)
        at java.net.SocketInputStream.read(SocketInputStream.java:141)
        at oracle.net.ns.Packet.receive(Packet.java:311)
        at oracle.net.ns.DataPacket.receive(DataPacket.java:105)
        at oracle.net.ns.NetInputStream.getNextPacket(NetInputStream.java:305)
        at oracle.net.ns.NetInputStream.read(NetInputStream.java:249)
        at oracle.net.ns.NetInputStream.read(NetInputStream.java:171)
        at oracle.net.ns.NetInputStream.read(NetInputStream.java:89)
        at oracle.jdbc.driver.T4CSocketInputStreamWrapper.readNextPacket(T4CSocketInputStreamWrapper.java:123)
        at oracle.jdbc.driver.T4CSocketInputStreamWrapper.read(T4CSocketInputStreamWrapper.java:79)
        at oracle.jdbc.driver.T4CMAREngineStream.unmarshalUB1(T4CMAREngineStream.java:426)
        at oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:390)
        at oracle.jdbc.driver.T4CTTIfun.doRPC(T4CTTIfun.java:249)
        at oracle.jdbc.driver.T4C8Oall.doOALL(T4C8Oall.java:566)
        at oracle.jdbc.driver.T4CStatement.doOall8(T4CStatement.java:202)
        at oracle.jdbc.driver.T4CStatement.doOall8(T4CStatement.java:45)
        at oracle.jdbc.driver.T4CStatement.executeForDescribe(T4CStatement.java:766)
        at oracle.jdbc.driver.OracleStatement.executeMaybeDescribe(OracleStatement.java:897)
        at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1026)
        at oracle.jdbc.driver.OracleStatement.executeQuery(OracleStatement.java:1244)
        - locked <0x00000000fcd35220> (a oracle.jdbc.driver.T4CConnection)
        at oracle.jdbc.driver.OracleStatementWrapper.executeQuery(OracleStatementWrapper.java:420)
        at org.jboss.jca.adapters.jdbc.WrappedStatement.executeQuery(WrappedStatement.java:397)
        at abc.doGet(abc.java:37)
...Omission...

Dans cet exemple, lorsque vous accédez à un servlet appelé abc, vous n'obtiendrez pas de réponse, mais si vous regardez la pile liée à cet abc, cela ressemble à ce qui précède. De bas en haut, vous pouvez voir de doExecuteWithTimeout dans jdbc vers NetInputStream.read et socketRead0, en attente d'une lecture. Attendre quelques dizaines de secondes et obtenir à nouveau un thread dump ne change pas cette situation. Il semble que le délai d'expiration de jdbc a été atteint car il y a en quelque sorte doExecuteWithTimeout. En d'autres termes, la 5ème opération ci-dessous ne passe pas au processus suivant en attendant.

  1. Requête HTTP GET du navigateur au serveur
  2. Le servlet envoie SQL à oracle avec jdbc pour créer le contenu de la réponse.
  3. La réponse SQL n'a pas été obtenue dans le délai d'expiration de la requête.
  4. Émettez une annulation à jdbc avec instruction.cancel comme processus d'expiration
  5. En attente de la réponse à l'annulation.
  6. Si vous obtenez une réponse à l'annulation, elle sera traitée comme SQLTimeoutException et l'exception sera gérée ... Peut-être.

** Remarque: statement.cancel est annulé en l'envoyant à un DB qui répond correctement **

Y avait-il donc un problème avec la base de données? ?? ?? Vous pourriez penser cela.

La vue du côté de la base de données

À partir du contenu du thread dump, demandez s'il y a une erreur du côté de la base de données pendant cette période ... ** Aucune anomalie n'a été trouvée. ** Que pensez-vous DB en premier lieu? On m'a dit </ FONT>.

Le paquet d'annulation est-il envoyé?

S'il n'y a pas de problème avec la base de données, je me demande si statement.cancel est vraiment exécuté et envoyé à la base de données sous forme de paquet. Alors, reproduisons le problème et capturons et vérifions le paquet.

** Côté système exécutant Java **

statement.Paquet correspondant à annuler

13:14:08.948939 IP rhel74.38860 > 192.168.1.25.1521: Flags [P.U], seq 4510:4511, ack 5404, win 44020, urg 1, length 1
..s....
        0x0010:  c0a8 0119 97cc 05f1 f070 d6a2 c3a2 111d  ......-..p......
        0x0020:  5038 abf4 cdeb 0001 21                   P8......!

Faites attention aux indicateurs [P.U], mais P.U, c'est-à-dire que les indicateurs PUSH et URG sont définis. Et les données utilisateur sont un caractère de "!". À partir de ce contenu, vous pouvez voir que statement.cancel est exécuté et que la demande d'annulation est envoyée correctement.

** Du côté de la réception? ** ** Lorsque je prends une capture de paquet et la vérifie sur le système côté base de données, le paquet correspondant à ce qui précède est introuvable. C'est comme ça qui a été jeté quelque part parce qu'il est passé à travers la pluralité de périphériques réseau Yara NAT.

  • Dans mon expérience, j'ai vu un modèle dans lequel seul l'indicateur URG de TCP a été abandonné. Le côté base de données oracle ne répond pas aux paquets "!" Qui n'ont pas d'URG défini.

De cette façon, si l'annulation de l'instruction à la base de données n'est pas atteinte comme prévu, il ne sera pas possible de temporiser et d'annuler le très long SQL, ce qui entraînera une réponse sans fin. Je vais.

Le problème est dans le réseau

Je soupçonne que certains mécanismes, tels que NAT ou pare-feu dans le chemin réseau, ne gèrent pas correctement ce paquet marqué URG. Par conséquent, sur la base de la capture de paquet capturé, je pense que la personne en charge du réseau sera informée que le paquet contenant ce drapeau URG n'est pas arrivé. Aussi Que pensez-vous du réseau? Vous pourriez être appelé </ FONT>, mais ...

Il existe une grande variété d'erreurs lorsque des problèmes surgissent.

Dans le cas d'un tel modèle d'attente d'une réponse de jdbc et l'annulation n'est pas effective, il n'est pas toujours le cas qu'il n'y ait qu'un seul type d'événement. Par exemple, après le démarrage d'une transaction, JTA (Java Transaction API) peut être configuré pour récupérer une transaction incomplète. Si l'opération de récupération est définie pour essayer toutes les 30 minutes jusqu'à ce que 24 heures se soient écoulées, la même réponse d'annulation sera attendue même si l'opération de récupération est tentée. Toutes les 30 minutes, le nombre de threads de récupération augmente et, par conséquent, de nombreux threads sont finalement créés, erreur de fichiers ouverts trop nombreux et erreur de ressource telle que Impossible de créer un nouveau thread natif. Cela peut conduire à. De plus, comme il n'abandonnera pas avant que 24 heures se soient écoulées, la même opération sera répétée même si elle est redémarrée.

Sur la base de ces points, je pense qu'il est important de vérifier le passage du temps et le contenu du thread dump pour comprendre ce qui se passe.

Nous espérons que vous trouverez cela utile.

Recommended Posts