实时分析kafka数据进行单词计数

1.首先要解决版本问题,先看自己的spark的版本,这一步及其重要,scala版本必须相同 我的scala版本是 2.11.12
在这里插入图片描述
2.在你的idea下面导入相同的scala版本,步骤放上
在这里插入图片描述
3.引入jar包 ,现在我的kafka的版本是 2.11-2.00的版本
所以 streaming-kafka-0-10_2.10 这个包一定要2.10

dependencies {
    testCompile group: 'junit', name: 'junit', version: '4.12'
    compile (group: 'org.apache.spark', name: 'spark-core_2.10', version:'2.2.0')
    compile (group: 'org.apache.spark', name: 'spark-streaming_2.10', version:'2.2.0')
    compile group: 'org.apache.spark', name: 'spark-streaming-kafka-0-10_2.10', version: '2.2.0'
}

4.完成上面的环境搭建也就完成重要的一步了,下面开始一个简单的案例,我们先到cmd下面创建主题,启动一个生产者,不了解kafka的命令的可以查看这个网站kafka命令点击这里,如何我们新建一个项目
1.先是声明一个构造器

Logger.getLogger("org").setLevel(Level.ERROR) //配置日志
val conf = new SparkConf().setMaster("local[*]").setAppName("NetworkWordCount")//设置spark运行环境和运行线程数,和运行名
val ssc = new StreamingContext(conf, Seconds(2))//实时流信息 每隔两秒到卡夫卡里面去poll拉取信息```

2.这里其实可以把这里看成是一个kafka的消费端,所以要反序列化消息,指定消费者的状态

  //当前是consumer端,要反序列化消息
    val kafkaParams = Map[String, Object](
      "bootstrap.servers" -> "localhost:9092,localhost:9093,localhost:9094",
      "key.deserializer" -> classOf[StringDeserializer],
      "value.deserializer" -> classOf[StringDeserializer],
      "group.id" -> "streaming74",    //消费者组编号
      "auto.offset.reset" -> "latest",       //消息从哪里开始读取  latest 从头
      "enable.auto.commit" -> (true: java.lang.Boolean)   //消息的位移提交方式
    )
    //要订阅的主题
    val topics = Array("topic74streaming1")

这里简单介绍一下消费组的原理,其实可以将消费组看成是一个消费者,这个消费者回读取分区上面的所有的数据,两个消费组直接数据是互斥的,但是两消费者组直接是数据共享的
3.这一步 就是要创建DStream 可以将DStream看成是一个个的RDD,就可以利用scala里面的函数来进行简单计算了
给一个git帐号,里面还有很多的案例可供参考点击这里可以查看更多案例和完整的项目

 //创建DStream
    val stream = KafkaUtils.createDirectStream[String, String](
      ssc,
      PreferConsistent,
      Subscribe[String, String](topics, kafkaParams)    //     SubscribePattern:主题名由正则表示    , Subscribe:主题名固定   Assign:固定分区
    )
    //    ConsumerRecord 从Kafka里面读到的数据
    val lines:DStream[String]=stream.map(record => (   record.value)  )
    //将数据进行展平
    val words:DStream[String]=lines.flatMap(   _.split(" "))
    //将每一个单词映射成 (word,1)的格式
    val wordAndOne:DStream[(String,Int)]=words.map(   (_,1) )
    //根据键相同的值来进行归约
    val reduced:DStream[  (String,Int) ]=wordAndOne.reduceByKey( _+_)
    reduced.print()//打印输出
    ssc.start()//开始实时流监控
    ssc.awaitTermination()//线程等待

全部代码

import org.apache.kafka.common.serialization.StringDeserializer
import org.apache.log4j.{Level, Logger}
import org.apache.spark.{HashPartitioner, SparkConf}
import org.apache.spark.streaming.dstream.DStream
import org.apache.spark.streaming.kafka010.ConsumerStrategies.Subscribe
import org.apache.spark.streaming.kafka010.KafkaUtils
import org.apache.spark.streaming.kafka010.LocationStrategies.PreferConsistent
import org.apache.spark.streaming.{Seconds, StreamingContext}
object kafkaTest_status{
  def main(args: Array[String]): Unit = {
    Logger.getLogger("org").setLevel(Level.ERROR) //配置日志
    val conf = new SparkConf().setMaster("local[*]").setAppName("NetworkWordCount")
    val ssc = new StreamingContext(conf, Seconds(2))
//    ssc.checkpoint("./chpoint")   //以后是一个hdfs 对于窗口和有状态的操作必须checkpoint,通过StreamingContext的checkpoint来指定目录,
    //当前是consumer端,要反序列化消息
    val kafkaParams = Map[String, Object](
      "bootstrap.servers" -> "localhost:9092,localhost:9093,localhost:9094",
      "key.deserializer" -> classOf[StringDeserializer],
      "value.deserializer" -> classOf[StringDeserializer],
      "group.id" -> "streaming74",    //消费者组编号
      "auto.offset.reset" -> "latest",       //消息从哪里开始读取  latest 从头
      "enable.auto.commit" -> (true: java.lang.Boolean)   //消息的位移提交方式
    )
    //要订阅的主题
    val topics = Array("topic74streaming1")
    //创建DStream
    val stream = KafkaUtils.createDirectStream[String, String](
      ssc,
      PreferConsistent,
      Subscribe[String, String](topics, kafkaParams)    //     SubscribePattern:主题名由正则表示    , Subscribe:主题名固定   Assign:固定分区
    )
    //    ConsumerRecord
    val lines:DStream[String]=stream.map(record => (   record.value)  )
    val words:DStream[String]=lines.flatMap(   _.split(" "))
    val wordAndOne:DStream[(String,Int)]=words.map(   (_,1) )

    //val reduced:DStream[  (String,Int) ]=wordAndOne.reduceByKey( _+_)
    val reduced=wordAndOne.updateStateByKey(   updateFunc, new HashPartitioner(  ssc.sparkContext.defaultMinPartitions  ),  true)
    reduced.print()
    ssc.start()
    ssc.awaitTermination()
  }

  /**
   * iter:   当前操作的RDD
   * String: 聚合的key
   * Seq[Int]: 在这个批次中此key在这个分区出现的次数集合  [1,1,1,1,1].sum()
   * Option[Int]:初始值或累加值   Some   None-> 模式匹配
   */
  val updateFunc= (   iter:Iterator[ (String,Seq[Int] ,  Option[Int] ) ] ) =>{
    //方案一:当成一个三元组运算
    // iter.map(    t=> (  t._1,   t._2.sum+t._3.getOrElse(0)  )    )   //  ->  { word:总次数}
    //方案二: 模式匹配来实现
    iter.map{  case(x,y,z)=>(  x,  y.sum+z.getOrElse(0)   ) }
  }

}



生产端代码

package wordSetGener
import java.util.{Properties, Random}
import org.apache.kafka.clients.producer.{KafkaProducer, ProducerRecord}
import scala.io.{BufferedSource, Source}
object Product {
  def main(args: Array[String]): Unit = {
    val event=10
    val topic = "comment"
    val props = new Properties()
    props.put("bootstrap.servers", "localhost:9092,localhost:9093,localhost:9094")
    props.put("acks", "all") // 确认的级别  ISR
    props.put("key.serializer", "org.apache.kafka.common.serialization.StringSerializer") //生产端用序列化
    props.put("value.serializer", "org.apache.kafka.common.serialization.StringSerializer")
    val line:BufferedSource=Source.fromFile("data/hanzi.txt")
    val rd=new Random();
    val li=line.mkString
    //随机发送10条消息
    for (i<-Range(0,event)){
      val sb=new StringBuilder()
      //随机生成20个数据
      for (ind <- Range(0,rd.nextInt(20))){
        sb+= li.charAt(rd.nextInt(li.length))
      }
      val userkey="User"+rd.nextInt(100)
      //发送消息
      val producer = new KafkaProducer[String, String](props);
      val pr = new ProducerRecord[String, String](topic, userkey,sb.toString()) // 0表示消息的类型  name 地址 类型
      producer.send(pr)

    }```

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,以下是一个简单的示例代码,假设我们要消费名为“test”的Kafka主题,并对其中的单词进行词频统计: ```scala import org.apache.spark.streaming.{Seconds, StreamingContext} import org.apache.spark.streaming.kafka._ import org.apache.kafka.common.serialization.StringDeserializer import org.apache.spark.SparkConf object WordCount { def main(args: Array[String]): Unit = { // 创建 SparkConf 对象 val conf = new SparkConf().setAppName("WordCount").setMaster("local[*]") // 创建 StreamingContext 对象 val ssc = new StreamingContext(conf, Seconds(5)) // 设置 Kafka 相关参数 val kafkaParams = Map[String, Object]( "bootstrap.servers" -> "localhost:9092", "key.deserializer" -> classOf[StringDeserializer], "value.deserializer" -> classOf[StringDeserializer], "group.id" -> "test-group", "auto.offset.reset" -> "latest", "enable.auto.commit" -> (false: java.lang.Boolean) ) // 创建一个 Kafka DStream val kafkaStream = KafkaUtils.createDirectStream[String, String]( ssc, LocationStrategies.PreferConsistent, ConsumerStrategies.Subscribe[String, String](Array("test"), kafkaParams) ) // 从 Kafka DStream 中提取单词 val words = kafkaStream.flatMap(record => record.value().split(" ")) // 对单词进行计数 val wordCounts = words.map(word => (word, 1)).reduceByKey(_ + _) // 输出计数结果 wordCounts.print() // 启动 Spark Streaming ssc.start() ssc.awaitTermination() } } ``` 上述代码中,我们首先创建了一个 `SparkConf` 对象,并设置了应用程序名为“WordCount”,使用本地模式运行。然后创建了一个 `StreamingContext` 对象,每隔 5 秒钟将接收到的数据进行批处理。 接下来,我们设置了 Kafka 相关参数,包括 Broker 地址、键值对反序列化器、消费者组 ID 等。然后使用 `KafkaUtils.createDirectStream` 方法创建了一个 Kafka DStream。在这个 DStream 上,我们使用 `flatMap` 方法将每个消息的值按空格拆分成单词,并使用 `map` 和 `reduceByKey` 方法对单词进行计数。最后,我们调用 `print` 方法输出计数结果。 最后,我们启动 Spark Streaming 并等待计算完成。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值