Log4j性能调优

不久前在系统中完成了监控的功能,监控系统的信息量很大,用户对页面的每一个点击都会产生记录,每天下来的日志量有2G多,我用log4j把这些监控记录放在日志里,然后进行异步处理,但即使是这样,记录日志会对磁盘IO产生频繁的访问,而IO通常就是系统的瓶颈所在。于是对log4j配置进行一些调优就成了必要。下面是我系统中的log4j配置: 
log4j.rootLogger=ERROR,fileout,stdout 
log4j.logger.monitorLogger=INFO,monitorAppender 
log4j.additivity.monitorLogger=false 

log4j.appender.stdout=org.apache.log4j.ConsoleAppender 
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout 
log4j.appender.stdout.layout.ConversionPattern=%d (%F:%L) %-5p %c - %m%n 

log4j.appender.fileout=org.apache.log4j.DailyRollingFileAppender 
log4j.appender.fileout.File=logs/server_log.txt 
log4j.appender.fileout.layout=org.apache.log4j.PatternLayout 
log4j.appender.fileout.layout.ConversionPattern=%d [%t] (%F:%L) %-5p %c - %m%n 

log4j.appender.monitorAppender=org.apache.log4j.DailyRollingFileAppender 
log4j.appender.monitorAppender.File=mtlogs/mt_log.txt 
log4j.appender.monitorAppender.layout=org.apache.log4j.PatternLayout 
log4j.appender.monitorAppender.layout.ConversionPattern=%m%n 
log4j.appender.monitorAppender.DatePattern='.'yyyy-MM-dd-HH 
log4j.appender.monitorAppender.BufferedIO=true 
#Buffer单位为字节,默认是8K 
log4j.appender.monitorAppender.BufferSize=8192 

1)log4j.additivity.monitorLogger=false 
这个选项用于控制监控logger的日志不会输出到rootlogger,否则无论会产生许多重复的数据,同时也会影响性能; 

2)log4j.appender.monitorAppender.DatePattern='.'yyyy-MM-dd-HH 
这个选项用于告诉DailyRollingFileAppender每小时输出日志,而不是默认的一天输出一次,因为监控日志的数据量很巨大,如果以天为单位输出,日志文件会很大(G级),而且再处理会很耗时。 
其他一些输出选项还有: 
1)'.'yyyy-MM: 每月 
2)'.'yyyy-ww: 每周 
3)'.'yyyy-MM-dd: 每天 
4)'.'yyyy-MM-dd-a: 每天两次 
5)'.'yyyy-MM-dd-HH: 每小时 
6)'.'yyyy-MM-dd-HH-mm: 每分钟 

3)log4j.appender.monitorAppender.BufferedIO=true 
log4j.appender.monitorAppender.BufferSize=8192 
这个选项用于告诉log4j输出日志的时候采用缓冲的方式,而不是即时flush方式,并且设定了缓冲为8K,8K是默认值,可以根据日志输出的情况来修改。这个选项很重要,在测试中发现,当并发访问很高,例如每一秒100个并发以上,使用缓存跟不使用缓冲差距很大。具体数字我这里就不列出来了。 
另外我想说的是,log4j输出缓冲日志是以8K为单位的,因为磁盘的一个block为8K,这样可以减少碎片,也就是说假设你设置缓存为18K,log4j在16K(8K*2)的时候就会输出),而不是18K。 

4)组装输出内容之前可对logger的输出级别先进行判断而不要完全依赖log4j控制,因为组装输出日志内容也是要损耗效率的。 
        //若log4j并未开启info级日志记录,直接返回 
        if(!monitorLogger.isInfoEnabled()){ 
            return; 
        } 
        StringBuilder log = new StringBuilder(); 
        logSql.append(logPk+" "); 
        ... 

5)使用异步输出 org.apache.log4j.AsyncAppender,异步输出必须使用xml方式配置才能支持,我把上面properties形式的配置文件用xml表达一下: 
<?xml version="1.0" encoding="UTF-8"?> 
<log4j:configuration debug="true"> 

    <appender name="stdout" 
        class="org.apache.log4j.ConsoleAppender"> 
        <layout class="org.apache.log4j.PatternLayout"> 
            <param name="ConversionPattern" value="%d (%F:%L) %-5p %c - %m%n" /> 
        </layout> 
    </appender> 

    <appender name="fileout" 
        class="org.apache.log4j.DailyRollingFileAppender"> 
        <layout class="org.apache.log4j.PatternLayout"> 
            <param name="ConversionPattern" value="%d [%t] (%F:%L) %-5p %c - %m%n" /> 
        </layout> 
        <param name="File" 
            value="logs/server_log.txt" /> 
    </appender> 

    <appender name="monitorAppender" 
        class="org.apache.log4j.DailyRollingFileAppender"> 
        <layout class="org.apache.log4j.PatternLayout"> 
            <param name="ConversionPattern" value="%m%n" /> 
        </layout> 
        <param name="DatePattern" value="'.'yyyy-MM-dd-HH" />        
        <param name="File" value="mtlogs/mt_log.txt" /> 
        <param name="BufferedIO" value="true" /> 
        <!-- 8K为一个写单元 --> 
        <param name="BufferSize" value="8192" /> 
    </appender> 

    <appender name="async" class="org.apache.log4j.AsyncAppender"> 
        <appender-ref ref="monitorAppender"/> 
    </appender> 
    
    <root> 
        <priority value="error" /> 
        <appender-ref ref="stdout" /> 
        <appender-ref ref="fileout" /> 
    </root> 
    
    <category name="com.danga.MemCached"> 
        <priority value="error" /> 
        <appender-ref ref="fileout" /> 
    </category > 
    
    <category name="com.opensymphony"> 
        <priority value="error" /> 
        <appender-ref ref="fileout" /> 
    </category > 
    
    <category name="monitorLogger" additivity="false"> 
        <priority value="info" /> 
        <appender-ref ref="async" /> 
    </category > 
</log4j:configuration> 


配置中红色的部分就是用于支持异步输出的,在用jmeter测试的过程中发觉使用异步方式,工作的不是很稳定。性能的提升也不显著。所以最后并没有采用。 

6)log4j配置文件的加载: 
         InputStream in=null; 
        try { 
             in = Log4jConfigLocator.class.getResourceAsStream(fileName); 
             if(fileName.endsWith(".xml")){ 
                 //载入XML格式的配置文件 
                 Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(in); 
                 DOMConfigurator.configure(doc.getDocumentElement()); 
             }else{ 
                 //载入properties格式的配置文件 
                 Properties props = new Properties(); 
                 props.load(in); 
                 PropertyConfigurator.configure(props); 
             } 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值