Spark學習(拾貳)- Spark Streaming整合Kafka


官方文檔:
http://spark.apache.org/docs/2.2.0/streaming-kafka-integration.html

Spark Streaming整合Kafka的版本選擇詳解

在spark2.2之前建議選擇spark-streaming-kafka-0-8版本;雖然spark-streaming-kafka-0-10是優化更好的;但是2.2之前的相關api還不穩定
在這裏插入圖片描述
在spark2.3之後建議選擇spark-streaming-kafka-0-10版本;spark-streaming-kafka-0-8已經是官方棄用的。
在這裏插入圖片描述

以下是基於spark2.2的測試:

Receiver方式整合之概述

這種方法使用一個接收器來接收數據。接收器是使用Kafka高級消費者API(高級api就是offset偏移量是自動完成控制;手動控制offset的就是低級api)實現的。與所有接收方一樣,通過接收方從Kafka接收到的數據存儲在Spark執行器中,然後由Spark流啓動的作業處理這些數據。

但是,在默認配置下,這種方法在失敗時可能會丟失數據(參見接收方可靠性)。爲了確保零數據丟失,您必須在Sparkstreaming中(在Spark 1.2中引入)另外啓用WAL機制。這將同步地將所有接收到的Kafka數據保存到分佈式文件系統(比如HDFS),以便在故障時可以恢復所有數據。有關寫前日誌的詳細信息,請參閱流編程指南中的部署部分

Receiver方式整合之Kafka測試

Receiver整合前置條件:

  1. 啓動zk
  2. 啓動kafka
  3. 創建topic
    在這裏插入圖片描述
  4. 通過控制檯測試本topic是否能夠正常的生產和消費信息

Receiver方式整合之Spark Streaming應用開發

添加pom文件中的依賴

<dependency>
    <groupId>org.apache.spark</groupId>
    <artifactId>spark-streaming-kafka-0-8_2.11</artifactId>
    <version>${spark.version}</version>
</dependency>
import org.apache.spark.SparkConf
import org.apache.spark.streaming.kafka.KafkaUtils
import org.apache.spark.streaming.{Seconds, StreamingContext}

/**
  * Spark Streaming對接Kafka的方式一
  */
object KafkaReceiverWordCount {

  def main(args: Array[String]): Unit = {

    if(args.length != 4) {
      System.err.println("Usage: KafkaReceiverWordCount <zkQuorum> <group> <topics> <numThreads>")
    }

    val Array(zkQuorum, group, topics, numThreads) = args

    val sparkConf = new SparkConf() //.setAppName("KafkaReceiverWordCount")
      //.setMaster("local[2]")

    val ssc = new StreamingContext(sparkConf, Seconds(5))

    val topicMap = topics.split(",").map((_, numThreads.toInt)).toMap

    // TODO... Spark Streaming如何對接Kafka
    val messages = KafkaUtils.createStream(ssc, zkQuorum, group,topicMap)

    // TODO... 自己去測試爲什麼要取第二個
    messages.map(_._2).flatMap(_.split(" ")).map((_,1)).reduceByKey(_+_).print()

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

Receiver方式整合之本地環境聯調

1、啓動IDEA應用程序:
在這裏插入圖片描述
2、從kafka生產者端輸入消息
在這裏插入圖片描述
觀察本地IDEA控制檯可以看到計算結果
同時kafka消費端也有消息輸出
在這裏插入圖片描述

Receiver方式整合之服務器環境聯調及Streaming UI講解

1、將本地IDEA的應用程序打包:mvn clean package -DskipTests
2、將jar包上傳到spark服務器上
3、提交應用程序

spark-submit \
--class com.imooc.spark.KafkaReceiverWordCount \
--master local[2] \
--name KafkaReceiverWordCount \
--packages org.apache.spark:spark-streaming-kafka-0-8_2.11:2.2.0 \
/home/hadoop/lib/sparktrain-1.0.jar  hadoop000:2181 test kafka_streaming_topic 1

4、向kafka輸入數據進行測試

Spark UI界面
下圖有一個receiver;如果停掉就沒有線程接受數據了。Directed模式不會有這個東西。
在這裏插入圖片描述
環境:
在這裏插入圖片描述
下圖界面對於調優有用。當前5s一個批次;運行了3分鐘11s
在這裏插入圖片描述

Direct方式整合之概述(推薦)

Spark 1.3中引入了這種新的無接收方“直接”方法,以確保更強的端到端保證。這種方法不使用接收者來接收數據,而是定期查詢Kafka以獲取每個主題+分區中的最新偏移量,並相應地定義每個批處理中的偏移量範圍。啓動處理數據的作業時,Kafka的簡單消費者API用於從Kafka讀取已定義的偏移量範圍(類似於從文件系統讀取文件)。請注意,這個特性是在針對Scala和Java API的Spark 1.3和針對Python API的Spark 1.4中引入的。

與基於接收者的方法(receive)相比,這種方法具有以下優點:

  • 簡化並行性:不需要創建多個輸入Kafka流並將它們合併。使用directStream, Sparkstreaming將創建儘可能多的RDD分區,因爲有Kafka分區要使用,這些分區將並行地從Kafka讀取數據。因此Kafka和RDD分區之間存在一對一的映射,這更容易理解和優化。
  • 效率:在receive方法中實現零數據丟失需要將數據存儲在WAL機制的日誌中,這樣可以進一步複製數據。這實際上是低效的,因爲數據被有效地複製了兩次——一次由Kafka複製,另一次由Write Ahead日誌複製。direct方法消除了這個問題,因爲沒有接收方,因此不需要提前寫日誌。只要保留了足夠的Kafka,就可以從Kafka恢復消息。
  • 精確的一次性語義:receive方法使用Kafka的高級API在Zookeeper中存儲消耗的偏移量。這是傳統上使用Kafka數據的方式。雖然這種方法(與寫前日誌相結合)可以確保零數據丟失(即至少一次語義),但是在某些失敗情況下,一些記錄可能被使用兩次的可能性很小。這是因爲火花流可靠接收的數據與Zookeeper跟蹤的偏移量之間的不一致。因此,在direct種方法中,我們使用不使用Zookeeper的簡單Kafka API。偏移量通過其檢查點內的Spark流進行跟蹤。這消除了Sparkstreaming和Zookeeper/Kafka之間的不一致性,因此儘管出現了故障,Sparkstreaming仍然可以有效地接收每條記錄一次。爲了精確地實現結果輸出的一次性語義,將數據保存到外部數據存儲的輸出操作必須是冪等的,或者是保存結果和偏移量的原子事務(更多信息請參閱主編程指南中的輸出操作語義)。

注意,這種方法的一個缺點是它不更新Zookeeper中的偏移量,因此基於Zookeeper的Kafka監控工具不會顯示進度。但是,您可以在每個批處理中訪問這種方法處理的偏移量,並自己更新Zookeeper。

Direct方式整合之Spark Streaming應用開發及本地環境測試

import org.apache.spark.SparkConf
import org.apache.spark.streaming.kafka.KafkaUtils
import org.apache.spark.streaming.{Seconds, StreamingContext}
import kafka.serializer.StringDecoder
/**
  * Spark Streaming對接Kafka的方式二
  */
object KafkaDirectWordCount {

  def main(args: Array[String]): Unit = {

    if(args.length != 2) {
      System.err.println("Usage: KafkaDirectWordCount <brokers> <topics>")
      System.exit(1)
    }

    val Array(brokers, topics) = args

    val sparkConf = new SparkConf() //.setAppName("KafkaReceiverWordCount")
      //.setMaster("local[2]")

    val ssc = new StreamingContext(sparkConf, Seconds(5))

    val topicsSet = topics.split(",").toSet
    val kafkaParams = Map[String,String]("metadata.broker.list"-> brokers)

    // TODO... Spark Streaming如何對接Kafka
    val messages = KafkaUtils.createDirectStream[String,String,StringDecoder,StringDecoder](
    ssc,kafkaParams,topicsSet
    )

    // TODO... 自己去測試爲什麼要取第二個
    messages.map(_._2).flatMap(_.split(" ")).map((_,1)).reduceByKey(_+_).print()

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

運行
在這裏插入圖片描述
測試數據的方式和receive一樣。生產端輸入數據;查看本地IDEA控制檯。

Direct方式整合之服務器環境聯調

1、將本地IDEA的應用程序打包:mvn clean package -DskipTests
2、將jar包上傳到spark服務器上
3、提交應用程序

spark-submit \
--class com.imooc.spark.KafkaDirectWordCount \
--master local[2] \
--name KafkaDirectWordCount \
--packages org.apache.spark:spark-streaming-kafka-0-8_2.11:2.2.0 \
/home/hadoop/lib/sparktrain-1.0.jar  hadoop000:9092 kafka_streaming_topic

查看UI界面發現沒有receive這個東西了
在這裏插入圖片描述
輸入一些測試數據;同時查看其他UI界面。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章