Не используйте System.out.println в коде на стороне сервера - PullRequest
48 голосов
/ 22 декабря 2011

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

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

Ответы [ 9 ]

51 голосов
/ 22 декабря 2011

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

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

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

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

21 голосов
/ 22 декабря 2011

Ознакомьтесь с Adam Biens статья в журнале Java Magazine, ноябрь / декабрь о стресс-тестировании приложений JEE6 - это бесплатно онлайн , вам нужно только подписаться на него.

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

19 голосов
/ 22 декабря 2011

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

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

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

5 голосов
/ 22 декабря 2011

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

3 голосов
/ 22 декабря 2011

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

2 голосов
/ 02 февраля 2017
  1. Программа будет ожидать окончания печати. Регистраторы используют очередь сообщений и пишут только в том случае, если нет других выходных данных.
  2. System.out.println (SOP) не являются потокобезопасными (т.е. асинхронными) Регистраторы являются потокобезопасными (т.е. синхронными)
  3. Регистраторы легко настраиваются a. Форматирование, ограничение содержимого журнала, достижимое регистраторами b. Регистрация нескольких получателей - файл, консоль, БД
  4. СОП записывают журналы в файлы журналов Сервера. Мы должны хранить журналы приложений отдельно от журналов сервера, так как это может привести к отказу сервера
  5. Серверные приложения, которым удается обрабатывать 1700 транзакций в секунду, уменьшаются до 800 при вставке одиночных SOP с фиксированной строкой в ​​каждом
2 голосов
/ 22 декабря 2011

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

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

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

1 голос
/ 30 апреля 2016

Еще одна причина в том, что System.out и err являются PrintStreams, которые используют все лежащие в основе исключения IOException.Смотрите следующие методы PrintStreams:

<code>/**
 * 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();
 * 
* или эквивалентный.* * @return true тогда и только тогда, когда в этом потоке обнаружен * IOException, отличный от * InterruptedIOException, или был вызван метод * setError * / public boolean checkError () {if (out! =null) flush ();if (out instanceof java.io.PrintStream) {PrintStream ps = (PrintStream) out;return ps.checkError ();} вернуть неприятности;}

Таким образом, IOException из базового потока используется ВСЕГДА, и обычно люди никогда не вызывают checkError в System out, поэтому они даже не знают, что что-то случилось.

1 голос
/ 22 декабря 2011

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...