使用Spark Streaming+Spark SQL+Kafka+FileSystem綜合案例
1、項目分析流程圖
2、項目代碼實戰
Flume sink到Kafka需要一個jar包支持
https://github.com/beyondj2ee/flumeng-kafka-plugin/tree/master/flumeng-kafka-plugin
編輯flume-conf.properties
#配置sink
agent1.sinks.sink1.type=org.apache.flume.plugins.KafkaSink
agent1.sinks.sink1.metadata.broker.list=Master:9092,Worker1:9092,Worker2.9092
agent1.sinks.sink1.partition.key=0
agent1.sinks.sink1.partitioner.class=org.apache.flume.plugins.SinglePartition
agent1.sinks.sink1.serializer.class=kafka.serializer.StringEncoder
agent1.sinks.sink1.request.requiredacks=0
agent1.sinks.sink1.max.message.size=1000000
agent1.sinks.sink1.producer.type=sync
agent1.sinks.sink1.custom.encoding=UTF-8
agent1.sinks.sink1.custom.topic.name=HelloKafka
agent1.sinks.sink1.channel= channel1
Kafka也可以監控文件夾,但爲什麼要用Flume?Kafka只能接收json格式的文件
數據來源?
互聯網:電商、社交網絡等的網站和App程序
傳統行業:金融、電信、醫療、農業、生產製造行業;
例如說:在京東上進行廣告的推送,當我們點擊廣告的時候,此時肯定有日誌記錄Log發送回到Server中,或者說我們使用Android,iOS等中的App,都會設置有數據記錄的關鍵點(埋點)
如果是網站,經典的方式是通過JS透過Ajax把日誌穿回到服務器上,如果是移動App等一般是通過Socket,其他的傳感器或者工業設備可以通過自己的通信協議把數據傳回到服務器端
爲了應對高併發訪問,一般採用Nginx等作爲Server前段,Server的分佈式集羣來做負載均衡
Tomcat、Apache、WebLogic作爲Server後端
Server中接收到請求路由後一般都會對每個請求在文件中寫一條Log
Logs Cluster可以專門設置日誌服務器集羣,所有的Server和J2EE類型的業務邏輯在執行過程中產生的日誌信息都可以在後臺同步到日誌服務器集羣中
Server中接收到請求路由後一般都會對每個請求在文件中寫一條Log,可以自動配置Server寫日誌
企業中一般都會有Crontab等定時工具來通過日誌整理工具來把當天的日誌採集、合併和初步的處理形成一份日誌文件,然後發送到Flume監控目錄中
當Flume發現有新的日誌文件進來的時候會按照配置把數據通過Channel來Sink到目的地,這裏是Sink到Kafka集羣中
HDFS:
1、使用MapReduce作業對數據進行出不清洗,並寫入新的HDFS文件中。
2、清洗後的數據一般導入到Hive數據倉庫中,可以採用分區表
3、通過Hive中的SQL,在數據倉庫的基礎上,進行ETL,此時的ETL會把原始的數據生成很多張目標的table
企業生產環境下,Spark數據都是來自Hive
一個小例子
package com.tom.spark.sparkstreaming
import org.apache.commons.codec.StringDecoder
import org.apache.spark.SparkConf
import org.apache.spark.sql.hive.HiveContext
import org.apache.spark.streaming.kafka.KafkaUtils
import org.apache.spark.streaming.{Durations, Seconds, StreamingContext}
/**
* 使用Scala開發集羣運行的Spark來實現在線熱搜詞
*/
case class MessageItem(name: String, age: Int)
object SparkStreamingFromKafkaFlume2Hive {
def main(args: Array[String]): Unit = {
if(args.length < 2) {
System.err.println("Please input your kafka broker list and topics to consume")
System.exit(1)
}
val conf = new SparkConf().setAppName("SparkStreamingFromKafkaFlume2Hive").setMaster("local[2]")
val ssc = new StreamingContext(conf, Durations.seconds(5))
val Array(brokers, topics) = args
val kafkaParams = Map[String, String]("metadata.broker.list" -> brokers)
val topicsParams = topics.split(",").toSet
KafkaUtils.createDirectStream[String, String, StringDecoder, StringDecoder](ssc, kafkaParams, topicsParams)
.map(_._2.split(",")).foreachRDD(rdd => {
val hiveContext = new HiveContext(rdd.sparkContext)
import hiveContext.implicits._
rdd.map(record => MessageItem(record(0).trim,record(1).trim.toInt)).toDF().registerTempTable("temp")
hiveContext.sql("SELECT count(*) FROM temp").show()
})
// Flume會作爲Kafka的Producer把數據寫入到Kafka供本程序消費
ssc.start()
ssc.awaitTermination()
}
}