Flume 實現自己的實時日誌(2)
目錄解讀
最近接觸到Flume,這裡透過一些小案例做一些學習的分享。主要包括以下內容:
1-概念、2-原始碼編譯、3-快速入門:
4-原始碼解讀
5-TAILDIR監聽日誌檔案,原始碼修改,新增系統名稱
6-TAILDIR監聽日誌檔案到HDFS的案例
7-TAILDIR監聽日誌檔案到Kafka的案例
8-TAILDIR監聽日誌檔案到ES6.X版本的案例(包括自己實現ES高版本的Sink)
注:本系列所有文章基於Flume 1.7.0
所有分析和註釋程式碼都在:
原始碼解讀
透過概念和快速的入門,大體對flume進行了瞭解。下面讓我們一起看一下flume的原始碼,
方便我們後續的使用。
(1)flume-ng-node
在這個模組下面找到org.apache.flume.node.Application入口類。就可以看到啟動
的main函式:
***對我們啟動命令的引數進行解析***
CommandLineParser parser = new GnuParser();
CommandLine commandLine = parser.parse(options, args);
***根據命令獲取到我們的配置檔案***
logger.info("flume載入的配置檔名稱:"+commandLine.getOptionValue('f'));
File configurationFile = new File(commandLine.getOptionValue('f'));
***獲取配置資訊,啟動source,channel,sink元件***
if (reload) {
logger.info("啟動PollingPropertiesFileConfigurationProvider進行輪訓檢查配置檔案是否修改!!!!!!");
EventBus eventBus = new EventBus(agentName + "-event-bus");
PollingPropertiesFileConfigurationProvider configurationProvider =
new PollingPropertiesFileConfigurationProvider(
agentName, configurationFile, eventBus, 30);
components.add(configurationProvider);
application = new Application(components);
eventBus.register(application);
} else {
PropertiesFileConfigurationProvider configurationProvider =
new PropertiesFileConfigurationProvider(agentName, configurationFile);
application = new Application();
application.handleConfigurationEvent(configurationProvider.getConfiguration());
}
***reload這種情況***
可以看到會初始化一個PollingPropertiesFileConfigurationProvider類,這個類的作用
就是當呼叫 application.start() 的時候 會啟動一個定時的任務檢查配置檔案是否修改
executorService = Executors.newSingleThreadScheduledExecutor(
new ThreadFactoryBuilder().setNameFormat("conf-file-poller-%d")
.build());
FileWatcherRunnable fileWatcherRunnable =
new FileWatcherRunnable(file, counterGroup);
executorService.scheduleWithFixedDelay(fileWatcherRunnable, 0, interval,
TimeUnit.SECONDS);
可以看到FileWatcherRunnable裡面的具體實現:
public void run() {
LOGGER.debug("Checking file:{} for changes", file);
counterGroup.incrementAndGet("file.checks");
long lastModified = file.lastModified();
if (lastModified > lastChange) {
LOGGER.info("Reloading configuration file:{}", file);
counterGroup.incrementAndGet("file.loads");
lastChange = lastModified;
try {
eventBus.post(getConfiguration());//會呼叫回撥函式handleConfigurationEvent
} catch (Exception e) {
...
} catch (NoClassDefFoundError e) {
...
} catch (Throwable t) {
...
}
}
}
***eventBus.post(getConfiguration())***
getConfiguration()非常重要
它會解析我們的配置檔案,獲取我們配置的具體實現類
loadChannels(agentConf, channelComponentMap);
loadSources(agentConf, channelComponentMap, sourceRunnerMap);
loadSinks(agentConf, channelComponentMap, sinkRunnerMap);
比如loadChannels:
Channel channel = getOrCreateChannel(channelsNotReused,
comp.getComponentName(), comp.getType());
在ChannelType裡面定義了所支援的Channel型別和具體的實現類
MEMORY("org.apache.flume.channel.MemoryChannel")
FILE("org.apache.flume.channel.file.FileChannel")
同理loadSources也差不多具體實現跨越深入此方法
Source source = sourceFactory.create(comp.getComponentName(),
comp.getType());
SourceType裡面會定義支援的Source型別
TAILDIR("org.apache.flume.source.taildir.TaildirSource")
AVRO("org.apache.flume.source.AvroSource")
最後看一下loadSinks會發現也一樣
//獲取具體的sink實現
Sink sink = sinkFactory.create(comp.getComponentName(), comp.getType());
SinkType裡面會定義自帶的Sink
HBASE("org.apache.flume.sink.hbase.HBaseSink")
HIVE("org.apache.flume.sink.hive.HiveSink")
注意在獲取sink class過程當中
if (!sinkType.equals(SinkType.OTHER)) {
sinkClassName = sinkType.getSinkClassName();
}
如果沒有在SinkType裡面配置則需要配置全類名,比如kafka需要配置:
org.apache.flume.sink.kafka.KafkaSink
*** SourceRunner和SinkRunner ***
SourceRunner和SinkRunner是對我們具體配置source和sink的包裝,並且會呼叫
具體的方法,比如start,process,stop.(非常重要的兩個類,自己檢視完整程式碼)
sourceRunnerMap.put(comp.getComponentName(),
SourceRunner.forSource(source));
source會被包裝在SourceRunner裡面
如果實現PollableSource則會初始化PollableSourceRunner,比如TaildirSource
就是實現 PollableSource
因此真正啟動的時候會執行PollableSourceRunner裡面的start方法,
透過 PollableSourceRunner 然後呼叫真正source的方法。
sinkRunnerMap.put(comp.getComponentName(),
new SinkRunner(group.getProcessor()));
類似SourceRunner,Sink的流程主要在SinkRunner裡面控制
SinkRunner
runner = new PollingRunner();會執行runner執行緒的run方法
***handleConfigurationEvent回撥函式***
這個方法會啟動我們配置的元件
@Subscribe
public synchronized void handleConfigurationEvent(MaterializedConfiguration conf) {
stopAllComponents();
startAllComponents(conf);
}
startAllComponents(conf);//啟動元件,按下面的順序
Starting Channel...
Starting Sink...
Starting Source...
元件的啟動都是呼叫了supervisor.supervise
supervisor.supervise(entry.getValue(),
new SupervisorPolicy.AlwaysRestartPolicy(), LifecycleState.START);
具體啟動的地方在MonitorRunnable監控執行緒裡面
try {
logger.info("啟動元件start...... : "+lifecycleAware.getClass().getSimpleName());
lifecycleAware.start();
} catch (Throwable e) {
}
source和sink實際上是會啟動SourceRunner和SinkRunner
LifecycleAware是一個頂級介面,定義了元件的開始,結束以及當前狀態,flume中重要元件如source,sink,channel都實現了這個介面
***KafkaSink流程***
透過KafkaSink具體程式碼實現來看上面的分析
在loadSinks的時候執行configure方法會根據配置設定kafka的配置引數
在startAllComponents裡面會啟動SourceRunner和SinkRunner
SinkRunner會呼叫KafkaSink的start方法初始化kafkaProducer
然後執行KafkaSink的process開始從channel中獲取資料。
未完待續
5-TAILDIR監聽日誌檔案,原始碼修改,新增系統名稱
6-TAILDIR監聽日誌檔案到HDFS的案例
7-TAILDIR監聽日誌檔案到Kafka的案例
8-TAILDIR監聽日誌檔案到ES6.X版本的案例(包括自己實現ES高版本的Sink)
程式碼地址
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/2001/viewspace-2821204/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- go開發屬於自己的日誌庫-檔案日誌庫實現Go
- go 開發屬於自己的日誌庫-檔案日誌庫原型實現Go原型
- SpringBoot日誌實現Spring Boot
- CDN日誌實時分析
- 日誌採集框架Flume框架
- SpringBoot 實現整合log4j2日誌Spring Boot
- Flume+Kafka收集Docker容器內分散式日誌應用實踐KafkaDocker分散式
- CentOS 7.0下nginx實現每天定時分割日誌CentOSNginx
- SpringBoot | SpringBoot 是如何實現日誌的?Spring Boot
- 分散式 | DBLE 的 general 日誌實現分散式
- Flume收集日誌到本地目錄
- 使用 Serverless 實現日誌報警Server
- Rust 實現日誌記錄功能Rust
- linux-實現日誌分析--pythonLinuxPython
- Yii使用DbTarget實現日誌功能
- .Net Core 審計日誌實現
- 利用oracle的日誌挖掘實現回滾Oracle
- 雲端日誌服務——UPLOG的實現
- Java實時讀取日誌檔案Java
- SpringBoot2 整合日誌,複雜業務下的自定義實現Spring Boot
- 大資料01-Flume 日誌收集大資料
- Data Guard備庫日誌的實時應用與非實時應用
- 從零開始實現放置遊戲(五)——實現掛機戰鬥(3)引入日誌功能並實現切面日誌遊戲
- 如何基於日誌,同步實現資料的一致性和實時抽取?
- 實訓日誌
- C語言回撥日誌庫的實現C語言
- C# Debug執行日誌Logs的實現C#
- 欄位修改記錄操作日誌的實現
- hyperf 如何實現按日期分割日誌
- ELK實時分析之php的laravel專案日誌PHPLaravel
- 基於flink和drools的實時日誌處理
- Linux 中實時檢視日誌的3種方法Linux
- 日誌實時分析:從入門到精通
- 實現自己的promisePromise
- Django websocket之web端實時檢視日誌實踐案例DjangoWeb
- 解鎖Nginx日誌的寶藏:GoAccess——你的實時、互動式Web日誌分析神器!NginxGoWeb
- 實現後臺管理系統的操作日誌功能
- 如何實現一個高效的本地日誌收集程式