flume在监控文件的时候,一旦有新文件产生就会直接采集传输,对于一般的小文件直接copy进flume监控的文件夹内是没有问题的,但是一旦文件太大,flume就会先把进来的部分文件给采集了,并打上标签,再次轮训监控文件中的变化文件时,发现拷贝万的文件在之前已经被采集了,就会抛出异常。
网上的解决办法1(修改源码):摘自骑小象去远方的文章https://www.cnblogs.com/pingjie/p/4146727.html
修改源码:ReliableSpoolingFileEventReader类的源码,追加一个判断,当进来的文件导入完成以后才开始进行采集。
将checkFileCpIsOver方法添加到
getNextFile()方法中。
private void checkFileCpIsOver(File file) { long modified = file.lastModified();//目前文件的修改时间 long length = file.length();//目前文件的大小 try { Thread.sleep(1000);//等待1秒钟 } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } File currentFile = new File(file.getAbsolutePath()); int count = 0;//记录循环次数,超过20次,也就是10秒后抛出异常 while(currentFile.lastModified() != modified || currentFile.length() != length) { if(count > 20) { String message = "File Copy time too long. please check copy whether exception!" + "\n" + "File at :" + file.getAbsolutePath() + "\n" + "File current length is:" + currentFile.lastModified(); new IllegalStateException(message); } count++; modified = currentFile.lastModified(); length = currentFile.length(); try { Thread.sleep(500);//等待500毫秒 } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } currentFile = new File(file.getAbsolutePath()); } //一直到文件传输完成就可以退出 }
方法二:摘自overstackflow中,添加一个临时目录,再使用mv指令
创建一个临时目录,将生成的日志文件放入临时目录,然后再用mv指令将临时目录中的文件移动至flume监控的目录下,这样既不会修改源文件,也可以防止copy延迟问题导致flume读取异常。
个人推荐使用方法二可行。
另外在监控中可能还会出现的问题:charset.MalformedInputException: Input length = 1或2
这个都是由于编码的问题或者特殊的字符集,所有再文件的生成时尽量去除特殊字符集,然后文件的格式设置成utf-8(注意不是utf-8无BOM哦)。也可以在采集器的配置文件中设置输入文件的指定编码:
#flume的默认编码为utf-8
agent1.sources.sc1.inputCharset=utf-8