Подтвердить что ты не робот

Не используйте System.out.println в коде на стороне сервера

Я слышал, что использование System.out.println для ведения журнала - очень плохая практика, и это может привести к сбою сервера.

Я не использую этот подход, но мне очень интересно знать, почему System.out.println может сделать так мусорные вещи, когда они используются во внутреннем коде.

4b9b3361

Ответ 1

System.out.println - это операция ввода-вывода, и поэтому требуется много времени. Проблема с его использованием в вашем коде заключается в том, что ваша программа будет ждать завершения println. Это может быть не проблема с небольшими сайтами, но как только вы получите нагрузку или много итераций, вы почувствуете боль.

Лучший подход - использовать структуру ведения журнала. Они используют очередь сообщений и записывают только в том случае, если другой вывод не выполняется.

И еще одно преимущество заключается в том, что вы можете настраивать отдельные файлы журналов для разных целей. Что-то ваша команда Ops будет вас любить.

Подробнее здесь:

Ответ 2

Это плохая практика, потому что, когда ваше приложение входит в Production, вы не можете отделять журналы приложений от журналов сервера.

Команды Prod хотят, чтобы вы отделили журналы, созданные вашим приложением, от тех, которые были с сервера приложений (tomcat, websphere и т.д.): они хотят иметь возможность контролировать сервер приложений по-разному из самого приложения.

Кроме того, используя System.out, вы не можете определить уровень журнала: в разделе "Производство" вы не хотите печатать отладочную информацию.

Ответ 3

Посмотрите статью Адама Биенса в выпуске журнала Java Magazine Ноябрь/Дезембер о стресс-тестировании приложений JEE6 - бесплатно онлайн, вам нужно только подписаться на него.

На стр. 43 он показывает, что серверные приложения, которым удается обрабатывать 1700 транзакций в секунду, падает до 800 при вставке одного System.out.println с фиксированной строкой в ​​каждом.

Ответ 4

Считается, что это плохо, потому что System.out.println(); потребляет больше процессора и, следовательно, выход медленный, значит, вредит производительности. (Фактически каждая операция ввода-вывода ест процессор).

Ответ 5

Причина не в том, что сервер может выйти из строя, но может быть трудно найти такой вывод на сервере. Вы всегда должны использовать какую-то структуру ведения журнала с определенным поведением и выходным файлом.

Ответ 6

Во-первых, наличие нескольких запросов, поражающих ваш сервер, и печать журнала на System.out не является хорошей практикой.

  • Все журналы печатаются на экране (дескриптор файла). Нет способа прокрутить назад и прочитать журнал.
  • System.out не синхронизируется. Для управления печатью с помощью System.out должно быть управление concurrency
  • Вы не можете определить уровни журнала через System.out. Вы не можете самостоятельно отделять уровни журнала для разделения выходов на лету.

Надеюсь, это поможет.

Ответ 7

  • Программа будет ждать завершения println. Журналы используют очередь сообщений и записывают только в том случае, если другой выход не выполняется.
  • System.out.println(SOP) не являются потокобезопасными (например, асинхронными) Регистраторы являются потокобезопасными (то есть синхронными)
  • Регистраторы могут быть легко конфигурируемы a. Форматирование, ограничение содержимого журнала, доступного регистраторам b. Несколько файлов журнала регистрации конечных пользователей, консоли, DB
  • SOP записывают журналы в файлы журнала сервера. Нам нужно, чтобы журналы приложений были отделены от журналов сервера, так как это может привести к сбою сервера.
  • Серверные приложения, которым удается обрабатывать 1700 транзакций в секунду, падает до 800 при вставке одного SOP с фиксированной строкой в ​​каждом

Ответ 8

Еще одна причина заключается в том, что System.out и err являются PrintStreams, которые потребляют все основные IOExceptions. См. Следующие методы 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 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 для System out, поэтому они даже не знают, что что-то произошло.

Ответ 9

Использование стандартного изложения - плохая практика. Однако, если у вас есть библиотека или код, который использует System.out и System.err, вы можете написать собственный PrintStream, который вместо этого записывает имя потока и info() и ошибку(). Как только вы это сделаете, вы можете быть более спокойным в использовании System.out, поскольку он будет записывать в журналы, например. log4j.

В идеале вы будете использовать соответствующие журналы непосредственно esp для регистрации уровня отладки. IMHO его не имеет большого значения, если вы не используете встроенный System.out/err! (По общему мнению, большое допущение)

Если вы используете System.out, который перенаправляется в файл или использует log4j или Java Logger для записи в файл, производительность почти точно такая же.