package com.bynear.spark_Streaming;
import org.apache.spark.SparkConf;
import org.apache.spark.api.java.function.FlatMapFunction;
import org.apache.spark.api.java.function.Function2;
import org.apache.spark.api.java.function.PairFunction;
import org.apache.spark.streaming.Durations;
import org.apache.spark.streaming.api.java.JavaDStream;
import org.apache.spark.streaming.api.java.JavaPairDStream;
import org.apache.spark.streaming.api.java.JavaReceiverInputDStream;
import org.apache.spark.streaming.api.java.JavaStreamingContext;
import scala.Tuple2;
import java.util.Arrays;
/**
* 2018/5/9
* 16:52
* 实时wordCount程序
*/
public class WordCount {
public static void main(String[] args) throws InterruptedException {
/**
*创建SparkConf对象,但是这里有一点不同,需要给他设置一个master属性,代表我们测试的时候使用local模式
* local后面必须加一个方括弧,里面填写一个数字,数字代表了我们用几个线程来执行我们的SparkStreaming程序
* 只是为2 ,一个用来接收数据,一个线程用来处理数据
*/
SparkConf conf = new SparkConf().setMaster("local[2]").setAppName("wordcount");
/**
*创建JavaStreamingContext对象,
* 该对象,就类似于Spark Core中的JavaSparkContext,类似于SparkSQL中的 SQLContext
* 该对象除了接收conf对象外,还必须接收一个batch interval参数,时间片 时间间隔 就是说,每收集多长时间的数据,划分为一个batch
* 进行处理,
* 这里设置1秒
*/
JavaStreamingContext jssc = new JavaStreamingContext(conf, Durations.seconds(1));
/** 首先创建输入DStream,代表一个从数据源(kafka)来的持续不断的实时数据流
* 调用JavaStreamingContext的socketTextStream方法,可以创建一个数据源为Socket网络端口的数据流
* JavaReceiverInputDStream,代表了一个输入的DStream
* socketTextStream方法接收两个参数,参数一是监听那个主机上的端口,参数2 为监听那个端口号
*/
JavaReceiverInputDStream<String> lines = jssc.socketTextStream("localhost", 9999);
/**到这里为止,可以理解为JavaReceiverInputDStream中的,每隔一秒,就会有一个RDD,其中封装了这一秒发送过来的数据
* RDD的元素类型为String,即一行一行的文本
* 所以,这里的JavaReceiverInputDStream的泛型类型为《String》,其实就代表了它底层的RDD的泛型类型
*
* 开始对接收到的数据,执行计算,使用Spark Core提供的算子,执行应用在DStream中即可
* 在底层 实际上是会对DStream中的一个一个的RDD,执行我们应用在DStream上的算子
*
*/
JavaDStream<String> words = lines.flatMap(new FlatMapFunction<String, String>() {
@Override
public Iterable<String> call(String line) throws Exception {
return Arrays.asList(line.split(","));
}
});
/**这个时候,每秒的数据,一行一行的文本,就会被拆分成多个单词,words DStream中的RDD的元素类型即为一个一个的单词
*
* 接着, 开始进行 flatMap,reduceByKey操作
*/
JavaPairDStream<String, Integer> pairs = words.mapToPair(new PairFunction<String, String, Integer>() {
@Override
public Tuple2<String, Integer> call(String word) throws Exception {
return new Tuple2<String, Integer>(word, 1);
}
});
/**这里说明一下,用SparkStreaming与SparkCore开发程序 很相似,
* 唯一不同的是SparkCore中的JavaRDD、JavaPairRDD,都变成了JavaDStream、JavaPairDStream
*/
JavaPairDStream<String, Integer> wordCounts = pairs.reduceByKey(new Function2<Integer, Integer, Integer>() {
@Override
public Integer call(Integer num1, Integer num2) throws Exception {
return num1 + num2;
}
});
/**
*到此为止,我们就实现了实时的wordCount程序了
* 总结:
* 每秒钟发送到指定socket端口上的数据,都会被lines DStream接收到
* 然后lines DStream会把每秒的数据,也就是一行一行的文本,诸如 hello Word ,封装为一个RDD
* 然后,就会对每秒钟对应的RDD,执行后续的一系列算子操作
* 比如对lines RDD 执行flatMap操作,得到一个 words RDD 作为words DStream中的一个RDD
* 以此类推,直到生成最后一个 wordCountRDD 作为WordCounts DStream中的一个RDD
* 此时就得到了 每秒钟发送过来的数据的单词统计
*
* 但是一定要注意,SparkStreaming的计算模型,就决定了,我们必须自己来进行中间缓存的控制
* 比如写入Redis等缓存
* 它的计算模型和storm是完全不同的,storm是自己编写的一个一个程序,运行在节点上,相当于一个一个的对象,
* 可以自己在对象中控制缓存,
* 但是spark本身是函数式编程的计算模型,所以,比如words或pairs DStream中,没法在实例变量中进行缓存。
* 此时就只能将最后计算的wordcounts中的一个一个RDD,写入外部的缓存,或者持久化的DB
* 最后计算完,都打印一下这一秒的单词计数情况
* 并休眠5s钟,以便于我们的测试和观察!
*/
Thread.sleep(5000);
System.out.println("已完成——————————完成——————————完成");
wordCounts.print();
/**
* 首先对JavaStreamingContext进行一下后续处理
* 必须调用JavaStreamingContext的start方法,整个SparkStreaming Application才会启动执行
* 否则不会执行
*/
jssc.start();
jssc.awaitTermination();
jssc.stop();
}
}
SparkStreaming实时wordCount程序
最新推荐文章于 2022-03-27 15:08:48 发布