object RealTimeRequestParamCollect {
// 在僞分佈式中,一個spark 應用對應了一個main函數,放在一個driver裏,driver裏有一個對應的實例(spark context).driver 負責向各個節點分發資源以及數據。
// 那麼如果你把創建實例放在了main函數的外面,driver就沒法分發了。所以如果這樣寫在local模式下是可以成功的,在分佈式就會報錯。
// https://blog.csdn.net/sinat_33761963/article/details/51723175
// 這裏使用lazy 懶加載解決這個問題
private lazy val spark = SparkSession.builder().appName("線上日誌收集").config("spark.serializer", "org.apache.spark.serializer.KryoSerializer").config("hive.exec.dynamic.partition.mode", "nonstrict")
.enableHiveSupport()
// 本地啓動使用,並且本地調試只用使用run模式,debug模式看不到日誌 start
// .master("local[2]")
// 本地啓動使用 end
.getOrCreate()
def main(args: Array[String]): Unit = {
val batchInterval = 60
val brokers = "123.234.231.111:9092" //指的是kafka的地址
val topics = "aaaa_topic" // 監聽的topic 英文“,”分割
val groupId = "consumer_group" //注意,這個也就是我們的消費者的名字
//步驟一:如下兩個參數配置了以後,就可以在spark界面上看到監控,不配置就看不到
// https://stackoverflow.com/questions/49307317/how-to-use-sparksession-and-streamingcontext-together
// sc 爲了保證StreamingContext和SparkSession使用一個SparkConf配置
// 當同時存在多個SparkConf時,會拋出這個異常:org.apache.spark.SparkException: Only one SparkContext may be running in this JVM (see SPARK-2243). To ignore this error, set spark.driver.allowMultipleContexts = true
val sc = spark.sparkContext
// sparkConf.set("spark.streaming.kafka.ui.enable", "1")
sc.getConf.set("spark.streaming.kafka.groupid", groupId)
val ssc = new StreamingContext(sc, Seconds(batchInterval))
// 監聽的topic 英文“,”分割
val topicsSet = topics.split(",").toSet
val kafkaParams = Map[String, String](
"metadata.broker.list" -> brokers,
"group.id" -> groupId
)
//步驟二:設置轉轉監聽器,幫我們完成偏移量的提交
ssc.addStreamingListener(
new FFListener(kafkaParams));
//鍵步驟三: 創建對象,然後通過這個對象獲取到上次的偏移量,然後獲取到數據流
val km = new KafkaManager(kafkaParams)
val messages = km.createDirectStream[String, String, StringDecoder, StringDecoder](
ssc, kafkaParams, topicsSet)
//完成你的業務邏輯即可
messages.foreachRDD(rdd => {
//獲取當前消息所屬的topic
val offsetRanges = rdd.asInstanceOf[HasOffsetRanges].offsetRanges
var topic: String = ""
offsetRanges.take(1).foreach(osr => topic = osr.topic)
// 處理日誌
rdd.flatMap(_._2.split("\n")).filter(
msg => PATTERN.matcher(msg).find()).take(100).foreach(c => {
logger.info("method=rdd.foreach topic :"+topic +" record:" + c);
})
})
ssc.start()
ssc.awaitTermination()
// ssc.stop()
}
}
參考資料:https://blog.csdn.net/sinat_33761963/article/details/51723175
https://stackoverflow.com/questions/49307317/how-to-use-sparksession-and-streamingcontext-together