利用kafka消息队列 ,spark实时处理数据
出现的错误有:
main找不到: 解决是把所有包匹配对。包括 spark spark streaming kafka版本问题
然后还是提示各种错误,把kafka包也添加进去之后 错误没有了
日志代码
object LoggerLevels extends Logging {
def setStreamingLogLevels() {
val log4jInitialized = Logger.getRootLogger.getAllAppenders.hasMoreElements
if (!log4jInitialized) {
logInfo("Setting log level to [WARN] for streaming example." +
" To override add a custom log4j.properties to the classpath.")
Logger.getRootLogger.setLevel(Level.WARN)
}
}
}
输入的参数
spark代码
import org.apache.spark.streaming.StreamingContext
import org.apache.spark.SparkConf
import org.apache.spark.streaming.kafka.KafkaUtils
import org.apache.spark.streaming.Seconds
import org.apache.spark.HashPartitioner
object kafacount{
//定义一个函数,可以将之前数据与现在数据累加
//upStateByKey已经是分好组的数据。
//String为单词,SparkStreaming是按批次操作,Seq是这个批次,每个单词产生的1,1,1,1(这里就是出现一个数据记录一个1)
//option上一次单词出现的次数。为什么要用Option 因为第一次没有,可以使用getOrElse(0)
def updateFunc=(it : Iterator[(String,Seq[int],Option[Int])]){
////it.flatMap(it=>Some(it._2.sum+it._3.getOrElse(0)).map(x=>(it._1,x)))
//已经知道为3个参数,对应xyz。y当前输入value 然后做累加,z是之前输入value的计数 getOrElse(0)代表如果为第一次则Z默认为0。y+z就是输入数据的总次数
it.flatMap{ case(x,y,z)=>some( y.sum+z.getOrElse(0).map(i=>(x,i)))
}
}
def main(args:Array[String]){
//设置输入日志
LoggerLevels.setStreamingLogLevels()
//设置输入的参数作为元组拿到
val Array(zkQuorum,group,topics,numThreads)=args
val conf =new SparkConf().setAppName("kafkacount").setMaster("local[2]")
val sc= new StreamingContext(conf,seconds(5))
//使用updateStateByKey必须要设置检查点
sc.checkpoint("/home/hadoop/Data")
//输入的topic肯能有多个然后进行切分,后与线程数映射成K V
val topicMap=topics.split(",").map((_,numThreads.toInt)).toMap
//用kafakUtils.createStream 主要拿kafka topic输入数据
//Streaming 配置, zk地址,组的名字,topic
val data=KafkaUtils.createStreami(sc,zkQuorum,group,topmicMap)
//在kafka生产者输入的值为value,因此要拿第二个数据_2,key是随意的
//然后输入切分
val word=data.map(_._2).flapMap(_.split(" "))
//将数据作为key 然后每一个key对应一个1。
//用updateStateByKey 计算数据总个数,不止是当前输入的,还会累加之前的数据
//第一个参数为一个函数,定义为tpdateFunc
//第二个是分区数,new一个HashPartitioner,指定一个分区数量sc.sparkContext.defultParallelism为默认分区数
//第三个表示是不是要记住这个分区器
val wordcount=word.map((_,1)).updateStateByKey(updateFunc,new HashPartitioner(sc.defultParallelism),true)
}
wordcount.print()
sc.start()
sc.awaitTermination()
}
在生产者topic 为order里输入
输出统计结果