web-dev-qa-db-fra.com

N'utilisez pas System.out.println dans le code côté serveur

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.

55
Oleksandr

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:

52
Lars

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.

21
Alexander Rühl

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.

19

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).

5
Harry Joy

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.

3
tobiasbayer
  1. Le programme attendra la fin de l'impression. Les enregistreurs utilisent la file d'attente de messages et n'écrivent que si aucune autre sortie n'est en cours.
  2. System.out.println (SOP) ne sont pas thread-safe (c'est-à-dire asynchrones) Les enregistreurs sont thread-safe (c'est-à-dire synchrones)
  3. Les enregistreurs sont hautement configurables a. Formatage, limitation du contenu des journaux réalisable par les enregistreurs b. Journalisation de destinations multiples - fichier, console, base de données
  4. Les SOP écrivent les journaux dans les fichiers journaux du serveur. Nous devons garder les journaux d'application séparés des journaux du serveur car cela peut entraîner une défaillance du serveur
  5. Les applications serveur qui parviennent à gérer 1700 transactions par seconde tombent à seulement 800 lors de l'insertion d'une seule SOP avec une chaîne fixe dans chaque
2
Yatish Balaji

D'une part, avoir plusieurs demandes frappant votre serveur et imprimant le journal sur System.out n'est pas une bonne pratique.

  1. Tous les journaux sont imprimés à l'écran (descripteur de fichier). Il n'y a aucun moyen de revenir en arrière et de lire le journal.
  2. System.out n'est pas synchronisé. Il doit y avoir une gestion des accès concurrents pour gérer l'impression via System.out
  3. Vous ne pouvez pas déterminer les niveaux de journal via 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.

2
Buhake Sindi

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.

1
Gábor Lipták

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.

1
Peter Lawrey