J'ai entendu dire qu'en utilisant System.out.println
à des fins de journalisation est une très mauvaise pratique et cela peut forcer le serveur à tomber en panne.
Je n'utilise pas cette approche, mais je suis très intéressé de savoir pourquoi System.out.println pourrait faire des choses si trash lorsqu'il est utilisé dans du code backend.
System.out.println est une opération IO et prend donc beaucoup de temps. Le problème avec son utilisation dans votre code est que votre programme attendra la fin de l'impression. Cela peut ne pas être un problème avec les petits sites, mais dès que vous obtenez une charge ou de nombreuses itérations, vous ressentirez la douleur.
La meilleure approche consiste à utiliser un cadre de journalisation. Ils utilisent une file d'attente de messages et n'écrivent que si aucune autre sortie n'est en cours.
Et un autre avantage est que vous pouvez configurer des fichiers journaux distincts à des fins différentes. Quelque chose pour lequel votre équipe Ops vous aimera.
En savoir plus ici:
Découvrez Adam Biens article dans le Java édition du magazine novembre/décembre sur les tests d'effort des applications JEE6 - c'est gratuit en ligne , vous n'avez qu'à abonnez-vous.
À la page 43, il montre qu'un serveur d'applications qui parvient à gérer 1700 transactions par seconde tombe à seulement 800 lors de l'insertion d'un seul System.out.println
avec une chaîne fixe dans chacun.
C'est une mauvaise pratique car lorsque votre application passe en production, vous ne pouvez pas séparer les journaux d'application des journaux du serveur.
Les équipes Prod veulent que vous sépariez les journaux produits par votre application de ceux du serveur d'application (Tomcat, websphere, etc ...): ils veulent pouvoir surveiller le serveur d'application différemment de l'application elle-même.
De plus, en utilisant System.out, vous ne pouvez pas définir le niveau de journalisation: dans Production, vous ne voulez pas imprimer les informations de débogage.
Il est considéré comme mauvais car System.out.println();
mange plus de cpu et donc la sortie est lente, ce qui nuit aux performances. (En fait, chaque opération d'E/S consomme de la CPU).
La raison n'est pas que le serveur peut échouer, mais il peut être difficile de trouver une telle sortie sur le serveur. Vous devez toujours utiliser une sorte de cadre de journalisation avec un comportement défini et un fichier de sortie.
a.
Formatage, limitation du contenu des journaux réalisable par les enregistreurs b.
Journalisation de destinations multiples - fichier, console, base de donnéesD'une part, avoir plusieurs demandes frappant votre serveur et imprimant le journal sur System.out
n'est pas une bonne pratique.
System.out
n'est pas synchronisé. Il doit y avoir une gestion des accès concurrents pour gérer l'impression via System.out
System.out
. Vous ne pouvez pas séparer vos niveaux de journal pour séparer les sorties à la volée.J'espère que ça aide.
Une autre raison est que System.out et err sont des PrintStreams, qui consomment toutes les IOExceptions sous-jacentes. Voir ces méthodes de PrintStreams:
/**
* Writes the specified byte to this stream. If the byte is a newline and
* automatic flushing is enabled then the <code>flush</code> method will be
* invoked.
*
* <p> Note that the byte is written as given; to write a character that
* will be translated according to the platform's default character
* encoding, use the <code>print(char)</code> or <code>println(char)</code>
* methods.
*
* @param b The byte to be written
* @see #print(char)
* @see #println(char)
*/
public void write(int b) {
try {
synchronized (this) {
ensureOpen();
out.write(b);
if ((b == '\n') && autoFlush)
out.flush();
}
}
catch (InterruptedIOException x) {
Thread.currentThread().interrupt();
}
catch (IOException x) {
trouble = true;
}
}
/**
* Flushes the stream and checks its error state. The internal error state
* is set to <code>true</code> when the underlying output stream throws an
* <code>IOException</code> other than <code>InterruptedIOException</code>,
* and when the <code>setError</code> method is invoked. If an operation
* on the underlying output stream throws an
* <code>InterruptedIOException</code>, then the <code>PrintStream</code>
* converts the exception back into an interrupt by doing:
* <pre>
* Thread.currentThread().interrupt();
* </pre>
* or the equivalent.
*
* @return <code>true</code> if and only if this stream has encountered an
* <code>IOException</code> other than
* <code>InterruptedIOException</code>, or the
* <code>setError</code> method has been invoked
*/
public boolean checkError() {
if (out != null)
flush();
if (out instanceof Java.io.PrintStream) {
PrintStream ps = (PrintStream) out;
return ps.checkError();
}
return trouble;
}
Donc, une IOException du flux sous-jacent est TOUJOURS consommée, et généralement les gens n'appellent jamais checkError sur System out, donc ils ne savent même pas que quelque chose s'est produit.
L'utilisation de la sortie standard est une mauvaise pratique. Cependant, si vous avez une bibliothèque ou un code qui utilise System.out et System.err, vous pouvez écrire votre propre PrintStream qui enregistre le nom du thread et info () et error () le texte à la place. Une fois que vous avez fait cela, vous pouvez être plus détendu à propos de l'utilisation de System.out car il écrit dans les journaux, par exemple. log4j.
Idéalement, vous utiliserez directement les journaux appropriés, notamment pour la journalisation au niveau du débogage. À mon humble avis, cela n'a pas tant d'importance, à condition que vous n'utilisiez pas le System.out/err intégré! (Une grande hypothèse certes)
Que vous utilisiez System.out qui est redirigé vers un fichier ou que vous utilisiez log4j ou Java Logger pour écrire dans un fichier, les performances sont presque exactement les mêmes.