2016-07-11 7 views
0

Ich bekomme CME, wenn ich Apache-Benchmark 200000 Anfrage mit 1000 concurent Client senden, aber wenn diese Werte niedrig bleiben, funktioniert es gut. Unten ist Stack-Trace:ConcurrentModificationException in log4j2 ParameterFormatter.appendCollection, wenn ich die Last auf Tomcat erhöhen

2016-07-11 21:02:26,829 http-bio-8080-exec-284 ERROR An exception occurred processing Appender debug-log java.util.ConcurrentModificationException 
at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:901) 
at java.util.ArrayList$Itr.next(ArrayList.java:851) 
at org.apache.logging.log4j.message.ParameterFormatter.appendCollection(ParameterFormatter.java:575) 
at org.apache.logging.log4j.message.ParameterFormatter.appendPotentiallyRecursiveValue(ParameterFormatter.java:483) 
at org.apache.logging.log4j.message.ParameterFormatter.recursiveDeepToString(ParameterFormatter.java:429) 
at org.apache.logging.log4j.message.ParameterFormatter.formatMessage2(ParameterFormatter.java:189) 
at org.apache.logging.log4j.message.ParameterizedMessage.formatTo(ParameterizedMessage.java:217) 
at org.apache.logging.log4j.core.pattern.MessagePatternConverter.format(MessagePatternConverter.java:65) 
at org.apache.logging.log4j.core.pattern.PatternFormatter.format(PatternFormatter.java:38) 
at org.apache.logging.log4j.core.layout.PatternLayout$PatternSerializer.toSerializable(PatternLayout.java:288) 
at org.apache.logging.log4j.core.layout.PatternLayout.toText(PatternLayout.java:194) 
at org.apache.logging.log4j.core.layout.PatternLayout.encode(PatternLayout.java:180) 
at org.apache.logging.log4j.core.layout.PatternLayout.encode(PatternLayout.java:57) 
at org.apache.logging.log4j.core.appender.AbstractOutputStreamAppender.directEncodeEvent(AbstractOutputStreamAppender.java:120) 
at org.apache.logging.log4j.core.appender.AbstractOutputStreamAppender.tryAppend(AbstractOutputStreamAppender.java:113) 
at org.apache.logging.log4j.core.appender.AbstractOutputStreamAppender.append(AbstractOutputStreamAppender.java:104) 
at org.apache.logging.log4j.core.appender.RollingFileAppender.append(RollingFileAppender.java:86) 
at org.apache.logging.log4j.core.config.AppenderControl.tryCallAppender(AppenderControl.java:155) 
at org.apache.logging.log4j.core.config.AppenderControl.callAppender0(AppenderControl.java:128) 
at org.apache.logging.log4j.core.config.AppenderControl.callAppenderPreventRecursion(AppenderControl.java:119) 
at org.apache.logging.log4j.core.config.AppenderControl.callAppender(AppenderControl.java:84) 
at org.apache.logging.log4j.core.config.LoggerConfig.callAppenders(LoggerConfig.java:390) 
at org.apache.logging.log4j.core.config.LoggerConfig.processLogEvent(LoggerConfig.java:375) 
at org.apache.logging.log4j.core.config.LoggerConfig.log(LoggerConfig.java:359) 
at org.apache.logging.log4j.core.config.LoggerConfig.log(LoggerConfig.java:349) 
at org.apache.logging.log4j.core.config.AwaitCompletionReliabilityStrategy.log(AwaitCompletionReliabilityStrategy.java:63) 
at org.apache.logging.log4j.core.Logger.logMessage(Logger.java:146) 
at org.apache.logging.log4j.spi.AbstractLogger.logMessage(AbstractLogger.java:2025) 
at org.apache.logging.log4j.spi.AbstractLogger.logIfEnabled(AbstractLogger.java:1898) 
at org.apache.logging.slf4j.Log4jLogger.debug(Log4jLogger.java:129) 

Edit: ich verwende log4j2 2.6

+0

Welche Version von Log4j verwenden Sie? Es entspricht nicht der neuesten Version, daher wäre es hilfreich, wenn Sie das ausprobieren könnten. Für was es wert ist, bin ich nicht wirklich sicher, warum Ihre Frage abgelehnt wurde. – rgoers

+0

Einverstanden, dass der Downvote keinen Sinn ergibt. Upvoted zurück auf Null. :-) –

Antwort

1

Es scheint, dass Sie eine Sammlung protokollieren, die so modifiziert wird, während die Log4j 2 ParameterFormatter über seine Elemente iteriert eine Textdarstellung zu erstellen.

Vom Stacktrace ist Log4j 2 für die synchrone Protokollierung konfiguriert, sodass die Collection möglicherweise von einem anderen Thread als dem Anwendungsthread geändert wird, der protokolliert wird.

Eine weitere Sache bei der synchronen Protokollierung ist, dass Ihre Benchmark-Ergebnisse einfach die Kosten der Festplatten-I/O widerspiegeln, oder, wenn Ihr Benchmark Multithread ist, die Kosten für Sperrenkonflikte im Log4j 2-Appender. Dies könnte die dominierenden Kosten sein. Wenn das was du messen willst dann toll. Ansonsten würde ich sehr empfehlen, Log4j 2's zu verwenden. Die einfachste Möglichkeit, Async-Logger zu verwenden, besteht darin, eine einzelne Systemeigenschaft festzulegen: Log4jContextSelector auf org.apache.logging.log4j.core.async.AsyncLoggerContextSelector.

+0

In async Logger, da es Snapshot macht, ist Snapshot wie eine Art defensive Kopie. Wenn ja, wird es mehr off aktivieren gc? – Shashank

+0

Asynchrone Protokollierer können keine defensive Kopie der Parameterobjekte erstellen. Stattdessen wird die Nachricht im Text gerendert, bevor sie an den Hintergrundthread übergeben wird. Seit 2.6 versucht Log4j, müllfrei zu sein, aber das Aufrufen von ArrayList.toString() erzeugt temporäre Objekte. (Dies gilt sowohl für die synchrone als auch die asynchrone Protokollierung.) –

+0

Vom Standpunkt des GC aus gesehen sind asynchrone Protokollierung und synchrone Protokollierung ziemlich identisch. Der Unterschied besteht darin, dass Async-Protokollierer Sperrkonflikte und E/A im Anwendungsthread vermeiden. Hierin liegen die Leistungsvorteile. –