环境
  虚拟机:VMware 10
  Linux版本:CentOS-6.5-x86_64
  客户端:Xshell4
  FTP:Xftp4
  jdk1.8
  scala-2.10.4(依赖jdk1.8)
  spark-1.6

一、SparkStreaming简介
SparkStreaming是流式处理框架,是Spark API的扩展,支持可扩展、高吞吐量、容错的实时数据流处理,实时数据的来源可以是:Kafka, Flume, Twitter, ZeroMQ或者TCP sockets,并且可以使用高级功能的复杂算子来处理流数据。例如:map,reduce,join,window 。最终,处理后的数据可以存放在文件系统,数据库等,方便实时展现。

二、SparkStreaming与Storm的区别

1、Storm是纯实时的流式处理框架(扶梯),SparkStreaming是准实时的处理框架(微批处理-电梯)。因为微批处理,SparkStreaming的吞吐量比Storm要高。
2、Storm 的事务机制要比SparkStreaming的要完善。
3、Storm支持动态资源调度。(spark1.2开始和之后也支持)
4、SparkStreaming擅长复杂的业务处理,Storm不擅长复杂的业务处理,擅长简单的汇总型计算。

整体而言速度比storm要快,目前新项目一般选择SparkStreaming多一些,具体选择还要看应用场景

三、SparkStreaming初始

SparkStreaming示例代码:

package com.wjy.ss;

import java.util.Arrays;

import org.apache.spark.SparkConf;
import org.apache.spark.api.java.JavaSparkContext;
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; public class SparkStreamingTest { public static void main(String[] args) {
SparkConf conf = new SparkConf().setMaster("local[2]").setAppName("SparkStreamingTest");
JavaSparkContext sc = new JavaSparkContext(conf);
sc.setLogLevel("WARN");//设置日志级别 不打印一堆无用的日志 //创建JavaStreamingContext 批次间隔为5秒
JavaStreamingContext jsc = new JavaStreamingContext(sc,Durations.seconds(5));
//监听134.32.123.101 9999端口 获取文本socket流
JavaReceiverInputDStream<String> socketTextStream = jsc.socketTextStream("134.32.123.101", 9999);
//接下来进行wordcount
JavaDStream<String> words = socketTextStream.flatMap(new FlatMapFunction<String, String>() {
private static final long serialVersionUID = 1L; @Override
public Iterable<String> call(String line) throws Exception {
return Arrays.asList(line.split(" "));
}
});
JavaPairDStream<String, Integer> pairWords = words.mapToPair(new PairFunction<String, String, Integer>() {
private static final long serialVersionUID = 1L;
@Override
public Tuple2<String, Integer> call(String word) throws Exception {
return new Tuple2<String, Integer>(word,1);
}
});
JavaPairDStream<String, Integer> reduceByKey = pairWords.reduceByKey(new Function2<Integer, Integer, Integer>() {
private static final long serialVersionUID = 1L;
@Override
public Integer call(Integer v1, Integer v2) throws Exception {
return v1+v2;
}
}); //print()可以加参数 默认打印在此 DStream 中生成的每个 RDD 的前十个元素。加参数print(num)前num个元素
reduceByKey.print(); /*
* -------------------------------------------
Time: 1555921465000 ms
------------------------------------------- 19/04/22 17:01:38 WARN BlockManager: Block input-0-1555923698400 replicated to only 0 peer(s) instead of 1 peers
19/04/22 17:01:38 WARN BlockManager: Block input-0-1555923698600 replicated to only 0 peer(s) instead of 1 peers
-------------------------------------------
Time: 1555921470000 ms
-------------------------------------------
(ee,1)
(aa,1)
(gg,1)
(dd,1)
(hh,1)
(wjy,1)
(kk,1)
(jj,1)
(ii,1)
(hello,14)
... -------------------------------------------
Time: 1555921475000 ms
-------------------------------------------
(ll,1)
(hello,1)
*/
//启动
jsc.start();
//监控:等待中断
jsc.awaitTermination();
//这里stop不会执行 我们在实际应用中根据触发条件执行 比如监控某个文件删除后就执行停止动作
jsc.stop();
}
}

以上使用print用来展示查看JavaPairDStream中数据,这是本机测试,实际应用是不会使用print的,这里需要我们通过foreachRDD来进行下一步的逻辑处理和触发:

package com.wjy.ss;

import java.util.Arrays;

import org.apache.spark.SparkConf;
import org.apache.spark.SparkContext;
import org.apache.spark.api.java.JavaPairRDD;
import org.apache.spark.api.java.JavaSparkContext;
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.api.java.function.VoidFunction;
import org.apache.spark.broadcast.Broadcast;
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; public class SparkStreamingTest { public static void main(String[] args) {
SparkConf conf = new SparkConf().setMaster("local[2]").setAppName("SparkStreamingTest");
JavaSparkContext sc = new JavaSparkContext(conf);
sc.setLogLevel("WARN");//设置日志级别 不打印一堆无用的日志 //创建JavaStreamingContext 批次间隔为5秒
JavaStreamingContext jsc = new JavaStreamingContext(sc,Durations.seconds(5));
//监听134.32.123.101 9999端口 获取文本socket流
JavaReceiverInputDStream<String> socketTextStream = jsc.socketTextStream("134.32.123.101", 9999);
//接下来进行wordcount
JavaDStream<String> words = socketTextStream.flatMap(new FlatMapFunction<String, String>() {
private static final long serialVersionUID = 1L; @Override
public Iterable<String> call(String line) throws Exception {
return Arrays.asList(line.split(" "));
}
});
JavaPairDStream<String, Integer> pairWords = words.mapToPair(new PairFunction<String, String, Integer>() {
private static final long serialVersionUID = 1L;
@Override
public Tuple2<String, Integer> call(String word) throws Exception {
return new Tuple2<String, Integer>(word,1);
}
});
JavaPairDStream<String, Integer> reduceByKey = pairWords.reduceByKey(new Function2<Integer, Integer, Integer>() {
private static final long serialVersionUID = 1L;
@Override
public Integer call(Integer v1, Integer v2) throws Exception {
return v1+v2;
}
}); //print()默认打印在此 DStream 中生成的每个RDD 的前十个元素。加参数前num个元素
//reduceByKey.print(); /**
* foreachRDD 可以拿到DStream中的RDD ,对拿到的RDD可以使用RDD的transformation类算子转换,要对拿到的RDD使用action算子触发执行,否则,foreachRDD不会执行。
* foreachRDD 中call方法内,拿到的RDD的算子外,代码是在Driver端执行。可以使用这个算子实现动态改变广播变量。
*
*/
reduceByKey.foreachRDD(new VoidFunction<JavaPairRDD<String,Integer>>() {
private static final long serialVersionUID = 1L;
@Override
public void call(JavaPairRDD<String, Integer> rdd)
throws Exception
{
//Driver端执行
System.out.println("Driver .......");
//获取SparkContext
SparkContext context = rdd.context();
//创建JavaSparkContext
JavaSparkContext javaSparkContext = new JavaSparkContext(context);
//广播变量 这里可以读取一个文件 文件内容可变 就达到了动态改变广播变量的目的
Broadcast<String> broadcast = javaSparkContext.broadcast("hello wjy");
String value = broadcast.value();
System.out.println(value);
JavaPairRDD<String, Integer> mapToPair = rdd.mapToPair(new PairFunction<Tuple2<String,Integer>, String,Integer>() {
private static final long serialVersionUID = 1L;
@Override
public Tuple2<String, Integer> call(Tuple2<String, Integer> tuple) throws Exception {
System.out.println("Executor .......");
return new Tuple2<String, Integer>(tuple._1+"~",tuple._2);
}
});
mapToPair.foreach(new VoidFunction<Tuple2<String,Integer>>() {
private static final long serialVersionUID = 1L; @Override
public void call(Tuple2<String, Integer> arg0)
throws Exception {
System.out.println(arg0);
}
});
}
}); /*
*
* 执行结果:
Driver .......
hello wjy
Driver .......
hello wjy
19/04/22 17:26:46 WARN BlockManager: Block input-0-1555925206600 replicated to only 0 peer(s) instead of 1 peers
19/04/22 17:26:47 WARN BlockManager: Block input-0-1555925206800 replicated to only 0 peer(s) instead of 1 peers
19/04/22 17:26:47 WARN BlockManager: Block input-0-1555925207200 replicated to only 0 peer(s) instead of 1 peers
Driver .......
hello wjy
Executor .......
(ee~,1)
Executor .......
(aa~,1)
Executor .......
(ll~,1)
Executor .......
(gg~,1)
Executor .......
(dd~,1)
Executor .......
(hh~,1)
Executor .......
(wjy~,1)
Executor .......
(kk~,1)
Executor .......
(jj~,1)
Executor .......
(ii~,1)
Executor .......
(hello~,31)
Executor .......
(tt~,1)
Executor .......
(ff~,1)
Executor .......
(bb~,1)
Executor .......
(world~,17)
Executor .......
(cc~,1)
Driver .......
hello wjy
*/ //启动
jsc.start();
//监控:等待中断
jsc.awaitTermination();
//这里stop不会执行 我们在实际应用中根据触发条件执行 比如监控某个文件删除后就执行停止动作
jsc.stop();
}
}

代码注意事项:
(2.1)启动socket server 服务器:nc –lk 9999

[root@PCS101 ~]# nc -lk
hello world
hello wjy
hello tt
hello aa
hello bb
hello cc
hello dd
hello ee
hello ff
hello gg
hello hh
hello ii
hello jj
hello kk
hello ll

Linux中nc命令是一个功能强大的网络工具,全称是netcat。
语法:nc
-l 开启 监听模式,用于指定nc将处于监听模式。通常 这样代表着为一个 服务等待客户端来链接指定的端口。
-p<通信端口> 设置本地主机使用的通信端口。有可能会关闭
-k<通信端口>强制 nc 待命链接.当客户端从服务端断开连接后,过一段时间服务端也会停止监听。 但通过选项 -k 我们可以强制服务器保持连接并继续监听端口。

(2.2)receiver模式下接受数据,local的模拟线程必须大于等于2,一个线程用来receiver用来接受数据,另一个线程用来执行job。
(2.3)Durations时间设置就是我们能接收的延迟度。这个需要根据集群的资源情况以及任务的执行情况来调节。
(2.4)创建JavaStreamingContext有两种方式(SparkConf,SparkContext)
  所有的代码逻辑完成后要有一个output operation类算子。
  JavaStreamingContext.start() Streaming框架启动后不能再次添加业务逻辑。
  JavaStreamingContext.stop() 无参的stop方法将SparkContext一同关闭,stop(false),不会关闭SparkContext。
  JavaStreamingContext.stop()停止之后不能再调用start。

四、Driver HA(Standalone或者Mesos)

因为SparkStreaming是7*24小时运行,Driver只是一个简单的进程,有可能挂掉,所以实现Driver的HA就有必要(如果使用的Client模式就无法实现Driver HA ,这里针对的是cluster模式)。Yarn平台cluster模式提交任务,AM(AplicationMaster)相当于Driver,如果挂掉会自动启动AM。这里所说的DriverHA针对的是Spark standalone和Mesos资源调度的情况下。实现Driver的高可用有两个步骤:
第一:提交任务层面,在提交任务的时候加上选项 --supervise,当Driver挂掉的时候会自动重启Driver。
第二:代码层面,使用JavaStreamingContext.getOrCreate(checkpoint路径,JavaStreamingContextFactory)
Driver中元数据包括:
  (1)创建应用程序的配置信息。
  (2)DStream的操作逻辑。
  (3)job中没有完成的批次数据,也就是job的执行进度。

package com.wjy.ss;

import java.util.Arrays;

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.JavaStreamingContext;
import org.apache.spark.streaming.api.java.JavaStreamingContextFactory; import scala.Tuple2; /**
*
* Spark standalone or Mesos with cluster deploy mode only:
* 在提交application的时候 添加 --supervise 选项 如果Driver挂掉 会自动启动一个Driver
*
*/
public class SparkStreamingOnHDFS { public static void main(String[] args) {
SparkConf conf = new SparkConf().setMaster("local").setAppName("SparkStreamingOnHDFS");
//checkpoint目录可以设置为HDFS目录 也可以是本地目录
//final String checkpointDirectory = "hdfs://node1:9000/spark/SparkStreaming/CheckPoint2019";
final String checkpointDirectory = "./checkpoint"; //JavaStreamingContext工厂类 需要重写create方法
JavaStreamingContextFactory jscfactory = new JavaStreamingContextFactory(){ /**
* 只有首次创建JavaStreamingContext 才会走这里
*/
@Override
public JavaStreamingContext create() {
System.out.println("Creating new context");
JavaStreamingContext jsc = new JavaStreamingContext(conf,Durations.seconds(5));
jsc.sparkContext().setLogLevel("WARN"); /**
* checkpoint 保存:
* 1.配置信息
* 2.DStream操作逻辑
* 3.job的执行进度
* 4.offset
*/
jsc.checkpoint(checkpointDirectory); /**
* 监控的是HDFS上的一个目录,监控文件数量的变化 文件内容如果追加监控不到。
* 只监控文件夹下新增的文件,减少的文件时监控不到的,文件的内容有改动也监控不到。
*/
//JavaDStream<String> lines = jsc.textFileStream("hdfs://node1:9000/spark/sparkstreaming");
JavaDStream<String> lines = jsc.textFileStream("./data"); JavaPairDStream<String, Integer> counts = lines.flatMap(new FlatMapFunction<String, String>() {
private static final long serialVersionUID = 1L; @Override
public Iterable<String> call(String line) throws Exception {
return Arrays.asList(line.split(" "));
}
}).mapToPair(new PairFunction<String, String, Integer>() {
private static final long serialVersionUID = 1L; @Override
public Tuple2<String, Integer> call(String word) throws Exception
{
return new Tuple2<String, Integer>(word.trim(),1);
}
}).reduceByKey(new Function2<Integer, Integer, Integer>() {
private static final long serialVersionUID = 1L; @Override
public Integer call(Integer v1, Integer v2) throws Exception {
return v1+v2;
}
}); counts.print(); return jsc;
} }; /**
* 获取JavaStreamingContext 先去指定的checkpoint目录中去恢复JavaStreamingContext
* 如果恢复不到,通过factory创建
*/
JavaStreamingContext jsc = JavaStreamingContext.getOrCreate(checkpointDirectory, jscfactory);
jsc.start();
jsc.awaitTermination();
jsc.close();//jsc.stop();
} }

参考:

Spark

【SparkStreaming学习之一】 SparkStreaming初识的更多相关文章

  1. 大数据学习day32-----spark12-----1. sparkstreaming(1.1简介,1.2 sparkstreaming入门程序(统计单词个数,updateStageByKey的用法,1.3 SparkStreaming整合Kafka,1.4 SparkStreaming获取KafkaRDD的偏移量,并将偏移量写入kafka中)

    1. Spark Streaming 1.1 简介(来源:spark官网介绍) Spark Streaming是Spark Core API的扩展,其是支持可伸缩.高吞吐量.容错的实时数据流处理.Sp ...

  2. 二、Android学习第二天——初识Activity(转)

    (转自:http://wenku.baidu.com/view/af39b3164431b90d6c85c72f.html) 一. Android学习第二天——初识Activity 昨天程序搭建成功以 ...

  3. Java学习-027-JSON 之一 -- 初识

    通常,我们在生活中使用的应用产品(无论是 Web应用还是 App 应用),又或者我们平常的信息交流,均无可避免的存在着信息交互,在信息交互的过程中就有着信息载体的存在.那么,在我们熟知的网络应用产品中 ...

  4. WPF学习之路初识

    WPF学习之路初识   WPF 介绍 .NET Framework 4 .NET Framework 3.5 .NET Framework 3.0 Windows Presentation Found ...

  5. Storm学习笔记 - Storm初识

    Storm学习笔记 - Storm初识 1. Strom是什么? Storm是一个开源免费的分布式计算框架,可以实时处理大量的数据流. 2. Storm的特点 高性能,低延迟. 分布式:可解决数据量大 ...

  6. [转]git学习------>git-rev-parse命令初识

    git学习------>git-rev-parse命令初识 2017年06月13日 10:04:13 阅读数:2172 一.准备工作 第一步:在d盘git test目录下,新建工作区根目录dem ...

  7. Spring 学习记录8 初识XmlWebApplicationContext(2)

    主题 接上文Spring 学习记录7 初识XmlWebApplicationContext refresh方法 refresh方法是定义在父类AbstractApplicationContext中的. ...

  8. LevelDB学习笔记 (1):初识LevelDB

    LevelDB学习笔记 (1):初识LevelDB 1. 写在前面 1.1 什么是levelDB LevelDB就是一个由Google开源的高效的单机Key/Value存储系统,该存储系统提供了Key ...

  9. 【SparkStreaming学习之四】 SparkStreaming+kafka管理消费offset

    环境 虚拟机:VMware 10 Linux版本:CentOS-6.5-x86_64 客户端:Xshell4 FTP:Xftp4 jdk1.8 scala-2.10.4(依赖jdk1.8) spark ...

随机推荐

  1. ElasticSearch + Canal 开发千万级的实时搜索系统

    公司是做社交相关产品的,社交类产品对搜索功能需求要求就比较高,需要根据用户城市.用户ID昵称等进行搜索. 项目原先的搜索接口采用SQL查询的方式实现,数据库表采用了按城市分表的方式.但随着业务的发展, ...

  2. Java 中关于基本数字类型的注意事项

    局部变量需初始化才能访问 public void test() { float n; n = n + 1; } 窄化导致自增异常 short i = 3; i += 1; // 不提升 short i ...

  3. centos7查看网卡UUID

    https://blog.csdn.net/kepa520/article/details/50222049 查看网卡UUID nmcli con show 查看mac地址 nmcli device ...

  4. 阿里云 windows 2008 使用Thinkphp5 captcha验证码不显示问题

    第一次使用Thinkphp5在阿里云上面运行,后台验证码竟然显示不出来!有种要吐血的感觉...找了半天,终于找到类似解决办法 thinkphp,onethink和thinkox中验证码不显示的解决方法 ...

  5. C语言企业级的需要学习的知识

    建立正确程序运行内存的布局图(印象图) 内存四区模型图: 函数调用模型图: 数据类型的本质:固定大小内存块的别名 对于数组变量b[10]; b+1,与&b+1结果不一样: b代表的是数组首元素 ...

  6. Jumpserver之安装在CentOS主机步骤

    环境 系统CentOS7.5 IP:172.16.90.248 关闭防火墙设置selinux systemctl stop firewalld setenforce 0 sed -i "s/ ...

  7. 电子产品使用感受之-- AirPods + Apple Watch S4 = Smart iPod ?

  8. python opencv 读取USB摄像头的像素问题

    问题描述 每次调用capture读取video的时候,还回的像素都是640x480,不管是笔记本的摄像头还是USB摄像头,明明我的摄像头是支持130万读取的功能的呀. 问题分析 一番查找,关于用ope ...

  9. 新装的centos怎样显示中文界面

    默认的显示英文界面,即使各种配置中都选择的chinese也没用,默认显示的还是英文. 要在终端输入 vim ~/.bashrc 编辑本用户配置文件 打开后最后一行加入 export LANG=&quo ...

  10. querySelector与getElementBy的区别

    1,querySelector() 方法返回匹配指定 CSS 选择器元素的第一个子元素 . 该方法只返回匹配指定选择器的第一个元素.如果要返回所有匹配元素,需要使用 querySelectorAll( ...