2009-10-22 3 views
1

J'ai donc une application qui fonctionne sur gridgain et le fait avec succès pendant environ 12-24 heures de tests de stress avant qu'il commence à agir drôle. Après cette période de temps, la demande va soudainement commencer à répondre à toutes les demandes, à l'exception java.nio.channels.ClosedByInterruptException (full trace de la pile est au http://pastie.org/664717Java Gridgain application commence à échouer après 1 jour de stress test

La méthode qui a échoué est de (modifié pour utiliser la rétroaction @stephenc)

public static com.vlc.edge.FileChannel createChannel(final File file) { 
    FileChannel channel = null; 
    try { 
    channel = new FileInputStream(file).getChannel(); 
    channel.position(0); 
    final com.vlc.edge.FileChannel fileChannel = new FileChannelImpl(channel); 
    channel = null; 
    return fileChannel; 
    } catch (FileNotFoundException e) { 
    throw new VlcRuntimeException("Failed to open file: " + file, e); 
    } catch (IOException e) { 
    throw new VlcRuntimeException(e); 
    } finally { 
    if (channel != null) { 
     try { 
     channel.close(); 
     } catch (IOException e){ 
     // noop 
     LOGGER.error("There was a problem closing the file: " + file); 
     } 
    } 
    } 
} 

et la fonction d'appel se ferme correctement l'objet

private void fillContactBuffer(final File signFile) { 
    contactBuffer = ByteBuffer.allocate((int) signFile.length()); 
    final FileChannel channel = FileUtils.createChannel(signFile); 
    try { 
     channel.read(contactBuffer); 
    } finally { 
     channel.close(); 
    } 
    contactBuffer.rewind(); 
} 

l'application sert essentiellement comme un analyseur de fichiers distribué il fait beaucoup de ces types d'opérations (ouvrira typiquement environ 10 canaux par requête par nœud). Il semble que, après une certaine période, il cesse d'être en mesure d'ouvrir des fichiers et je ne sais pas pourquoi cela pourrait se produire et j'apprécierais grandement ceux qui peuvent me dire ce qui pourrait être à l'origine de ce problème. le bas et le réparer. Si cela est possiblement lié à l'épuisement du gestionnaire de fichiers, j'adorerais avoir des conseils pour en savoir plus ... ie interroger la JVM pendant son exécution ou utiliser les outils de ligne de commande linux pour en savoir plus sur les handles actuellement ouverts .

mise à jour: J'ai été en utilisant des outils de ligne de commande pour interroger la sortie de lsof et n'ont pas été en mesure de voir la preuve que les descripteurs de fichiers sont maintenus ouverts ... chaque nœud dans la grille a une très profil stable des fichiers ouverts que je peux voir changer lorsque le code ci-dessus est exécuté ... mais il revient toujours à un nombre stable de fichiers ouverts.

liés à cette question: Freeing java file handles

Répondre

2

Il y a deux scénarios où les descripteurs de fichiers peuvent ne pas être en cours de fermeture:

  1. Il pourrait y avoir un autre code qui ouvre les fichiers.
  2. Il pourrait y avoir un autre morceau de code qui appelle createChannel(...) et ne remet pas fillContactBuffer(...)
  3. Si channel.position(0) déclenche une exception, ne sera pas fermé le canal. Le correctif consiste à réorganiser le code afin que les instructions suivantes soient à l'intérieur du bloc try.

    channel.position(0); 
    return new FileChannelImpl(channel); 
    

EDIT: Au vu de la trace de la pile, il semble que les deux méthodes sont différentes dans le code-bases. Je pointerais le doigt de la faute à la méthode createChannel. Il y a une fuite potentielle, même si ce n'est pas la source de vos problèmes. Il a besoin d'une clause interne finally pour s'assurer que le canal est fermé en cas d'exception.

Quelque chose comme ça devrait faire l'affaire. Notez que vous devez vous assurer que le bloc finally ne ferme pas le canal en cas de succès!

public static com.vlc.edge.FileChannel createChannel(final File file) { 
    final FileChannel channel = null; 
    try { 
     channel = new FileInputStream(file).getChannel(); 
     channel.position(0); 
     FileChannel res = new FileChannelImpl(channel); 
     channel = null; 
     return res; 
    } catch (FileNotFoundException e) { 
     throw new VlcRuntimeException("Failed to open file: " + file, e); 
    } catch (IOException e) { 
     throw new VlcRuntimeException(e); 
    } finally { 
     if (channel != null) { 
      try { 
       channel.close(); 
      } catch (...) { 
       ... 
      } 
     } 
    } 
} 

FOLLOWUP beaucoup plus tard

Étant donné que la fuite de descripteur de fichier a été éliminé comme cause possible, ma prochaine théorie serait que le côté serveur interrompt effectivement ses propres fils en utilisant Thread.interrupt(). Certains appels d'E/S de bas niveau répondent à une interruption en lançant une exception, et l'exception racine lancée ici semble comme une exception de ce type. Cela n'explique pas pourquoi cela se produit, mais à la conjecture, je dirais que c'était le framework côté serveur qui essayait de résoudre un problème de surcharge ou de blocage.

Questions connexes