Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/366.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/logging/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 不要在服务器端代码中使用System.out.println_Java_Logging_Backend - Fatal编程技术网

Java 不要在服务器端代码中使用System.out.println

Java 不要在服务器端代码中使用System.out.println,java,logging,backend,Java,Logging,Backend,我听说使用System.out.println进行日志记录是一种非常糟糕的做法,这可能会迫使服务器失败 我不使用这种方法,但我很想知道为什么System.out.println在后端代码中使用时会造成如此多的垃圾。这被认为是不好的,因为System.out.println()消耗了更多的cpu,因此输出速度变慢意味着会影响性能。(实际上,每个I/O操作都会消耗cpu)。这是一种不好的做法,因为当应用程序投入生产时,无法将应用程序日志与服务器日志分开 Prod团队希望您将应用程序生成的日志与来自应

我听说使用
System.out.println
进行日志记录是一种非常糟糕的做法,这可能会迫使服务器失败


我不使用这种方法,但我很想知道为什么System.out.println在后端代码中使用时会造成如此多的垃圾。

这被认为是不好的,因为
System.out.println()消耗了更多的cpu,因此输出速度变慢意味着会影响性能。(实际上,每个I/O操作都会消耗cpu)。

这是一种不好的做法,因为当应用程序投入生产时,无法将应用程序日志与服务器日志分开

Prod团队希望您将应用程序生成的日志与来自应用程序服务器(tomcat、websphere等)的日志分开:他们希望能够以不同于应用程序本身的方式监控应用程序服务器


此外,使用System.out,您无法定义日志级别:在生产环境中,您不想打印调试信息。

原因不是服务器可能出现故障,而是在服务器上很难找到此类输出。您应该始终使用某种具有定义行为和输出文件的日志框架。

例如,让多个请求命中您的服务器并在
系统上打印日志。out
不是好做法

  • 所有日志都打印在屏幕上(文件描述符)。没有办法向后滚动并读取日志
  • System.out
    未同步。必须有并发管理才能通过
    System.out
  • 您无法通过
    System.out
    确定日志级别。您不能在运行时将日志级别分隔为单独的输出

  • 我希望这会有所帮助。

    System.out.println是一个IO操作,因此非常耗时。 在代码中使用它的问题是,程序将等待println完成。对于小型站点来说,这可能不是问题,但一旦您获得负载或多次迭代,您就会感到痛苦

    更好的方法是使用日志框架。 它们使用消息队列,并且仅在没有其他输出进行时写入

    另一个好处是,您可以为不同的目的配置单独的日志文件。 你的行动团队会喜欢你的

    在此处阅读更多信息:

    查看Java杂志11月/12月版中关于压力测试JEE6应用程序的Adam Biens-它是免费的,您只需订阅即可


    在第43页,他指出,当插入单个
    System.out.println
    时,一个每秒处理1700个事务的服务器应用程序下降到只有800个,每个应用程序中都有固定字符串。

    使用标准输出是一种不好的做法。但是,如果您有一个库,或者代码使用System.out和System.err,那么您可以编写自己的PrintStream,它记录线程名称和info(),而error()记录文本。完成此操作后,您可能会更轻松地使用System.out,因为它将写入日志,例如log4j

    理想情况下,您将直接使用适当的日志进行调试级日志记录。如果你不使用内置的System.out/err,那么它就没有那么重要了!(无可否认,这是一个很大的假设)


    无论您使用重新定向到文件的System.out,还是使用log4j或Java Logger写入文件,性能几乎完全相同。

    另一个原因是System.out和err是打印流,它们消耗所有底层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;
    }
    
    *或同等标准。 * *@return
    true
    当且仅当此流遇到 *
    IOException
    除了 *
    中断异常
    ,或 *
    setError
    方法已被调用 */ 公共布尔校验错误(){ if(out!=null) 冲洗(); if(out instanceof java.io.PrintStream){ 打印流ps=(打印流)输出; 返回ps.checkError(); } 返回故障; }
    因此,底层流中的IOException总是被使用,而且通常人们从不在System out上调用checkError,所以他们甚至不知道发生了什么事情

  • 程序将等待直到println完成。 记录器仅在没有其他输出进行时才使用消息队列和写入
  • System.out.println(SOP)不是线程安全的(即异步的) 记录器是线程安全的(即同步的)
  • 记录器是高度可配置的
    a.
    格式化,限制日志记录者可获得的日志内容
    b.
    多目标日志记录–文件、控制台、数据库
  • SOP将日志写入服务器日志文件。 我们需要将应用程序日志与服务器日志分开,因为这可能导致服务器故障
  • 当在每个SOP中插入一个带有修复字符串的SOP时,每秒处理1700个事务的服务器应用程序下降到只有800个

  • 我相信这个问题(或其背后的原理)比答案要有趣得多。关于第一点:很容易将输出重定向到一个文件,以便您可以滚动任何您想要的内容。这是如果您从控制台进行管道传输,但这是资源密集型的。通常主要问题不是CPU使用情况,而是I/O使用情况,事实上,
    System.out.println
    与Java(以及大多数其他环境)中的大多数I/O调用一样。这会完全扼杀吞吐量。