問題導讀
1.如何理解將FTP上的信令數據匯聚到HDFS上去存儲?
2.使用Spooling Directory Source的時候同時讀寫一個文件會怎樣?
最近在弄一個信令數據匯聚的事情,主要目的是把FTP上的信令數據匯聚到HDFS上去存儲。 邏輯是這樣的:把FTP服務器上的文件下載到一臺主機上,然後SCP到另外一臺主機上的Spooling Directory Source所監控的目錄下面去,sink是hdfs(這裏解釋一下,由於網絡環境的因素,另一臺不能訪問到內網的FTP服務器,所以只能這樣中轉一下)。
嗯,想法不錯,邏輯上看上去也應該沒啥問題,於是就開始吭哧吭哧寫腳本了。FTP上每個信令數據的每個文件的大小差不多都有300M左右。SCP到遠端服務器也沒出現問題,可就是agent老是會掛掉,報這個異常:
-
2014-11-26 12:30:16,942 ERROR org.apache.flume.source.SpoolDirectorySource: FATAL: Spool Directory source source1: { spoolDir: /var/log/apache/flumeSpool }: Uncaught exception in SpoolDirectorySource thread. Restart or reconfigure Flume to continue processing.
-
java.nio.charset.MalformedInputException: Input length = 1
-
at java.nio.charset.CoderResult.throwException(CoderResult.java:277)
-
at org.apache.flume.serialization.ResettableFileInputStream.readChar(ResettableFileInputStream.java:195)
-
at org.apache.flume.serialization.LineDeserializer.readLine(LineDeserializer.java:134)
-
at org.apache.flume.serialization.LineDeserializer.readEvent(LineDeserializer.java:72)
-
at org.apache.flume.serialization.LineDeserializer.readEvents(LineDeserializer.java:91)
-
at org.apache.flume.client.avro.ReliableSpoolingFileEventReader.readEvents(ReliableSpoolingFileEventReader.java:241)
-
at org.apache.flume.source.SpoolDirectorySource$SpoolDirectoryRunnable.run(SpoolDirectorySource.java:224)
-
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)
-
at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:304)
-
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:178)
-
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293)
-
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
-
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
- at java.lang.Thread.run(Thread.java:745)
然後讓我重啓agent纔會把Spooling Directory Source所監控的目錄下面的文件抽取到HDFS上去,感覺很莫名,網上搜索了一下這個錯誤的原因,很多都是說可能傳輸的文件字符集的原因,不以爲然,因爲我反覆測試了一下,如果是字符集的原因,那麼爲什麼我重啓一下agent又可以成功的抽取數據了。
於是我想了想是不是由於同時讀寫導致的問題,因爲我SCP文件過去,文件較大,需要一定的時間,而flume監測到有文件馬上就開始逐行讀取文件轉化成EVENT發送到HDFS上去,這中間肯定存在同時讀寫一個文件了,然後就產生的這個異常問題?
目前僅僅是猜測,於是我修改了Spooling Directory Source的配置,加了這麼一個配置:
tier1.sources.source1.ignorePattern = ^(.)*\\.tmp$
就是忽略監控目錄下面的.tmp文件。然後我修改了scp的邏輯,拷貝到另一臺主機上時,先命名爲:原文件名.tmp(由於是.tmp文件,agent不會採集此類文件),等SCP執行成功之後,在mv這個.tmp文件,去掉.tmp後綴,這樣agent又會抽取這個文件的數據了,通過這麼一處理,就巧妙的避免了同時讀寫一個文件的問題。
腳本調整好之後,重新運行腳本,驚喜的發現成功了,這次agent沒有掛掉,大功告成了。
總結:使用Spooling Directory Source的時候,一定要避免同時讀寫一個文件的情況。採用上面提到的方法就可以巧妙的避開這個問題。