一、什么是Spark Streaming?特点
在spark streaming这一块,还是使用scala语言比较好一点,因为Java好多api并没有提供,而scala语言把各个功能的模块的api进行封装好了。
Spark Streaming makes it easy to build scalable fault-tolerant streaming applications.
spark streaming获得数据,最终要转化为rdd进行操作阶段数据。
由于spark streaming是按时间间隔进行获取数据,并不是真正上的streaming,获取时间的间隔又形成一个一个rdd,因此rdd之间是离散的。在同一时刻,spark里面可能存在多个rdd。
特点:
1、易用:支持Java、Scala、Python,集成Spark SQL
2、容错机制
3、已经集成到Spark
二、开发自己的NetworkWordCount
java版本
添加依赖
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-core_2.11</artifactId>
<version>2.3.2</version>
</dependency>
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-sql_2.11</artifactId>
<version>2.3.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.spark/spark-streaming -->
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-streaming_2.11</artifactId>
<version>2.3.2</version>
</dependency>
代码展示
public class MyNetworkWordCount {
public static void main(String[] args) throws Exception {
Logger.getLogger("org.apache.spark").setLevel(Level.ERROR);
Logger.getLogger("org.eclipse.jetty.server").setLevel(Level.OFF);
SparkConf conf = new SparkConf().setAppName("MyNetworkWordCount")
// local[2] 表示:相当于有两个CPU的核数
.setMaster("local[2]");
JavaStreamingContext js = new JavaStreamingContext(conf, Durations.seconds(3));
//创建一个输入流:DStream离散流,表现形式看,就是RDD
JavaReceiverInputDStream<String> line = js.socketTextStream("192.168.92.111", 1234);
JavaDStream<String> rdd1 = line.flatMap(new FlatMapFunction<String, String>() {
@Override
public Iterator<String> call(String s) throws Exception {
return Arrays.asList(s.split(" ")).iterator();
}
});
rdd1.print();
js.start();
js.awaitTermination();
}
}
在Linux系统上执行nc -l 1234
Java streaming版本没有reducebykey这个方法
三、核心数据模型
DStream(离散流),就是一个RDD,DStream是:通过一个时间采用的间隔,把连续的数据流变成不连续RDD
1、窗口操作:
指定窗口的参数:1、窗口的大小 2、窗口的滑动距离,集成Spark SQL,就是计算现在过去和现在的数据
public class MyNetworkWordCountByWindow {
public static void main(String[] args) throws Exception {
Logger.getLogger("org.apache.spark").setLevel(Level.ERROR);
Logger.getLogger("org.eclipse.jetty.server").setLevel(Level.OFF);
SparkConf conf = new SparkConf().setAppName("MyNetworkWordCount")
// local[2] 表示:相当于有两个CPU的核数
.setMaster("local[2]");
JavaStreamingContext js = new JavaStreamingContext(conf, Durations.seconds(3));
//创建一个输入流:DStream离散流,表现形式看,就是RDD
JavaReceiverInputDStream<String> line = js.socketTextStream("192.168.92.111", 1234);
JavaDStream<String> rdd1 = line.flatMap(new FlatMapFunction<String, String>() {
@Override
public Iterator<String> call(String s) throws Exception {
return Arrays.asList(s.split(" ")).iterator();
}
});
/*
* Function2 : 执行的窗口计算
* Seconds(30) 窗口的大小
* Seconds(9) 窗口滑动的距离
* 注意:窗口滑动的距离,一定要是采样时间的整数倍
*/
JavaDStream<String> rdd2 = rdd1.reduceByWindow(new Function2<String, String, String>() {
@Override
public String call(String s, String s2) throws Exception {
return s + s2;
}
}, Durations.seconds(30), Durations.seconds(9));
rdd2.print();
js.start();
js.awaitTermination();
}
}
2、集成Spark SQL
public class SparkStreamSql {
public static void main(String[] args) throws InterruptedException {
Logger.getLogger("org.apache.spark").setLevel(Level.ERROR);
Logger.getLogger("org.eclipse.jetty.server").setLevel(Level.OFF);
SparkConf conf = new SparkConf().setAppName("MyNetworkWordCount")
// local[2] 表示:相当于有两个CPU的核数
.setMaster("local[2]");
JavaStreamingContext js = new JavaStreamingContext(conf, Durations.seconds(3));
//创建一个输入流:DStream离散流,表现形式看,就是RDD
JavaReceiverInputDStream<String> line = js.socketTextStream("192.168.92.111", 1234);
JavaDStream<String> rdd1 = line.flatMap(new FlatMapFunction<String, String>() {
@Override
public Iterator<String> call(String s) throws Exception {
return Arrays.asList(s.split(" ")).iterator();
}
});
rdd1.foreachRDD(new VoidFunction<JavaRDD<String>>() {
@Override
public void call(JavaRDD<String> eachRdd) throws Exception {
SparkSession sqlc = SparkSession.builder().config(conf).getOrCreate();
JavaRDD<Row> rowdd = eachRdd.map(new Function<String, Row>() {
@Override
public Row call(String s) throws Exception {
return RowFactory.create(s);
}
});
List<StructField> fields = new ArrayList<StructField>();
fields.add(DataTypes.createStructField("word", DataTypes.StringType, false));
StructType schema = DataTypes.createStructType(fields);
Dataset<Row> dataFrame = sqlc.createDataFrame(rowdd, schema);
dataFrame.createOrReplaceTempView("myword");
sqlc.sql("select word,count(*) as total from myword group by word").show();
}
});
js.start();
js.awaitTermination();
}
}
集成sql 可以实现单词计数。
四、输入:接收器与输出------> 指定数据源
1、基本数据源
(1)文件流
与flume一样,就是监听某个目录是否发生变化,我们常用flume进行实现。
public class SparkText {
public static void main(String[] args) throws Exception {
Logger.getLogger("org.apache.spark").setLevel(Level.ERROR);
Logger.getLogger("org.eclipse.jetty.server").setLevel(Level.OFF);
SparkConf conf = new SparkConf().setAppName("MyNetworkWordCount")
// local[2] 表示:相当于有两个CPU的核数
.setMaster("local[2]");
JavaStreamingContext js = new JavaStreamingContext(conf, Durations.seconds(3));
// 接受变化的目录
JavaDStream<String> rdd1 = js.textFileStream("hdfs://192.168.92.111:9000/input");
JavaDStream<String> map = rdd1.map(new Function<String, String>() {
@Override
public String call(String s) throws Exception {
return s;
}
});
// 进行输出
map.print();
js.start();
js.awaitTermination();
}
}
(2)RDD队列流
Java编程没有这个接口,还请参考scala编程语言
(3)Socket流(WordCount)
前面已经展示
2、保存数据
foreachrdd,然后进行进行jdbc连接数据等存储。
五、接收Kafka的数据(放到Kafka中介绍)