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

发布于 2024-12-22 19:43:30 字数 128 浏览 2 评论 0原文

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

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

I heard that using System.out.println for logging purposes is a very bad practice and this may force the server to fail.

I don't use this approach but I am very interested in knowing why System.out.println could make so trash things when used in backend code.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

为你拒绝所有暧昧 2024-12-29 19:43:30

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

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

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

在此处阅读更多信息:

System.out.println is an IO-operation and therefor is time consuming.
The Problem with using it in your code is, that your program will wait until the println has finished. This may not be a problem with small sites but as soon as you get load or many iterations, you'll feel the pain.

The better approach is to use a logging framework.
They use a message queue and write only if no other output is going on.

And another benefit is that you can configure separate log files for different purposes.
Something your Ops team will love you for.

Read more here:

迟月 2024-12-29 19:43:30

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

他在第 43 页上展示了,当插入一个带有固定字符串的 System.out.println 时,每秒处理 1700 个事务的服务器应用程序会下降到仅 800 个。

Check out Adam Biens article in the Java Magazine edition November/Dezember about stress testing JEE6 applications - it's free online, you only have to subscribe to it.

On page 43 he shows, that a server applications which manages to handle 1700 transactions per second falls down to only 800 when inserting a single System.out.println with fix String in each.

天赋异禀 2024-12-29 19:43:30

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

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

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

It's a bad practice because when your application goes in Production, you can't separate application logs from server logs.

Prod teams want that you separate logs produced by your application from the ones from the app server (tomcat, websphere, etc...) : they want to be able to monitor the app server diffrently from the application itself.

Moreover, using System.out, you can't define the log level : in Production, you don't want to print debug information.

疾风者 2024-12-29 19:43:30

它被认为是不好的,因为 System.out.println(); 会占用更多的 cpu,因此输出变慢意味着会损害性能。 (实际上每个I/O操作都会吃cpu)。

It is considered to be bad because System.out.println(); eats more cpu and thus output comes slow means hurts the performance. (Actually every I/O operation eats cpu).

中性美 2024-12-29 19:43:30

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

The reason is not that the server might fail but it might be hard to find such output on the server. You should always use some kind of logging framework with a defined behaviour and output file.

你好,陌生人 2024-12-29 19:43:30

其一,让多个请求访问您的服务器并在 System.out 上打印日志并不是一个好的做法。

  1. 所有日志都会打印在屏幕上(文件描述符)。无法向后滚动并阅读日志。
  2. System.out 未同步。必须有并发管理来通过System.out管理打印。
  3. 您无法通过System.out确定日志级别。您无法即时分离日志级别以分离输出。

我希望这有帮助。

For one, having multiple requests hitting your server and printing the log on System.out isn't good practice.

  1. All the logs gets printed on screen (file descriptor). There's no way to scroll back and read the log.
  2. System.out isn't synchronized. There must be a concurrency management to manage printing via System.out
  3. You can't determine log levels through System.out. You can't separate your log levels to separate outputs on the fly.

I hope this helps.

我不在是我 2024-12-29 19:43:30
  1. 程序将等待,直到 println 完成。
    记录器使用消息队列,并且仅在没有其他输出发生时才进行写入。
  2. System.out.println (SOP) 不是线程安全的(即异步)
    记录器是线程安全的(即同步)
  3. 记录器是高度可配置的
    a. 格式化,限制记录器可实现的日志内容
    b. 多目标日志记录 – 文件、控制台、DB
  4. SOP 将日志写入服务器日志文件。
    我们需要将应用程序日志与服务器日志分开,因为这可能会导致服务器故障
  5. 服务器应用程序每秒处理 1700 个事务,当在每个事务中插入带有修复字符串的单个 SOP 时,每秒处理的事务数会下降到仅 800 个
  1. Program will wait until the println has finished.
    Loggers use message queue and write only if no other output is going on.
  2. System.out.println (SOPs) are not thread safe (i.e asynchronous)
    Loggers are thread safe (i.e synchronous)
  3. Loggers are highly configurable
    a. Formatting, Limiting log content achievable by loggers
    b. Multiple destination logging –file, console, DB
  4. SOPs write logs into Server log files.
    We need to keep application logs separate from Server logs as it may lead to Server Failure
  5. Server applications which manages to handle 1700 transactions per second falls down to only 800 when inserting a single SOPs with fix String in each
记忆里有你的影子 2024-12-29 19:43:30

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

理想情况下,您将直接使用正确的日志,特别是用于调试级别日志记录。恕我直言,只要您不使用内置的 System.out/err,它就没有那么重要! (诚​​然,这是一个很大的假设)

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

Using standard out is bad practice. However if you have a library, or code which uses System.out and System.err you can write your own PrintStream which logs the thread name and info() and error() the text instead. Once you have done this, you may be more relaxed about using System.out as it will write to the logs e.g. log4j.

Ideally you will use the proper logs directly esp for debug level logging. IMHO its doesn't have to matter that much, provided you don use the built-in System.out/err! (A big assumption admittedly)

Whether you use System.out which is re-directed to a file or use log4j or Java Logger to write to a file, the performance is almost exactly the same.

兔姬 2024-12-29 19:43:30

另一个原因是 System.out 和 err 是 PrintStream,它们消耗所有底层 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,因此他们甚至不知道发生了某些事情。

One more reason is that System.out and err are PrintStreams, which are consuming all underlying IOExceptions. See this methods of 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;
}

So an IOException from the underlying stream is ALWAYS consumed, and usually the people never call checkError on System out, so they are not even knowing that something happened.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文