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

Рекомендации по ведению журналов Java из нескольких потоков?

Я хочу иметь журнал диагностики, который создается несколькими задачами, управляющими данными. Эти задачи могут быть в нескольких потоках. Каждой задаче нужно написать элемент (возможно с подэлементами) в журнал; входите и быстро выходите. Если бы это была ситуация с одной задачей, я бы использовал XMLStreamWriter, поскольку это похоже на лучшее соответствие простоты/функциональности без необходимости удерживать закрашивание XML-документа в память.

Но это не однозадачная ситуация, и я не уверен, как лучше всего убедиться, что это "threadafe" , где "threadafe" в этом приложении означает, что каждый элемент журнала должен быть записан в журнал правильно и последовательно (один за другим и не чередующиеся каким-либо образом).

Любые предложения? У меня есть туманная интуиция, что путь - это использовать очередь элементов журнала (каждый из которых может быть быстро создан: мое приложение занято выполнением реальной работы с учетом производительности) и имеет отдельный поток, который обрабатывает журнал элементы и отправляет их в файл, поэтому ведение журнала не прерывает производителей.

Ведение журнала не обязательно должно быть XML, но я хочу, чтобы оно было структурированным и машиносчитываемым.

edit: Я помещал "threadafe" в кавычки. Log4j кажется очевидным выбором (новым для меня, но старым для сообщества), зачем изобретать колесо...

4b9b3361

Ответ 1

Используйте фреймворк регистрации, например Log4j.

Ответ 2

Я думаю, что вы на неправильном пути. Вы говорите "threadafe", но на самом деле вы подразумеваете "сериализованный". Threadsafe означает, что один поток не будет мешать данным из другой нити. В большинстве случаев проблемы с потоками решаются заранее, и вам не стоит беспокоиться об этом только ради регистрации. Например, если вы пишете:

myVariableSum = 0 + myVariable;
//here comes other thread - Not very likely!
logger.info("Log some INFO; myVariable has value" + myVariable.toString());

Вы должны убедиться, что myVariable не был изменен каким-либо другим потоком с момента вычисления (первая строка), но до вызова метода ведения журнала. Если это произойдет, вы запишете грязное значение, которое не было использовано для выполнения операции, но значение, которое было назначено каким-либо другим потоком. Об этом обычно заботятся; например, локальная (уровень метода) переменная не может быть изменена другим потоком. В любом случае, если вам приходится беспокоиться об этом при регистрации, чем 99%, что ваша программа имеет серьезные проблемы с потоками.

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

Получение следов в журнале, чтобы они происходили, на самом деле обычно называют "сериализацией" вызовов. Сериализация записей в журналах будет серьезным узким местом в любом многопоточном приложении. Если вы используете фреймворк logging, например log4j, следы из всех потоков будут отображаться в одном месте более или менее, чтобы они произошли. Тем не менее, один столбец, как правило, является именем Thread, поэтому вы можете легко фильтровать данные журнала по потоку; каждый поток будет записывать свои данные в хронологическом порядке. Проверьте эту ссылку: http://logging.apache.org/log4j/1.2/faq.html#1.7
Наконец, если сериализация записи журнала - это то, что вам действительно нужно, тогда вы можете использовать какую-то структуру, например java.util.concurrent.BlockingQueue для маршрутизации ваших сообщений.

Ответ 3

Использовать logback-classic. Это новая и лучшая реализация log4j.

Ответ 4

Я предпочитаю использовать SLF4J поверх Log4J. Функциональность параметризованная регистрация особенно привлекательна, если у вас будет много операторов регистрации, которые могут быть отключены в производственной среде.

Он также может работать поверх java.util.logging или использовать собственный простой вывод.

Ответ 5

Используйте фреймворк регистрации, например Log4.

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

Ответ 6

Используйте фреймворк протоколирования, который реализует некоторую форму шаблон NDC, например Log4J.

Ответ 7

Вы можете использовать механизмы синхронизации (например, монитор или семафор), чтобы убедиться, что один запрос журнала обрабатывается до принятия следующего. Все это можно скрыть от кода, вызывающего процедуры ведения журнала.

Ответ 8

log4j является и является стандартом для java-регистрации в течение многих лет. Но если вы не представляете внешнюю зависимость, пакет java.util.logging обеспечивает приемлемое решение.

Ответ 9

У меня была аналогичная проблема и требования к внедрению только для специальных журналов. Мое решение было:

  • Я взял blockinglinkedqueue с размером *2 трафика приложения/мин.

  • Все потоки помещают объект в очередь и завершают задание.

  • Отделить Log-Writer поток, беря головной объект из очереди и записывая его в файл log4j, используя отдельный appender. Это приложение не использовалось для системных журналов.

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

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

Вы также можете использовать aysncappender для log4j.

Ответ 10

Разработка этого в потокобезопасном режиме не является тривиальной задачей, поэтому вы должны действительно использовать существующую среду ведения журнала, которая является потокобезопасной. Наиболее часто используемым является Log4J, который является потокобезопасным (см. FAQ).

Ответ 11

Если вам нужно было, вы могли бы свернуть свое собственное... используя однопользовательский/однострочный FIFO или очереди.