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