序
本文主要研究一下rocketmq的RollingFileAppender
RollingFileAppender
org/apache/rocketmq/logging/inner/LoggingBuilder.java
public static class RollingFileAppender extends FileAppender {
protected long maxFileSize = 10 * 1024 * 1024;
protected int maxBackupIndex = 1;
private long nextRollover = 0;
public RollingFileAppender() {
super();
}
public int getMaxBackupIndex() {
return maxBackupIndex;
}
public long getMaximumFileSize() {
return maxFileSize;
}
//......
public synchronized void setFile(String fileName, boolean append, boolean bufferedIO, int bufferSize)
throws IOException {
super.setFile(fileName, append, this.bufferedIO, this.bufferSize);
if (append) {
File f = new File(fileName);
((CountingQuietWriter) qw).setCount(f.length());
}
}
public void setMaxBackupIndex(int maxBackups) {
this.maxBackupIndex = maxBackups;
}
public void setMaximumFileSize(long maxFileSize) {
this.maxFileSize = maxFileSize;
}
protected void setQWForFiles(Writer writer) {
this.qw = new CountingQuietWriter(writer, this);
}
protected void subAppend(LoggingEvent event) {
super.subAppend(event);
if (fileName != null && qw != null) {
long size = ((CountingQuietWriter) qw).getCount();
if (size >= maxFileSize && size >= nextRollover) {
rollOver();
}
}
}
protected class CountingQuietWriter extends QuietWriter {
protected long count;
public CountingQuietWriter(Writer writer, Appender appender) {
super(writer, appender);
}
public void write(String string) {
try {
out.write(string);
count += string.length();
} catch (IOException e) {
appender.handleError("Write failure.", e, Appender.CODE_WRITE_FAILURE);
}
}
public long getCount() {
return count;
}
public void setCount(long count) {
this.count = count;
}
}
}
- 这里重写了subAppend方法,调用父类subAppend方法之后,判断是否需要rollOver
- 这里定义了maxFileSize,即单个文件的大小,然后还定义了nextRollover索引
- 这里使用的是CountingQuietWriter,里头有个count来累积计算字符串的长度
RollingFileAppender.rollOver
org/apache/rocketmq/logging/inner/LoggingBuilder.java
public void rollOver() {
File target;
File file;
if (qw != null) {
long size = ((CountingQuietWriter) qw).getCount();
SysLogger.debug("rolling over count=" + size);
nextRollover = size + maxFileSize;
}
SysLogger.debug("maxBackupIndex=" + maxBackupIndex);
boolean renameSucceeded = true;
if (maxBackupIndex > 0) {
file = new File(fileName + '.' + maxBackupIndex);
if (file.exists()) {
renameSucceeded = file.delete();
}
for (int i = maxBackupIndex - 1; i >= 1 && renameSucceeded; i--) {
file = new File(fileName + "." + i);
if (file.exists()) {
target = new File(fileName + '.' + (i + 1));
SysLogger.debug("Renaming file " + file + " to " + target);
renameSucceeded = file.renameTo(target);
}
}
if (renameSucceeded) {
target = new File(fileName + "." + 1);
this.closeFile(); // keep windows happy.
file = new File(fileName);
SysLogger.debug("Renaming file " + file + " to " + target);
renameSucceeded = file.renameTo(target);
if (!renameSucceeded) {
try {
this.setFile(fileName, true, bufferedIO, bufferSize);
} catch (IOException e) {
if (e instanceof InterruptedIOException) {
Thread.currentThread().interrupt();
}
SysLogger.error("setFile(" + fileName + ", true) call failed.", e);
}
}
}
}
if (renameSucceeded) {
try {
this.setFile(fileName, false, bufferedIO, bufferSize);
nextRollover = 0;
} catch (IOException e) {
if (e instanceof InterruptedIOException) {
Thread.currentThread().interrupt();
}
SysLogger.error("setFile(" + fileName + ", false) call failed.", e);
}
}
}
- 这个方法首先更新nextRollover的值,然后根据maxBackupIndex来递增重命名文件,然后再把现有的文件重名为为.1后缀
- 重命名成功之后,再对新的文件进行setFile相关设置,关联writer,写入header
小结
RollingFileAppender在每次append的时候,都会先append数据,然后再判断是否超出文件大小限制,超出了再执行rollOver操作,对既有文件进行重命名,然后重新生成新的文件。注意这里没有进行同步操作,因此需要最外层调用的方法有同步并发控制。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。