谈一谈Java开发中的坑(一) -- log4j2在SaaS项目中的应用
来源:互联网 发布:java并发教程 编辑:程序博客网 时间:2024/06/16 04:30
背景介绍:
做server端开发有些年头了,特别是开始做SaaS类型的项目时,深知log的重要性,特别是半夜三更用户(大都是美国那边的)遇到问题的电话打过来,这个时候没有一个强大log,那只有抓瞎的份了。以前都是走的微软系的开发工具,log的框架也是别人早就写好的,所以对于log性能这一块也没有什么关注,觉得它就应该是轻量级的,不应该耗费太多的资源。
后来换公司以后,开始学习用java编程了,紧跟着也就是各种开源类项目的引用。这次就跟大家说说,我在log这一块遇到的问题和解决方案。
遇到的问题:
log框架的选型上比较顺利,直接选用了比较常用的log4j2。开发工程中,没有考虑太多,直接采用了常用的同步logger,appender采用的RollingFileAppender。类似如下配置方法:
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="warn" name="MyApp" packages="">
<Appenders>
<RollingFile name="RollingFile" fileName="logs/app.log"
filePattern="logs/$${date:yyyy-MM}/app-%d{MM-dd-yyyy}-%i.log.gz">
<PatternLayout>
<Pattern>%d %p %c{1.} [%t] %m%n</Pattern>
</PatternLayout>
<Policies>
<TimeBasedTriggeringPolicy interval="1" modulate="true" />
<SizeBasedTriggeringPolicy size="250 MB"/>
</Policies>
</RollingFile>
</Appenders>
<Loggers>
<Root level="error">
<AppenderRef ref="RollingFile"/>
</Root>
</Loggers>
</Configuration>
开发工程中一切安好,可是在打压测试时发现,service的响应性能随着线程的增加会变得很差(初期目标8000个用户线程)。后来抓了dump(jstack)发现了好多线程都停留在执行log的方法里。这才开始看看为什么log的性能为什么这么差。
解决方案:
后来上网搜索了一下,发现对于像这种SaaS,log需求量比较大的应用(多线程并发打log),需要采用异步的log输出方式。log4j2对于异步log有很好的支持。这里就把我学到的做一个小的总结。
- 异步log的历史
起初log4j 1.x中引入了async appender,例如在RollingFileAppender中,设置一个属性immediateFlush=false,就可以实现异步log,其后台通过一个ArrayBlockingQueue,来实现log的缓存机制,其I/O操作使用的是BufferedOutputStream。
其后的log4j2中引入了AsyncLogger的概念,其中引用到了LMAX Disprutor的概念,性能明显优化于ArrayBlockingQueue;同时Log4j2还引入了一个新的RandomAccessFileAppender,其使用ByteBuffer + RandomAccessFile的方式,比BufferedOutputStream在性能方面有明显的提升。
- 最终的解决方案
AsyncLogger + RandomAccessFileAppender,示例如下:
<Configuration status="WARN">
<Appenders>
<!-- Async Loggers will auto-flush in batches, so switch off immediateFlush. -->
<RandomAccessFile name="RandomAccessFile" fileName="async.log"
immediateFlush="false" append="false">
<PatternLayout>
<Pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [ThdID=%t] %-level: %m%n</Pattern>
</PatternLayout>
<Policies>
<TimeBasedTriggeringPolicy interval="1" modulate="true" />
</Policies>
</RandomAccessFile>
</Appenders>
<Loggers>
<Root level="info">
<AppenderRef ref="RandomAccessFile"/>
</Root>
</Loggers>
- 一个小建议:
在使用log的方式上,不要采取这样的方式,例如:myLogger.logDebug("aa" + i + " bb" + j),而是要采用myLogger.logDebug("aa {} bb {}", i, j);的方式。这样做的好处,可以把字符串的拼接操作,放在需要输出之前,这样可以在你想要按level控制输出时,减少那些不必要的字符操作,例如:
public void logDebug(String logMsg, Object... params){
if(currentLevel > DEBUG){
// 当决定不输出debug level的数据时,这里没有发生字符串的拼接操作
return;
}
// 在这里做实际的输出
}
以下是几篇非常不错的关于AsyncLogger和LMAX Disprutor的文章,供大家深入的学习:
https://logging.apache.org/log4j/2.x/manual/async.html
https://logging.apache.org/log4j/2.x/manual/appenders.html
https://www.grobmeier.de/log4j-2-performance-close-to-insane-20072013.html
http://lmax-exchange.github.io/disruptor/
1 0
- 谈一谈Java开发中的坑(一) -- log4j2在SaaS项目中的应用
- Log4j2在项目中的应用
- log4j2在web中的应用
- Spring在项目中的应用(一)
- log4j2 在java web中的使用
- 敏捷开发在项目中的应用心得
- 类模板在项目开发中的应用
- MVC模式在j2me项目中的应用(一)
- MVC模式在j2me项目中的应用(一)
- iOS 多线程在项目中的应用场景(一)
- 监听器(Listener)在开发中的应用(一)
- netty在游戏服务器开发中的应用(一)
- 向量在游戏开发中的应用(一)
- Java自定义异常在项目中的应用
- memcached在JAVA项目中的应用
- java线程在项目中的应用场景
- 枚举在java项目中的应用
- 打消中小企业在SaaS应用中的安全顾虑
- DIV设置最小高度
- 看 Facebook 如何以三大法宝化茧成蝶
- 高质量C编程09-位操作
- 基于Flume的美团日志收集系统(二)改进和优化
- CSDN学院“跟着龙哥学JavaWeb”的笔记,请求中文参数的乱码处理
- 谈一谈Java开发中的坑(一) -- log4j2在SaaS项目中的应用
- CodeForces - 673A Bear and Game (模拟)水
- 将View转换为Image保持高清
- windows下安装redis
- PopupWindow的应用以及渐变背景
- 20160513+毕业设计项目需求分析一
- http://www.tuicool.com/articles/vQRnum
- PopUpWindow
- 横向滑动的Recycleview