SparkStreaming接收socket数据,实现单词计数WordCount
在上面的案例中存在一个问题,每个批次的单词次数都被正确的统计出来,但是结果不能累加!如果需要累加需要使用updateStateByKey(func)来更新状态
架构图
实现流程
-
安装并启动生成者
首先在linux服务器上用YUM安装nc工具,nc命令式netcat命令的简称,都是用来设置路由器。我们可以利用它向某个端口发送数据。yum install -y nc
-
启动一个服务端并监听9999端口,向指定的端口发送数据
nc -lk 9999
-
编写Spark Streaming程序
package cn.test.spark
import org.apache.spark.streaming.dstream.{DStream, ReceiverInputDStream}
import org.apache.spark.streaming.{Seconds, StreamingContext}
import org.apache.spark.{SparkConf, SparkContext}
/**
* sparkStreaming流式处理,接受socket数据,实现单词统计并且每个批次数据结果累加
*/
object SparkStreamingTCPTotal {
//newValues 表示当前批次汇总成的(word,1)中相同单词的所有的1
//runningCount 历史的所有相同key的value总和
def updateFunction(newValues: Seq[Int], runningCount: Option[Int]): Option[Int] = {
val newCount =runningCount.getOrElse(0)+newValues.sum
Some(newCount)
}
def main(args: Array[String]): Unit = {
//配置sparkConf参数
val sparkConf: SparkConf = new SparkConf().setAppName("SparkStreamingTCPTotal").setMaster("local[2]")
//构建sparkContext对象
val sc: SparkContext = new SparkContext(sparkConf)
sc.setLogLevel("WARN")
//构建StreamingContext对象,每个批处理的时间间隔
val scc: StreamingContext = new StreamingContext(sc, Seconds(5))
scc.checkpoint("./")
//注册一个监听的IP地址和端口 用来收集数据
val lines: ReceiverInputDStream[String] = scc.socketTextStream("192.168.24.124", 9999)
//切分每一行记录
val words: DStream[String] = lines.flatMap(_.split(" "))
//每个单词记为1
val wordAndOne: DStream[(String, Int)] = words.map((_, 1))
//累计统计单词出现的次数
val result: DStream[(String, Int)] = wordAndOne.updateStateByKey(updateFunction)
result.print()
scc.start()
scc.awaitTermination()
}
}
通过函数updateStateByKey实现。根据于key的前置状态和key的新值,对key进行更新,返回一个新状态的DStream
执行查看效果
- 先执行nc -lk 9999
- 然后执行上述代码
- 不断的在步骤1中输入不同的单词,观察IDEA控制台输出
现象:sparkStreaming每隔5s计算一次当前5s内的数据,然后将每个批次的结果数据累加输出。