web-dev-qa-db-ja.com

サーバー側のコードでSystem.out.printlnを使用しないでください

System.out.printlnロギングを目的とすることは非常に悪い習慣であり、これはサーバーの障害を強制する可能性があります。

私はこのアプローチを使用しませんが、System.out.printlnがバックエンドコードで使用されたときに非常にゴミになる理由を知ることに非常に興味があります。

49
Oleksandr

System.out.printlnはIO操作であるため、時間がかかります。コードで使用する際の問題は、printlnが終了するまでプログラムが待機することです。これは小さなサイトでは問題にならないかもしれませんが、負荷がかかったり、何度も繰り返されるとすぐに痛みを感じます。

より良いアプローチは、ロギングフレームワークを使用することです。メッセージキューを使用し、他の出力が行われていない場合にのみ書き込みます。

また、別の利点は、さまざまな目的に応じて個別のログファイルを構成できることです。 Opsチームがあなたを愛しているもの。

詳細はこちら:

52
Lars

JEE6アプリケーションのストレステストに関する11月/ 12月のJavaマガジンエディションのAdam Biens article をチェックしてください-無料です online 、購読するだけです。

43ページでは、1秒あたり1700トランザクションを処理するサーバーアプリケーションが、それぞれに修正文字列を含む単一のSystem.out.printlnを挿入すると、800にしか落ちないことを示しています。

21
Alexander Rühl

アプリケーションが実稼働環境に移行すると、アプリケーションログとサーバーログを分離できないため、これは悪い習慣です。

Prodチームは、アプリケーションによって生成されたログを、アプリケーションサーバー(Tomcat、websphereなど)のログと分離することを望んでいます。アプリケーションサーバーとは別にアプリケーションサーバーを監視できるようにしたいのです。

さらに、System.outを使用してログレベルを定義することはできません。実稼働環境では、デバッグ情報を出力する必要はありません。

19

System.out.println();はより多くのCPUを消費するため、出力が遅くなるため、パフォーマンスが低下するため、悪いと見なされます。 (実際には、すべてのI/O操作がCPUを消費します)。

5
Harry Joy

理由は、サーバーに障害が発生する可能性があるからではありませんが、サーバー上でそのような出力を見つけるのは難しいかもしれません。定義された動作と出力ファイルを備えた何らかのロギングフレームワークを常に使用する必要があります。

3
tobiasbayer
  1. プログラムは、printlnが終了するまで待機します。ロガーはメッセージキューを使用して、他に出力が行われていない場合にのみ書き込みます。
  2. System.out.println(SOP)はスレッドセーフではありません(つまり、非同期)ロガーはスレッドセーフです(つまり、同期)
  3. ロガーは高度に設定可能ですa.フォーマット、ロガーによって達成可能なログコンテンツの制限b.複数の宛先ロギング–ファイル、コンソール、DB
  4. SOPは、サーバーのログファイルにログを書き込みます。サーバー障害につながる可能性があるため、アプリケーションログをサーバーログとは別に保管する必要があります
  5. 1秒あたり1700のトランザクションを処理するサーバーアプリケーションは、それぞれに修正文字列を含む単一のSOPを挿入すると、わずか800に低下します。
2
Yatish Balaji

1つは、サーバーに複数のリクエストを送信し、System.outにログを出力することは良い習慣ではありません。

  1. すべてのログが画面に出力されます(ファイル記述子)。スクロールバックしてログを読む方法はありません。
  2. System.outは同期されていません。 System.outを介して印刷を管理するには、同時実行管理が必要です。
  3. System.outを使用してログレベルを決定することはできません。ログレベルをその場で個別の出力に分離することはできません。

これがお役に立てば幸いです。

2
Buhake Sindi

もう1つの理由は、System.outとerrがPrintStreamsであり、基礎となるすべてのIOExceptionを消費していることです。 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;
}

そのため、基礎となるストリームからのIOExceptionは常に消費され、通常、システム出力時にcheckErrorを呼び出すことはないため、何かが起こったことさえ知らないのです。

1
Gábor Lipták

標準出力の使用は悪い習慣です。ただし、System.outおよびSystem.errを使用するライブラリまたはコードがある場合は、代わりにスレッド名とinfo()およびerror()を記録する独自のPrintStreamを作成できます。これを行うと、System.outを使用してログに書き込むため、System.outの使用についてよりリラックスできます。 log4j。

理想的には、適切なログを直接デバッグレベルのログ記録に使用します。私見では、組み込みのSystem.out/errを使用しない限り、それほど重要ではありません! (確かに大きな仮定)

ファイルにリダイレクトされるSystem.outを使用する場合でも、log4jまたはJava Loggerを使用してファイルに書き込む場合でも、パフォーマンスはほぼ同じです。

1
Peter Lawrey