log4j2RollingRandomAccessFile配置过程
log4j2 RollingRandomAccessFile配置
⼀、需求背景
1. ⽇志按⼩时压缩成zip⽂件。
2. 仅保存距离当前时间最近24⼩时的历史压缩⽂件。
3. 压缩封存的zip⽂件,按照零点为参考点纠偏。
4. 将adway.acceptor.base.DebugUtils类的⽇志输出到指定⽂件,且不再输出到其他⽂件。
⼆、log4j2 配置实现
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="INFO" monitorInterval="120">
<properties>
<property name="MSG_LOG_HOME">/data/gpslog</property>
</properties>
<Appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="%d [%t] %-5p [%c] - %m%n" />
</Console>
<RollingRandomAccessFile name="msgAppender" immediateFlush="true"
fileName="${MSG_LOG_HOME}/msg.log"
filePattern="${MSG_LOG_HOME}/backup/msg.%d{yyyyMMddHH}.zip">
<Filters>
<ThresholdFilter level="INFO" onMatch="ACCEPT" onMismatch="DENY"/>
</Filters>
<PatternLayout pattern="%m%n" />
<Policies>
<TimeBasedTriggeringPolicy interval="1" modulate="true"/>
</Policies>
<DefaultRolloverStrategy max="24">
<Delete basePath="${MSG_LOG_HOME}" maxDepth="2">
<IfFileName glob="*/msg.*.zip" />
<IfLastModified age="24H" />
</Delete>
</DefaultRolloverStrategy>
</RollingRandomAccessFile>
</Appenders>
<Loggers>
<AsyncLogger name="adway.DebugUtils" additivity="FALSE" level="INFO">
<appender-ref ref="msgAppender" />
</AsyncLogger>
</Loggers>
</Configuration>
三、配置说明
1. monitorInterval,博客配置的为120,单位为秒。即在服务运⾏过程中发⽣了log4j2配置⽂件的修改,log4j2能够在monitorInterval时间范围重新加载配置,⽆需重启应⽤。
2. property配置⽂件全局属性的声明,使⽤⽅式为:${声明的属性名称}。
${sys:catalina.home}为tomcat部署路径,例如:/data/tomcat。
3. RollingRandomAccessFile基本属性
name:Appender名称
immediateFlush:log4j2接收到⽇志事件时,是否⽴即将⽇志刷到磁盘。默认为true。
fileName:⽇志存储路径
filePattern:历史⽇志封存路径。其中%d{yyyyMMddHH}表⽰了封存历史⽇志的时间单位(⽬前单位为⼩时,yyyy表⽰年,MM表⽰⽉,dd表⽰天,HH表⽰⼩时,mm表⽰分钟,ss表⽰秒,SS表⽰毫秒)。注意后缀,log4j2⾃动识别zip等后缀,表⽰历史⽇志需要压缩。
4. TimeBasedTriggeringPolicy
interval:表⽰历史⽇志封存间隔时间,单位为filePattern设置的单位值
modulate:表⽰是否历史⽇志⽣成时间纠偏,纠偏以零点为基准进⾏。⽐如:15:16⽣成了msg.2017041715.zip⽂件,那么纠偏后会在16:00⽣成msg.2017041716.zip
5. ThresholdFilter
level,表⽰最低接受的⽇志级别,博客配置的为INFO,即我们期望打印INFO级别以上的⽇志。
onMatch,表⽰当⽇志事件的⽇志级别与level⼀致时,应怎么做。⼀般为ACCEPT,表⽰接受。
onMismatch,表⽰⽇志事件的⽇志级别与level不⼀致时,应怎么做。⼀般为DENY,表⽰拒绝。也可以为NEUTRAL表⽰中⽴。
6. 保存24⼩时历史⽇志,但不想⽤⽂件索引
<DefaultRolloverStrategy max="24">
<Delete basePath="${MSG_LOG_HOME}" maxDepth="2">
<IfFileName glob="*/msg.*.zip" />
<IfLastModified age="24H" />
</Delete>
</DefaultRolloverStrategy>
备注:
1. age的单位:D、H、M、S,分别表⽰天、⼩时、分钟、秒
2. basePath表⽰⽇志存储的基⽬录,maxDepth=“1”表⽰当前⽬录。因为我们封存的历史⽇志在basePath⾥⾯的backup⽬录,所以maxDepth设置为2。
log4j2 delete7. RollingRandomAccessFile设置bufferSize不⽣效问题
a. log4j2配置如下:
<RollingRandomAccessFile name="msgAppender"
immediateFlush="false"
bufferSize="512"
fileName="${MSG_LOG_HOME}/msg.log"
filePattern="${MSG_LOG_HOME}/backup/msg.%d{yyyyMMddHH}.zip">
......
b. 使⽤异步Logger⽅式输出⽇志
......
<AsyncLogger name="adway.DebugUtils" additivity="FALSE" level="INFO">
<appender-ref ref="msgAppender" />
</AsyncLogger>
......
c. 验证
经过反复测试验证,⽇志始终实时刷新到磁盘,这是为什么?查看log4j2⽂档发现:
Asynchronous loggers and appenders will automatically flush at the end of a batch of events, even if
immediateFlush is set to false. This also guarantees the data is written to disk but is more efficient.
因此,如果期望使⽤ RollingRandomAccessFile异步的⽅式打印输出⽇志,bufferSize是⽆法⽣效的且也没有必要采⽤buffer 的⽅式。
请参考
RandomAccessFile的常见⽤法
1.RandomAccessFile的简介
1.1为什么要⽤到RandomAccessFile
我们平常创建流对象关联⽂件,开始读⽂件或者写⽂件都是从头开始的,不能从中间开始,如果是开多线程下载⼀个⽂件我们之前学过的FileWriter或者FileReader等等都⽆法完成,⽽当前介绍的RandomAccessFile他就可以解决这个问题,因为它可以指定位置读,指定位置写的⼀个类,通常开发过程中,多⽤于多线程下载⼀个⼤⽂件.
1.2.常⽤⽅法简介
构造⽅法:RandomAccessFile raf = newRandomAccessFile(File file, String mode);
其中参数 mode 的值可选 "r":可读,"w" :可写,"rw":可读性;
成员⽅法:
seek(int index);可以将指针移动到某个位置开始读写;
setLength(long len);给写⼊⽂件预留空间:
2.RandomAccessFile的特点和优势
这个对象有两个优点
1.既可以读也可以写
RandomAccessFile不属于InputStream和OutputStream类系的它是⼀个完全独⽴的类,所有⽅法(绝⼤多数都只属于它⾃⼰)都是⾃⼰从头开始规定的,这⾥⾯包含读写两种操作
2.可以指定位置读写
RandomAccessFile能在⽂件⾥⾯前后移动,在⽂件⾥移动⽤的seek( ),所以它的⾏为与其它的I/O类有些根本性的不同。总⽽⾔之,它是⼀个直接继承Object的,独⽴的类。只有RandomAccessFile才有seek搜寻⽅法,⽽这个⽅法也只适⽤于⽂件. 3.通过案例来熟悉RandomAccessFile的最常⽤的操作
⾸先创建⼀个DownLoadThread的类继承Thread
public class DownLoadThread extends Thread {
private long start;
private File src;
private long total;
private File desc;
/**
*
* @param start
*            开始下载的位置
* @param src
*            要下载的⽂件
* @param desc
*            要下载的⽬的地
* @param total
*            要下载的总量
*/
public DownLoadThread(long start, File src, File desc, long total) {
this.start = start;
this.src = src;
this.desc = desc;
}
@Override
public void run() {
try {
// 创建输⼊流关联源,因为要指定位置读和写,所以我们需要⽤随机访问流
RandomAccessFile src = new RandomAccessFile(this.src, "rw");
RandomAccessFile desc = new RandomAccessFile(this.desc, "rw");
// 源和⽬的都要从start开始
src.seek(start);
desc.seek(start);
// 开始读写
byte[] arr = new byte[1024];
int len;
long count = 0;
while ((len = ad(arr)) != -1) {
//分三种情况
if (len + count > total) {
//1.当读取的时候操作⾃⼰该线程的下载总量的时候,需要改变len
len = (int) (total - count);
desc.write(arr, 0, len);
//证明该线程下载任务已经完毕,结束读写操作
break;
} else if (len + count < total) {
/
/2.证明还没有到下载总量,直接将内容写⼊
desc.write(arr, 0, len);
//并且使计数器任务累加
count += arr.length;
} else {
//3.证明改好到下载总量
desc.write(arr, 0, len);
//结束读写
break;
}
}
src.close();
desc.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
然后定义主⽅法进⾏⽂件的测试
public class TestRandomAccess {
public static void main(String[] args) {
//关联源
File src = new File("a.txt");
//关联⽬的
File desc = new File("b.txt");
//获取源的总⼤⼩
long length = src.length();
// 开两条线程,并分配下载任务
new DownLoadThread(0, src, desc, length / 2).start();
new DownLoadThread(length / 2 , src, desc, length - (length / 2)).start();    }
}
4.效果展⽰
<的内容
<的内容
5.总结
从以上分析可以看出RandomAccessFile最⼤两个特点:
1.可以指定位置开始操作
2.既可以读,也可以写
所以,我们但凡遇到不是需要从⽂件中中间部分开始读取的时候,可以使⽤RandomAccessFile这个类,⽐如:多线程下载是最常⽤的应该场景
以上为个⼈经验,希望能给⼤家⼀个参考,也希望⼤家多多⽀持。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。