Spark Streaming

概述

一般流式计算会与批量计算相比较。在流式计算模型中,输入时持续的,可以认为在时间上是无界的,也就意味着,永远拿不到全量数据去做计算。同时,计算结果是持续输出的,也即计算结果在时间上也是无界的。流式计算一般对实时性要求较高,同时一般是先定义目标计算,然后数据到来之后将计算逻辑应用于数据。同时为了提高计算效率,往往尽可能采用增量计算代替全量计算。批量处理模型中,一般先有全量数据集,然后定义计算逻辑,并将计算应用于全量数据。特点是全量计算,并且计算结果一次性全量输出。
在这里插入图片描述

批处理VS流处理区别
在这里插入图片描述
目前主流流处理框架:Kafka Streaming、Storm(JStrom)、Spark Streaming、Flink(BLink)

  • Kafka Streaming:是一套基于Kafka-Streaming库的一套流计算工具jar包,具有入门门槛低,简单容易集成等特点。
  • Apache Strom:一款纯粹的流计算引擎,能够达到每秒钟百万级别数据的低延迟处理框架。
  • Spark Streaming:是构建在Spark批处理之上一款流处理框架。与批处理不同的是,流处理计算的数据是无界数据流,输出也是持续的。Spark Streaming底层将Spark RDD Batch拆分成Macro RDD Batch实现类似流处理的功能。因此Spark Streaming在微观上依旧是批处理框架。

在这里插入图片描述

  • Flink DataStream:在实时性和应用性上以及性能都有很大的提升,是目前为止最火热的流计算引擎。
快速入门
  • 导入依赖
<dependency>
 <groupId>org.apache.spark</groupId>
  <artifactId>spark-core_2.11</artifactId>
  <version>2.4.5</version>
</dependency>

<dependency>
  <groupId>org.apache.spark</groupId>
  <artifactId>spark-streaming_2.11</artifactId>
  <version>2.4.5</version>
</dependency>
  • 编写Driver
import org.apache.spark.SparkConf
import org.apache.spark.streaming.{Seconds, StreamingContext}

object DStreamWordCount {
  def main(args: Array[String]): Unit = {
    //1.创建StreamContext
    val conf = new SparkConf().setAppName("wordcount").setMaster("local[*]")
    val ssc = new StreamingContext(conf,Seconds(1))
    ssc.sparkContext.setLogLevel("FATAL")

    //2.创建持续输入DStream
    val lineStream = ssc.socketTextStream("train",9999)

    //3.对lineStream做算子转换
    lineStream.flatMap(_.split(" "))
      .map((_,1))
      .reduceByKey(_+_)
      .print()//打印输出console

    //4.启动计算
    ssc.start()
    //5.等待关闭
    ssc.awaitTermination()
  }
}
  • 使用mvn package进行打包
<build>
        <plugins>
            <!--scala编译插件-->
            <plugin>
                <groupId>net.alchim31.maven</groupId>
                <artifactId>scala-maven-plugin</artifactId>
                <version>4.0.1</version>
                <executions>
                    <execution>
                        <id>scala-compile-first</id>
                        <phase>process-resources</phase>
                        <goals>
                            <goal>add-source</goal>
                            <goal>compile</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            <!--创建fatjar插件-->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-shade-plugin</artifactId>
                <version>2.4.3</version>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>shade</goal>
                        </goals>
                        <configuration>
                            <filters>
                                <filter>
                                    <artifact>*:*</artifact>
                                    <excludes>
                                        <exclude>META-INF/*.SF</exclude>
                                        <exclude>META-INF/*.DSA</exclude>
                                        <exclude>META-INF/*.RSA</exclude>
                                    </excludes>
                                </filter>
                            </filters>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
            <!--编译插件-->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.2</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                    <encoding>UTF-8</encoding>
                </configuration>
                <executions>
                    <execution>
                        <phase>compile</phase>
                        <goals>
                            <goal>compile</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
  • 下载nc组件
[root@train ~]# yum -y install nmap-ncat

  • 启动nc服务
[root@train ~]# nc -lk 9999
  • 启动服务
[root@train spark-2.4.5]# ./bin/spark-submit --master spark://train:7077 --name DStreamWordCount --deploy-mode client --class com.baizhi.sparkstreaming.DStreamWordCount --total-executor-cores 6 /root/spark-streaming-1.0-SNAPSHOT.jar
  • 用户可以访问webUI

在这里插入图片描述

Discretized Streams

Discretized Streams或DStream是Spark Streaming提供的基本抽象。它表示连续的数据流,可以是从源接受的输入数据流,也可以是通过转换输入流生成的已处理数据流。在内部,DStream由一系列连续的RDD表示,这是Spark对不可变分布式数据集的抽象。DStream中的每个RDD都包含来自特定时间间隔的数据,如下图所示。
在这里插入图片描述
应用于DStream的任何操作都转换为底层RDD上的操作。例如,在先前快速入门示例中,flatMap操作应用于行DStream中的每个RDD以生成单词DStream的RDD。

在这里插入图片描述
注意:通过对DStream底层运行机制的了解,在设计StreamingContext的时候要求设置的Seconds()间隔要略大于微批的计算时间。这样才可以有效的避免数据在Spark的内存中产生积压。

DStream&Receivers

每个输入DStream(file stream除外,稍后讨论)都与Receiver对象相关联,该对象从源接受数据并将其存储在Spark的内存中进行处理。Spark Streaming提供了两类内建的输入源,用于接受外围系统数据:

内建输入源
  • Basic sources-Spark中的StreamContext的API可以直接获取的数据源,例如:fileStream(读文件)、socket(测试)

socketTextStream

val lineStream = ssc.socketTextStream("train",9999)

File Streams

val lineStream = ssc.textFileStream("hdfs://train:9000/demo/words")

或者

val lines = ssc.fileStream("hdfs://train:9000/demo/word")

根据时间监测hdfs://train:9000/demo/word是否有新文件产生,如果有新文件产生,系统就自动读取该文件。并不会监控文件内容的变化。提示:在测试的时候,一定要注意同步时间。

  • Queue of RDDs(测试)
var queueRDDs = new mutable.Queue[RDD[String]]()

    //产生测试数据
    new Thread(new Runnable {
      override def run(): Unit = {
        while (true){
          queueRDDs += ssc.sparkContext.makeRDD(List("this is a demo","hello hello"))
          Thread.sleep(100)
        }
      }
    }).start()
    //2.创建持续输入DStream
    val lineStream = ssc.queueStream(queueRDDs)
高级数据源
  • Advanced sources:并不是Spark自带的源,例如:Kafka、Flume、Kinesis等,这些一般都需要第三方支持

Custom Receiver(自定义)

class CustomReceiver(values:List[String])
  extends Receiver[String](StorageLevel.MEMORY_ONLY) with Logging{
  override def onStart(): Unit = {
    new Thread(new Runnable {
      override def run(): Unit = receive()
    }).start()
  }

  override def onStop(): Unit = {}
  
  //接受来自外围系统的数据
  private def receive() {
    try {
      while (!isStarted()){
        Thread.sleep(500)
        val line = values(new Random().nextInt(values.length))
        store(line)
      }
      
      restart("Trying to restart again")
    } catch {
        case t: Throwable =>
        // restart if there is any other error
        restart("Error receiving data", t)
    }
  }
}

val arrays = List("this is a demo","good good","study come on")
    //2.创建持续输入DStream
    val lineStream = ssc.receiverStream(new CustomReceiver(arrays))

Spark对接Kafka

参考资料:http://spark.apache.org/docs/latest/streaming-kafka-0-10-integration.html

<dependency>
   <groupId>org.apache.spark</groupId>
   <artifactId>spark-streaming-kafka-0-10_2.11</artifactId>
   <version>2.4.5</version>
</dependency>
  • 准备
    开启zookeeper
    启动kafka
[root@train kafka_2.11-2.2.0]# ./bin/kafka-server-start.sh -daemon config/server.properties

创建一个topic01

[root@train kafka_2.11-2.2.0]# ./bin/kafka-topics.sh --bootstrap-server train:9092 --create --topic topic01 --partitions 30 --replication-factor 1
//1.创建StreamContext
    val conf = new SparkConf().setAppName("wordcount").setMaster("local[*]")
    val ssc = new StreamingContext(conf,Seconds(5))
    ssc.sparkContext.setLogLevel("FATAL")

    val kafkaParams = Map[String, Object](
      "bootstrap.servers" -> "train:9092", //kafka链接配置参数
      "key.deserializer" -> classOf[StringDeserializer], //消费者--key的反序列化
      "value.deserializer" -> classOf[StringDeserializer], //消费者--value的反序列化
      "group.id" -> "g1",//设置消费组
      "auto.offset.reset" -> "latest",//偏移量策略
      "enable.auto.commit" -> (false: java.lang.Boolean) //是否自动提交偏移量
    )

    val topics = Array("topic01")  //订阅topic

    val stream = KafkaUtils.createDirectStream[String, String](
      ssc, //StreamContext -- 流计算环境
      LocationStrategies.PreferConsistent, //位置策略配置
      ConsumerStrategies.Subscribe[String,String](topics,kafkaParams) //检查点重新启动之后也可以获得正确配置
    )

    stream.map(result=>result.value())
        .flatMap(_.split(" "))
        .map(t=>(t,1))
        .reduceByKey(_+_)
        .print()

    //4.启动计算
    ssc.start()
    //5.等待关闭
    ssc.awaitTermination()

生产者

[root@train kafka_2.11-2.2.0]# ./bin/kafka-console-producer.sh --broker-list train:9092 --topic topic01
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值