日志采集异常,生产报错误日志:
(org.apache.flume.source.SpoolDirectorySource$SpoolDirectoryRunnable.run:280) - FATA
L: Spool Directory source spool_source: { spoolDir: /apps/logs/libra }: Uncaught exception in SpoolDirectorySource thread. Restart or
reconfigure Flume to continue processing.
java.lang.IllegalStateException: File has been modified since being read: /apps/logs/libra/financial-webapp/spool/libra.2018-03-09_09-
10-16.tmp
看提示应该是flume读文件时,该文件正被其他进程修改。
查阅资料有人因为大日志文件导致该问题(http://www.bubuko.com/infodetail-508764.html),仔细分析flume的源码,发现应该不是这个原因。
因为我们的文件很小。
后来发现是因为两个系统用了用一个日志目录,日志文件的格式均为年月日时分秒,如果同一秒两个系统都写文件,一个系统写完,flume去获取发现已经写完,这时候另一个系统又去写,这时flume会和写进程冲突。
解决办法就是两个系统分写两个目录,或者文件名区分开同一秒的两个文件。
另外针对大文件,flume的解决方案可以设置一个文件完成后缀:
SPOOLED_FILE_SUFFIX
以下摘自flume 1.7源码,可以看到,当后缀匹配是才会取。大文件可以在写完时修改后缀,可以避免大文件问题。
public FileVisitResult visitFile(Path candidate, BasicFileAttributes attrs)
throws IOException {
String fileName = candidate.getFileName().toString();
if (!fileName.endsWith(completedSuffix) &&
!fileName.startsWith(".") &&
includePattern.matcher(fileName).matches() &&
!ignorePattern.matcher(fileName).matches()) {
candidateFiles.add(candidate.toFile());
}
其中
completedSuffix = context.getString(SPOOLED_FILE_SUFFIX,
DEFAULT_SPOOLED_FILE_SUFFIX);