scala版本的sparkstreaming基于Direct连接kafka0.8旧版本开发详解


文章目录

  • scala版本的sparkstreaming基于Direct连接kafka0.8旧版本开发详解
  • 1:本次/基于Direct的方式读取kafka数据
  • 1.1Direct方式讲解
  • 1.1.1**特点**
  • 1.1.2:这种方式有如下优点:
  • 1.2进行消息生产
  • 2:代码开发
  • 2.1:偏移量管理:checkpoint
  • 2.2:完整demo
  • 结果运行
  • 2.3:checkpoint+kafka自己管理


1:本次/基于Direct的方式读取kafka数据

1.1Direct方式讲解

/**
   * 摒弃了高阶的kafkaConsumerAPI直接从kafkaBrokers获取信息,可以保证每条消息只被消费一次
   * 特点:
   * - No receivers:没有receivers接收器,直接从kafka拉取数据
   * - Offsets:不用zookeeper存储offsets,偏移量是通过stream自己跟踪记录的,可以通过HasOffsetRanges获取offset
   * - Failure Recovery故障恢复:需要开启sparkContext的checkpoint功能
   * - End-to-end semantics最终一致性:保证消息被消费且只消费一次
   * @return DStream of (Kafka message key, Kafka message value)
1.1.1特点
Direct的方式是会直接操作kafka底层的元数据信息,这样如果计算失败了,可以把数据重新读一下,重新处理。即数据一定会被处理。拉数据,是RDD在执行的时候直接去拉数据。
由于直接操作的是kafka,kafka就相当于你底层的文件系统。这个时候能保证严格的事务一致性,即一定会被处理,而且只会被处理一次。而Receiver的方式则不能保证,因为Receiver和ZK中的数据可能不同步,Spark Streaming可能会重复消费数据。而Direct api直接是操作kafka的,spark streaming自己负责追踪消费这个数据的偏移量或者offset,并且自己保存到checkpoint,所以它的数据一定是同步的,一定不会被重复。
底层是直接读数据,没有所谓的Receiver,直接是周期性(Batch Intervel)的查询kafka,处理数据的时候,我们会使用基于kafka原生的Consumer api来获取kafka中特定范围(offset范围)中的数据,这个时候,Direct Api访问kafka带来的一个显而易见的性能上的好处就是,如果你要读取多个partition,Spark也会创建RDD的partition,这个时候RDD的partition和kafka的partition是一致的。所以增加kafka中的topic的partition数量可以提高并行度。
偏移量:默认从最新偏移量(largest)开始消费。如果设置了auto.offset.reset参数值为smallest将从最小偏移处开始消费。
**```
**API介绍****
/*
1:createDirectStream的api详细介绍:
   参数列表3个:
       1.1: ssc:sparkstreaming对象
       1.2: kafkaParams:map类型的kafka配置列表
       1.3:topics
   类型限制

     * @param topics Names of the topics to consume
     * @tparam K: type of Kafka message key:kafka消息的keyd的类型
     * @tparam V :type of Kafka message value
     * @tparam KD :type of Kafka message key decoder
     * @tparam VD :type of Kafka message value decoder
     * @return DStream of (Kafka message key, Kafka message value)
     *         decoder:编解码器,将字节数组byte转换为字符流进行解码
### 1:开发准备
1:集群正常启动
2:创建kafka的topic
kafka-console-producer.sh \
	--broker-list hdp01:9092,hdp02:9092,hdp03:9092 \
	--topic spark01
1.1.2:这种方式有如下优点:
1、简化并行读取:如果要读取多个partition,不需要创建多个输入DStream然后对它们进行union操作。Spark会创建跟Kafka partition一样多的RDD partition,并且会并行从Kafka中读取数据。所以在Kafka partition和RDD partition之间,有一个一对一的映射关系。

2、高性能:如果要保证零数据丢失,在基于receiver的方式中,需要开启WAL机制。这种方式其实效率低下,因为数据实际上被复制了两份,Kafka自己本身就有高可靠的机制,会对数据复制一份,而这里又会复制一份到WAL中。而基于direct的方式,不依赖Receiver,不需要开启WAL机制,只要Kafka中作了数据的复制,那么就可以通过Kafka的副本进行恢复。

3、一次且仅一次的事务机制:

基于receiver的方式,是使用Kafka的高阶API来在ZooKeeper中保存消费过的offset的。这是消费Kafka数据的传统方式。这种方式配合着WAL机制可以保证数据零丢失的高可靠性,但是却无法保证数据被处理一次且仅一次,可能会处理两次。因为Spark和ZooKeeper之间可能是不同步的。

4、降低资源。
Direct不需要Receivers,其申请的Executors全部参与到计算任务中;而Receiver-based则需要专门的Receivers来读取Kafka数据且不参与计算。因此相同的资源申请,Direct 能够支持更大的业务。

5、降低内存。
Receiver-based的Receiver与其他Exectuor是异步的,并持续不断接收数据,对于小业务量的场景还好,如果遇到大业务量时,需要提高Receiver的内存,但是参与计算的Executor并无需那么多的内存。而Direct 因为没有Receiver,而是在计算时读取数据,然后直接计算,所以对内存的要求很低。实际应用中我们可以把原先的10G降至现在的2-4G左右。

6、鲁棒性更好。
Receiver-based方法需要Receivers来异步持续不断的读取数据,因此遇到网络、存储负载等因素,导致实时任务出现堆积,但Receivers却还在持续读取数据,此种情况很容易导致计算崩溃。Direct 则没有这种顾虑,其Driver在触发batch 计算任务时,才会读取数据并计算。队列出现堆积并不会引起程序的失败。

基于direct的方式,使用kafka的简单api,Spark Streaming自己就负责追踪消费的offset,并保存在checkpoint中。Spark自己一定是同步的,因此可以保证数据是消费一次且仅消费一次

1.2进行消息生产

spark 连接工具_大数据

2:代码开发

2.1:偏移量管理:checkpoint

偏移量管理有三种方式,本次采checkpoint
————————————————————————————

2.2:完整demo

代码逻辑必须写在createSSC方法中

object _04StreamingGetOrCreate {
//利用checkpoint本地磁盘进行offset偏移量管理,数据存放
  //可本地可hdfs
  val checkpointPath = "file:///C:\\Users\\Administrator.SC-201905261418\\Desktop\\bigdata开发实例\\checkpoint"

  def main(args: Array[String]): Unit = {
    val context = StreamingContext.getOrCreate(checkpointPath, createSSC)
    context.start()
    context.awaitTermination()
  }
  
//代码逻辑必须写在createSSC中
  def createSSC(): StreamingContext = {
    val conf = new SparkConf().setAppName("local test checkpoint").setMaster("local[2]")
    val ssc = new StreamingContext(conf, Seconds(10))
    val kafkaParams = Map[String, String](
      "bootstrap.servers" -> "hdp01:9092,hdp02:9092,hdp03:9092",
      "group.id" -> "comsumer1",
      //smallest从偏移量最早的位置开始读取,开发多用此配置
      //本次demo即保存在checkpoint中
      "auto.offset.reset" -> "smallest",
      "enable.auto.commit" -> "false",
      //此时我们相当于在消费数据,指定反序列数据的方式,实现org.apache.kafka.common.serialization.Deserializer的类
      "key.deserializer" -> "org.apache.kafka.common.serialization.StringDeserializer",
      "value.deserializer" -> "org.apache.kafka.common.serialization.StringDeserializer")
    val topic = Set("spark01")
    ssc.checkpoint(checkpointPath)
    //dstreams是一个rdd的集合rdds
    val dstreams = KafkaUtils.createDirectStream[String, String, StringDecoder, StringDecoder](ssc, kafkaParams, topic)
   //配置持久定时写到checkpoint,参数建议:5-10倍的batch
    dstreams.checkpoint(Seconds(100))
   dstreams.print()
   //获取到数据lines
 val lines = dstreams.map(_._2)
    lines.print()
    val words = lines.flatMap(_.split(" "))
    val wordCounts = words.map(x => (x, 1L)).reduceByKey(_ + _)
    wordCounts.print()
    println("start rdd")
    ssc
  }
}

结果运行

spark 连接工具_spark 连接工具_02

2.3:checkpoint+kafka自己管理

在这里插入代码片