spark Spark Streaming、kafka数据源Direct模式、 自定义数据源

前言

  Spark Streaming广泛运用于流式数据的处理(准实时、微批次的数据处理框架)。使用离散化流(discretized stream)作为抽象表示,即DStream。DStream 是随时间推移而收到的数据的序列。在内部,每个时间区间收到的数据都作为 RDD 存在,而DStream是由这些RDD所组成的序列。典型的流式数据输入源就是kafka

本文使用的spark版本3.0.0


1. Kafka数据源

1.1 选型

  ReceiverAPI:需要一个专门的Executor去接收数据,然后发送给其他的Executor做计算。由于接收数据的Executor和计算的Executor速度会有所不同,特别在接收数据的Executor速度大于计算的Executor速度,会导致计算数据的节点内存溢出。早期版本中提供此方式,当前版本不适用
  DirectAPI:是由计算的Executor来主动消费Kafka的数据,速度由自身控制。

1.2 Kafka 0-10 Direct模式

依赖:

    <dependency>
      <groupId>org.apache.spark</groupId>
      <artifactId>spark-core_2.12</artifactId>
      <version>3.0.0</version>
    </dependency>
    <dependency>
      <groupId>org.apache.spark</groupId>
      <artifactId>spark-streaming_2.12</artifactId>
      <version>3.0.0</version>
    </dependency>
    <dependency>
      <groupId>org.apache.spark</groupId>
      <artifactId>spark-sql_2.12</artifactId>
      <version>3.0.0</version>
    </dependency>
    <dependency>
      <groupId>org.apache.spark</groupId>
      <artifactId>spark-streaming-kafka-0-10_2.12</artifactId>
      <version>3.0.0</version>
    </dependency>
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-core</artifactId>
      <version>2.10.1</version>
    </dependency>

代码:

import org.apache.kafka.clients.consumer.{ConsumerConfig, ConsumerRecord}
import org.apache.spark.SparkConf
import org.apache.spark.streaming.dstream.{DStream, InputDStream}
import org.apache.spark.streaming.kafka010.{ConsumerStrategies, KafkaUtils, LocationStrategies}
import org.apache.spark.streaming.{Seconds, StreamingContext}



object T5{
  def main(args: Array[String]): Unit = {
    val streamingConf = new SparkConf().setMaster("local[*]").setAppName("streaming")
    val ssc = new StreamingContext(streamingConf, Seconds(3))

    //定义Kafka参数
    val kafkaPara: Map[String, Object] = Map[String, Object](
      ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG -> "192.168.42.102:9092,192.168.42.103:9092,192.168.42.104:9092",
      ConsumerConfig.GROUP_ID_CONFIG -> "cz",
      "key.deserializer" -> "org.apache.kafka.common.serialization.StringDeserializer",
      "value.deserializer" -> "org.apache.kafka.common.serialization.StringDeserializer"
    )

    //读取Kafka数据创建DStream
    val kafkaDStream: InputDStream[ConsumerRecord[String, String]] = KafkaUtils.createDirectStream[String, String](ssc,
      LocationStrategies.PreferConsistent,
      ConsumerStrategies.Subscribe[String, String](Set("di18600"), kafkaPara))

    //将每条消息的KV取出
    val valueDStream: DStream[String] = kafkaDStream.map(record => record.value())

    //计算WordCount
    valueDStream.flatMap(_.split(" "))
      .map((_, 1))
      .reduceByKey(_ + _)
      .print()

    ssc.start()
    ssc.awaitTermination()
  }
}

kafka生产者发送消息:

kafka-console-producer.sh --broker-list  192.168.42.102:9092,192.168.42.103:9092,192.168.42.104:9092 --topic di18600

在这里插入图片描述


2. 自定义数据源

  需要继承Receiver,并实现onStart、onStop方法来自定义数据源采集
onStart: This method is called by the system when the receiver is started. This function must initialize all resources (threads, buffers, etc.) necessary for receiving data.This function must be non-blocking, so receiving the data must occur on a different
thread. Received data can be stored with Spark by calling store(data).(重点在于初始化源,调用store(data)方法使spark接收数据)

onStop:This method is called by the system when the receiver is stopped. All resources (threads, buffers, etc.) set up in onStart() must be cleaned up in this method.(重点在于清理onStart()中的线程、缓存)

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

import scala.util.Random

object T4 {
  def main(args: Array[String]): Unit = {
    val streamingConf = new SparkConf().setMaster("local[*]").setAppName("streaming")
    val ssc = new StreamingContext(streamingConf, Seconds(3))
    val ds = ssc.receiverStream(new MyReceiver())
    ds.print()

    ssc.start()
    ssc.awaitTermination()
  }
}

class MyReceiver extends Receiver[String](StorageLevel.MEMORY_ONLY) {
  private var flag = true

  override def onStart(): Unit = {
    new Thread(() => {
      while (flag) {
        val i = new Random().nextInt(100)
        store("" + i)
        Thread.sleep(500)
      }
    }).start()
  }

  override def onStop(): Unit = {
    flag = false
  }
}

### 配置 Spark Streaming 使用 Kafka 数据源Spark Streaming 中配置 Kafka 作为数据源涉及多个方面,包括环境准备、依赖设置以及具体的编程接口调用。 #### 环境与依赖设置 对于开发环境而言,确保使用的 Scala 和 Spark 版本兼容于所选用的 Kafka 版本非常重要。例如,在构建项目时可以采用如下组合: - Scala 版本:2.11.12 - Spark Streaming 版本:2.2.1 或更高版本 - Kafka Broker 版本:0.8.2.1 及以上[^4] 这些版本的选择基于它们之间的良好兼容性和稳定性考虑。 #### 编程接口调用 当一切就绪之后,可以通过 `KafkaUtils` 类来创建一个来自 Kafka 的输入 DStream。下面是一个简单的例子展示如何实现这一点: ```scala import org.apache.spark.streaming.kafka._ val kafkaStream = KafkaUtils.createStream( streamingContext, "localhost:2181", // Zookeeper Quorum 地址 "test-consumer-group", // 消费者组 ID Map("topic-name" -> 1) // 主题名称及其对应的分区数 ) ``` 上述代码片段展示了通过指定 ZooKeeper 连接地址、消费者组ID以及主题名和消费线程数量来初始化一个 Kafka 输入流的方式[^1]。 另外值得注意的是,Spark Streaming 支持多种不同类型的 Kafka 接入方式,其中 Direct 方式提供了更高效的数据读取机制,并且不需要依赖 ZooKeeper 来跟踪偏移量。这种方式适用于 Kafka 0.10及以上版本[^3]。 #### 实现细节补充说明 除了基本的连接参数外,还可以根据实际需求调整其他选项,比如批量拉取消息的数量上限等。这有助于优化性能并满足特定应用场景下的要求。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

但行益事莫问前程

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值