spark-17.sparkStreaming_2_DStream的输入

1.文件数据源

监控目录下新生成的文件,将文件内容读成一个RDD,这个文件最好是mv进来的。

import org.apache.spark.streaming._
val ssc = new StreamingContext(sc,Seconds(5))
val lineDStream = ssc.textFileStream("hdfs://master:9000/data")
val words = lineDStream.flatMap(_.split(" "))
val word2count = words.map((_,1))
val result = word2count.reduceByKey(_+_)
result.print
ssc.start

2.RDD队列

监控一个队列,实时获取队列中的新增的RDD。

package com.dendan.queueRDD

import org.apache.spark.SparkConf
import org.apache.spark.rdd.RDD
import org.apache.spark.streaming.{Seconds, StreamingContext}

import scala.collection.mutable

object QueueRDD {
  def main(args: Array[String]): Unit = {
    val conf = new SparkConf().setMaster("local[*]").setAppName("QueueRDD")
    val ssc = new StreamingContext(conf, Seconds(1))

    //创建RDD队列
    val rddQueue = new mutable.SynchronizedQueue[RDD[Int]]()
    //创建QueueInputDStream
    val inputStream = ssc.queueStream(rddQueue)
    //处理队列中的RDD数据
    val mappedStream = inputStream.map(x => (x % 10, 1))
    val reducedStream = mappedStream.reduceByKey(_ + _)
    //打印结果
    reducedStream.print()
    //自动计算
    ssc.start()
    for (i <- 1 to 30) {
      rddQueue += ssc.sparkContext.makeRDD(1 to 300, 10)
      Thread.sleep(2000)
      //通过程序停止StreamingContext的运行
      //      ssc.stop()
    }

    ssc.awaitTermination()
  }
}

3.自定义Receiver

继承Receiver抽象类,实现onStart和onStop方法。
使用:通过ssc.receiverStream传入一个自定义的Receiver实例。

package com.dendan

import java.io.{BufferedReader, InputStreamReader}
import java.net.Socket
import java.nio.charset.StandardCharsets

import org.apache.spark.SparkConf
import org.apache.spark.storage.StorageLevel
import org.apache.spark.streaming.{Seconds, StreamingContext}
import org.apache.spark.streaming.receiver.Receiver

/**
 * 自定义Receiver
 *
 * @param host
 * @param port
 */
class CustomReceiver(host: String, port: Int) extends Receiver[String](StorageLevel.MEMORY_ONLY) {
  /**
   * 程序启动的时候调用
   */
  override def onStart(): Unit = {
    val socket = new Socket(host, port)
    var inputText = ""
    val reader = new BufferedReader(new InputStreamReader(socket.getInputStream(), StandardCharsets.UTF_8))
    inputText = reader.readLine()
    while (!isStopped() && inputText != null) {
      //如果接收到了数据就保存
      store(inputText)
      inputText = reader.readLine()
    }
    //重新连接,重新执行onStart()方法
    restart("")
  }

  /**
   * 程序停止的时候调用
   */
  override def onStop(): Unit = {}
}

object CustomReceiver {
  def main(args: Array[String]): Unit = {
    //创建配置
    val sparkConf = new SparkConf().setAppName("streaming").setMaster("local[*]")
    //创建streamingContext
    val ssc = new StreamingContext(sparkConf, Seconds(5))

    // 业务逻辑:从socket接受数据
    val lineDStream = ssc.receiverStream(new CustomReceiver("master", 9999))

    val wordStream = lineDStream.flatMap(_.split(" "))
    val word2CountDStream = wordStream.map((_, 1))
    val resultDStream = word2CountDStream.reduceByKey(_ + _)
    resultDStream.print()

    //启动ssc
    ssc.start()
    ssc.awaitTermination()
  }
}

4.对接Kafka

在这里插入图片描述
连接kafka的两种方式:

  • 通过kafka的高级API来获取数据,这种情况是spark比较老的版本支持的情况,receiver运行再某一个executor中,性能比较低,会存在丢失数据的风险,spark为了保存数据处理,提供了WAL(预写日志)的方式来保证。
  • 通过kafka的低级API来获取数据,这种情况是spark比较新的版本提供的,性能比较高,receiver运行在Driver端,由于使用了低级API,需要业务人员手动维护offset,需要保证业务代码的事务性。

连接池技术:
主要通过apache提供的commons-tools来实现在sparkstreaming写入到kafka的时候,从连接池中获取kafka连接。
连接的时候使用如下jar包:

<!-- streaming 与 kafka 连接-->
<dependency>
    <groupId>org.apache.spark</groupId>
    <artifactId>spark-streaming-kafka_2.11</artifactId>
    <version>1.6.3</version>
</dependency>
<!-- kafka连接池技术 -->
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-pool2</artifactId>
    <version>2.5.0</version>
</dependency>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值