使用apache log解決高併發下log4j引起大量線程block問題

由於項目用戶量比較大,測試同事採用兩百併發進行測試,在測試查過程中,查看jvm 虛擬機發現很多日誌線程出現BLOCKED,

結果如下:

"http-saoma%2F192.168.6.162-8097-184" daemon prio=10 tid=0x00002aaab0ecc800 nid=0x2d7a waiting for monitor entry [0x0000000045fa9000]
   java.lang.Thread.State: BLOCKED (on object monitor)
	at org.apache.log4j.Category.callAppenders(Category.java:204)
	- waiting to lock <0x00000007800020a0> (a org.apache.log4j.spi.RootLogger)
	at org.apache.log4j.Category.forcedLog(Category.java:391)
	at org.apache.log4j.Category.log(Category.java:856)
	at org.slf4j.impl.Log4jLoggerAdapter.info(Log4jLoggerAdapter.java:304)

通過日誌結果可以看出問題是出在org.apache.log4j.Category.callAppenders方法中,下面是該方法的代碼:

/**
     Call the appenders in the hierrachy starting at
     <code>this</code>.  If no appenders could be found, emit a
     warning.

     <p>This method calls all the appenders inherited from the
     hierarchy circumventing any evaluation of whether to log or not
     to log the particular log request.

     @param event the event to log.  
*/
  public void callAppenders(LoggingEvent event) {
    int writes = 0;

    for(Category c = this; c != null; c=c.parent) {
      // Protected against simultaneous call to addAppender, removeAppender,...
      synchronized(c) {
	if(c.aai != null) {
	  writes += c.aai.appendLoopOnAppenders(event);
	}
	if(!c.additive) {
	  break;
	}
      }
    }

    if(writes == 0) {
      repository.emitNoAppenderWarning(this);
    }
  }

我們從上面可以看出在該方法中有個synchronized同步鎖,同步鎖就會導致線程競爭,那麼在大併發情況下將會出現性能問題,同會引
起線程BLOCKED問題。

那怎樣解決這個問題呢?

我們可以使用Apache log 解決這個問題,代碼如下:

private static final Log log = LogFactory.getLog("xxx");  


通過測試發現,以前org.apache.log4j.Category.callAppenders線程BLOCKED問題沒有了。大家以後遇到這個問題可以採取這個方式解決。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章