Kafka實時流資料經Storm至Hdfs
目前HDFS上日誌一部分由MR清洗生成&二次計算,一部分直接從伺服器離線上傳,但在私有云環境下,離線日誌的壓縮上傳可能會對服務造成效能影響,而且在很多日誌已經實時傳輸到Kafka叢集的情況下,考慮Kafka->Hdfs也不失為一條合理的路徑。
1. Kafka-Flume-Hdfs
這種方法直接通過Flume-ng的Hdfs-Sink往Hdfs導資料,Hdfs-Sink用來將資料寫入Hadoop分散式檔案系統(HDFS)中。支援建立text和sequence檔案及這2種檔案型別的壓縮;支援檔案週期性滾動(就是關閉當前檔案在建立一個新的),滾動可以基於時間、資料大小、事件數量;也支援通過event hearder屬性timestamp或host分割資料。HDFS目錄路徑或檔名支援格式化封裝,相應的封裝串在Hdfs-Sink生成目錄或檔案時被恰當的替換。使用HDFSSink需要首先安裝hadoop,Hdfs-Sink是通過hadoop jar和HDFS叢集通訊的。注意Hadoop版本需要支援sync()。具體配置類似:
dataAgent.channels.kafka-piwikGlobal.kafka.producer.type=sync
dataAgent.channels.kafka-piwikGlobal.topic=app_piwik
dataAgent.channels.kafka-piwikGlobal.groupId=AutoCollect-piwikGlobal-1
dataAgent.channels.kafka-piwikGlobal.zookeeperConnect=192.168.1.10:2181,192.168.1.11:2181
dataAgent.channels.kafka-piwikGlobal.brokerList=192.168.1.10:9092,192.168.1.11:9092
dataAgent.channels.kafka-piwikGlobal.is_avro_event=false
dataAgent.channels.kafka-piwikGlobal.transactionCapacity=100000
dataAgent.channels.kafka-piwikGlobal.capacity=6000000
dataAgent.channels.kafka-piwikGlobal.type=org.apache.flume.channel.kafka.KafkaChannel
dataAgent.channels.kafka-piwikGlobal.parseAsFlumeEvent=false
dataAgent.sinks.hdfs-piwikGlobal.channel=kafka-piwikGlobal
dataAgent.sinks.hdfs-piwikGlobal.type=hdfs
#使用gzip壓縮演算法
dataAgent.sinks.hdfs-piwikGlobal.hdfs.codeC=gzip
dataAgent.sinks.hdfs-piwikGlobal.hdfs.fileType=CompressedStream
#日誌儲存路徑,這裡按小時存放
dataAgent.sinks.hdfs-piwikGlobal.hdfs.path=hdfs://argo/data/logs/autoCollect/piwikGlobal/%Y-%m-%d/%H
#檔案字首,也可以使用封裝串
dataAgent.sinks.hdfs-piwikGlobal.hdfs.filePrefix=piwikGlobal
#不按時間滾動
dataAgent.sinks.hdfs-piwikGlobal.hdfs.rollInterval=0
#不根據檔案大小滾動
dataAgent.sinks.hdfs-piwikGlobal.hdfs.rollSize=0
#按事件條數滾動
dataAgent.sinks.hdfs-piwikGlobal.hdfs.rollCount=1000000
#hadoop叢集響應時間較長時需要配置
dataAgent.sinks.hdfs-piwikGlobal.hdfs.callTimeout=40000
#100秒後這個檔案還沒有被寫入資料,就會關閉它然後去掉.tmp,後續的events會新開一個.tmp檔案來接收
dataAgent.sinks.hdfs-piwikGlobal.hdfs.idleTimeout=100
dataAgent.sinks.hdfs-piwikGlobal.hdfs.useLocalTimeStamp=true
這種方式在日誌量大的情況下,需要啟動多個Hdfs-Sink或多個Flume程式,甚至需要部署在多臺機器上,不好管理,並且在特定需求下,還需要做定製開發。
2.Kafka-Storm-Hdfs
這種方法通過storm往hdfs寫資料,可以做定製開發,可以根據日誌量調整併發度,上下線方便,可根據Storm REST Api做監控報警。
官方原始碼:https://github.com/apache/storm/tree/master/external/storm-hdfs
主要的類為HdfsBolt和SequenceFileBolt,都在org.apache.storm.hdfs.bolt包中。HdfsBolt用來寫text資料, SequenceFileBolt用來寫二進位制資料。
HdfsBolt的配置引數:
1、RecordFormat:定義欄位分隔符,你可以使用換行符\n或者製表符\t;
2、SyncPolicy:定義每次寫入的tuple的數量;
3、FileRotationPolicy:定義寫入的hdfs檔案的輪轉策略,你可以以時間輪轉(TimedRotationPolicy)、大小輪轉(FileSizeRotationPolicy)、不輪轉(NoRotationPolicy);
4、FileNameFormat:定義寫入檔案的路徑(withPath)和檔名的前字尾(withPrefix、withExtension);
5、withFsUrl:定義hdfs的地址。
示例:
RecordFormat format = new DelimitedRecordFormat().withFieldDelimiter("|");
SyncPolicy syncPolicy = new CountSyncPolicy(1000);
FileRotationPolicy rotationPolicy = new FileSizeRotationPolicy(5.0f, Units.MB);
FileNameFormat fileNameFormat = new DefaultFileNameFormat()
.withPath("/data/logs");
HdfsBolt bolt = new HdfsBolt()
.withFsUrl("hdfs://localhost:8020")
.withFileNameFormat(fileNameFormat)
.withRecordFormat(format)
.withRotationPolicy(rotationPolicy)
.withSyncPolicy(syncPolicy);
如果要連線開啟了HA的Hadoop叢集,可以改為withFsURL(“hdfs://nameserviceID”)。
nameserviceID可以在hdfs-site.xml中查到。
<property>
<name>dfs.nameservices</name>
<value>nameserviceID</value>
</property>
這裡存在的問題是,一個執行緒只會寫一個檔案,不支援壓縮儲存,無法分目錄,因此需要做一些修改。
1)Gzip壓縮儲存
this.fs = FileSystem.get(URI.create(this.fsUrl), hdfsConfig);
CompressionCodecFactory compressionCodecFactory = new CompressionCodecFactory(new Configuration());
CompressionCodec compressionCodec = compressionCodecFactory.getCodecByClassName("org.apache.hadoop.io.compress.GzipCodec");
FSDataOutputStream out = this.fs.create(new Path(parentPath, new Path(childStrPath)));
CompressionOutputStream compressionOutput = compressionCodec.createOutputStream(out, compressionCodec.createCompressor());
#寫資料
compressionOutput.write(bulkStr.toString().getBytes());
Flush操作也需要做些修改,太過頻繁會影響寫入效能:
try {
compressionOutput.flush();
if (out instanceof HdfsDataOutputStream) {
((HdfsDataOutputStream) out).hsync(EnumSet.of(HdfsDataOutputStream.SyncFlag.UPDATE_LENGTH));
} else {
out.hsync();
}
} catch (IOException e) {
LOG.error("flush error:{}",e.getMessage());
}
如果worker異常終止,造成gzip檔案非正常關閉,通過hdfs -text命令是可以正常檢視的,但一般MR程式無法讀取此類檔案,指標不治本的方法,可以簡單設定mapred.max.map.failures.percent來跳過異常檔案,或者自己實現InputStream類。
2)分目錄寫入
比如對於接收到的每一條日誌,需要解析時間或型別,按/type/day/hour的方式儲存,這就會導致一個hdfsBolt執行緒需要開啟多個不同目錄下的檔案進行寫入。
#每個目錄對應一個Path物件,以防重複建立
private Map<String, Path> parentPathObjMap = Maps.newHashMap();
#每個目錄對應一個CompressionOutputStream物件,判斷日誌需要寫入哪一個目錄,則獲取相應物件寫入
private Map<String, CompressionOutputStream> pathToCompWriter = Maps.newHashMap();
#每個目錄對應一個StringBuilder物件,積攢一批日誌寫入,以提高效能
private Map<String, StringBuilder> pathToCache = Maps.newHashMap();
#每個目錄對應一個Long物件,判斷積攢日誌量是否滿足寫入閾值
private Map<String, Long> pathToCacheLineNum = Maps.newHashMap();
#每個目錄對應一個檔案輪轉物件
private Map<String, FileRotationPolicy> fileRotationMap = Maps.newHashMap();
#每個目錄寫入的日誌位元組數,用來判斷是否輪轉
private Map<String, Long> offsetMap = Maps.newHashMap();
#每個目錄上次寫入的時間,超過一定時間沒有資料寫入,則關閉檔案
private Map<String, Long> lastFlushTimeMap = Maps.newHashMap();
因為一個執行緒在一個目錄下只會往一個檔案寫,因此這些Map的key值都為目錄路徑。
在程式執行過程本來將日誌解析單獨作為一個bolt,後來將其融入HdfsBolt,以配置正規表示式的方式,減少網路傳輸開銷,來提高效能。
相關文章
- 大資料6.1 - 實時分析(storm和kafka)大資料ORMKafka
- 使用Storm、Kafka和ElasticSearch處理實時資料 -javacodegeeksORMKafkaElasticsearchJava
- Storm 系列(九)—— Storm 整合 KafkaORMKafka
- Storm系列(六)storm和kafka整合ORMKafka
- Storm與kafka整合ORMKafka
- kafka+storm+hbaseKafkaORM
- kafka和websocket實時資料推送KafkaWeb
- 淺談hdfs架構與資料流架構
- SpringBoot整合Kafka和StormSpring BootKafkaORM
- storm-kafka-client使用ORMKafkaclient
- Logstash讀取Kafka資料寫入HDFS詳解Kafka
- Flume將 kafka 中的資料轉存到 HDFS 中Kafka
- 實時資料處理:Kafka 和 FlinkKafka
- Spark Streaming,Flink,Storm,Kafka Streams,Samza:如何選擇流處理框架SparkORMKafka框架
- 大資料Storm 之RCE實踐大資料ORM
- VoltDB讓Kafka支援複雜資料流驅動的實時業務決策Kafka
- kafka connect,將資料批量寫到hdfs完整過程Kafka
- storm(1.1.3)與kafka(1.0.0)整合ORMKafka
- Mysql增量寫入Hdfs(二) --Storm+hdfs的流式處理MySqlORM
- 使用Flume消費Kafka資料到HDFSKafka
- 阿里 Canal 實時同步 MySQL 增量資料至 ClickHouse 資料庫阿里MySql資料庫
- Storm大資料位置ORM大資料
- Kafka如何實現實時流處理 Part 1 - André MeloKafka
- 如果通過流資料實現實時分析?
- Mysql增量寫入Hdfs(一) --將Mysql資料寫入Kafka TopicMySqlKafka
- canal+mysql+kafka實時資料同步安裝、配置MySqlKafka
- Spark+Kafka實時監控Oracle資料預警SparkKafkaOracle
- 大資料開發實戰:實時資料平臺和流計算大資料
- HDFS資料平衡
- 通過DTS將RDS的資料實時同步至DataHub
- Spark拉取Kafka的流資料,轉插入HBase中SparkKafka
- 大資料流處理:Flume、Kafka和NiFi對比大資料KafkaNifi
- mysql通過kafka實現資料實時同步(三)——es叢集配置MySqlKafka
- 快速部署DBus體驗實時資料流計算
- 使用Kafka和Flink構建實時資料處理系統Kafka
- alpakka-kafka(8)-kafka資料消費模式實現Kafka模式
- ETL資料整合丨透過ETLCloud工具,將Oracle資料實時同步至Doris中CloudOracle
- 亞信安慧AntDB資料庫——實時流資料處理的先鋒資料庫
- MongoDB和資料流:使用MongoDB作為Kafka消費者MongoDBKafka