【原】小心log4j的多进程写入
问题发现:项目使用log4j日志。公司使用的模式是log4j-wget下载日志-awk处理日志-入mysql
最近统计发现统计数据比日志严重少。而脚本数据库同步到测试机上,再执行竟然没错误。
后来才发现日志写入时间出错。比如x.2009-08-13-00日志理论应该是在14点时就切出来了,也就是写入完毕。但是它的最后写入时间竟然是14点多。
tail一下日志,更神奇的,发现x.2009-08-13-00的日志中的日志全是14点的。竟然被重写了。
问题归纳:log4j采用如下机制切文件:新来一个写入请求是在系统时间的新的一个小时里,比如14点来了一个请求,而之前一直是13点的请求。那么就切日志 x.2009-08-12-00
怀疑过系统时间。因为linux下作了系统时间同步的脚本。但是很快排除了这个问题。
考虑多进程的问题。因为多个页面pv日志都要记录到同一个日志中。因此action要调用同一个service类处理。但是在service上加了同步synchronized仍旧无果。
我的调用结构是这样的。
action1--调用service---调用log4j写入静态方法类logger 其中这个logger中形如:
public static void log(ShopPageLoggerBean bean) {
StringBuffer contents=new StringBuffer();
contents.append(sdf.format(bean.getDate()));
contents.append(SPLIT_STR);
logger.info(contents);}
分析:通过google知道log4j有自己的锁文件的功能。再看我的程序public static void log(ShopPageLoggerBean bean)其实根本就没起到了同步的功能。
因为是静态方法,因此上层(service)加synchronize根本没起作用。后来在logger中加同步后成功~!
public static synchronized void log(ShopPageLoggerBean bean) {
StringBuffer contents=new StringBuffer();
contents.append(sdf.format(bean.getDate()));
contents.append(SPLIT_STR);
logger.info(contents);}
结论: 处理log4j多进程处理时,一定要在写日志的地方进行同步处理。
最近统计发现统计数据比日志严重少。而脚本数据库同步到测试机上,再执行竟然没错误。
后来才发现日志写入时间出错。比如x.2009-08-13-00日志理论应该是在14点时就切出来了,也就是写入完毕。但是它的最后写入时间竟然是14点多。
tail一下日志,更神奇的,发现x.2009-08-13-00的日志中的日志全是14点的。竟然被重写了。
问题归纳:log4j采用如下机制切文件:新来一个写入请求是在系统时间的新的一个小时里,比如14点来了一个请求,而之前一直是13点的请求。那么就切日志 x.2009-08-12-00
怀疑过系统时间。因为linux下作了系统时间同步的脚本。但是很快排除了这个问题。
考虑多进程的问题。因为多个页面pv日志都要记录到同一个日志中。因此action要调用同一个service类处理。但是在service上加了同步synchronized仍旧无果。
我的调用结构是这样的。
action1--调用service---调用log4j写入静态方法类logger 其中这个logger中形如:
public static void log(ShopPageLoggerBean bean) {
StringBuffer contents=new StringBuffer();
contents.append(sdf.format(bean.getDate()));
contents.append(SPLIT_STR);
logger.info(contents);}
分析:通过google知道log4j有自己的锁文件的功能。再看我的程序public static void log(ShopPageLoggerBean bean)其实根本就没起到了同步的功能。
因为是静态方法,因此上层(service)加synchronize根本没起作用。后来在logger中加同步后成功~!
public static synchronized void log(ShopPageLoggerBean bean) {
StringBuffer contents=new StringBuffer();
contents.append(sdf.format(bean.getDate()));
contents.append(SPLIT_STR);
logger.info(contents);}
结论: 处理log4j多进程处理时,一定要在写日志的地方进行同步处理。