初識Spark Streaming

參考官網:http://spark.apache.org/streaming/

Spark Streaming特點

Spark Streaming makes it easy to build scalable fault-tolerant streaming applications.
Spark Streaming使得 去構建可擴展的能容錯的流式應用程序 變得容易。
(RDD容錯體現在哪些方面?)
特點:

  • Ease of Use易用性
    可以通過高級別的API操作進行構建應用程序,可以像寫批處理(離線處理)的job那樣去寫Streaming job,比如你會core、sql,在這裏很相似。
  • Fault Tolerance容錯機制
    Spark Streaming不需要額外的代碼,就可以恢復掛掉的工作流以及操作的狀態。
  • Spark Integration Spark集成
    能夠把Streaming和批處理和交互式查詢綜合起來使用。通過在Spark上運行,Spark流允許您重用相同的代碼進行批處理、根據歷史數據連接流,或者對流狀態運行即席查詢。構建強大的交互式應用程序,而不僅僅是分析。比如假如你之前用的是批處理,現在要修改成流式處理,什麼業務邏輯代碼都不需要改變,那麼只要把代碼稍微修改一下,改一下輸入輸出即可。
  • 運行模式多種多樣,可以從HDFS, Flume, Kafka, Twitter and ZeroMQ上讀取數據,也可以自定義數據源,可以跑在standalone上,yarn上等等。

常用的模式是:Flume→消息隊列(比如Kafka)→Spark Streaming

Spark Streaming概覽

參考官網:http://spark.apache.org/docs/latest/streaming-programming-guide.html

Spark Streaming是Spark core API的擴展,它的底層還是Spark RDD來實現的,它支持對實時數據流進行可橫向擴展、高吞吐量、容錯的流處理。
既然是數據流,肯定有輸入、處理和輸出。
輸入:Spark Streaming數據可以有很多數據源:Kafka, Flume, Kinesis, or TCP sockets,工作中用的比較多的是Kafka、TCP 。
處理:數據進來後可以被Spark Streaming的引擎處理,這些進來的數據可以被複雜的算法去處理,這些算法是用高級別的函數來表達的,比如: map, reduce, join and window這些函數。
輸出:最後被處理後的數據,可以被吐到文件系統、數據庫、實時dashboards上去。
另外:在Spark Streaming紙上可以使用機器學習和圖計算的處理算法。這也驗證了Spark Streaming可以和Spark生態圈裏的框架做很好的集成,可以混合起來使用。
源可以分爲有receiver和沒有receiver,後面會講到。
在這裏插入圖片描述

實質上,Spark Streaming的工作原理如下:Spark Streaming接收實時輸入數據流,並將數據分爲批(把數據切開,切成一個一個的批次),然後由Spark engine進行處理,最後也是以批次(一批一批的)的形式,產生最終的結果流。(其實就是mini batch微批處理)
這說明Spark Streaming並不是真正的實時處理的框架,它會每隔多少時間比如10秒,批處理一次,微批處理。
對於Spark,可以這樣說:Spark是以批處理爲準,使用微批來解決實時問題。

而Flink,以Stream實時爲主,來解決批處理/離線問題。
在這裏插入圖片描述
上圖:一個持續的數據流(就是一個DStream)輸入進來,通過Spark Streaming進行設置,比如幾秒鐘讀一次,把數據流按照時間劃分爲一個一個的批次(就是一個一個的RDD),由Spark engine進行處理,最後以一批一批的輸出。

Internally, a DStream is represented as a sequence of RDDs.
Spark Streaming提供了一種高級抽象,它叫做discretized stream 或者 DStream,它是Spark Streaming進行開發的時候一個頂級的接口,DStream代表了持續的數據流(數據會源源不斷的過來)。DStreams可以從數據源進行創建,比如 Kafka, Flume, and Kinesis,在其它DStreams上面作用於一個高級別的操作來產生一個DStreams。實質上,一個DStream代表了一個RDD的sequence,就是說一個DStream是由n多個RDD的sequence所構成的。

Spark Streaming:不同的數據源經過Spark Streaming處理之後,將結果輸出到某個地方上去。

在這裏插入圖片描述
小知識點:部署了Spark就不需要再單獨部署Spark Streaming,Spark Streaming是Spark裏的一個模塊。
面試:有了storm,你爲什麼還要去使用Spark Streaming?

Spark Streaming應用場景

比如電商上面,淘寶、京東、天貓等,上面推薦等(也可以使用storm等)。
再比如:公司的系統有很多,系統會採用log4j這樣的日誌框架,把日誌輸出,輸出的日誌分佈在各個節點之上,節點有很多很多,整個是個大集羣。那麼如何把這些日誌採集過來,用流處理進行分析?比如從log裏面,把error的信息給蒐集過來,error又分爲好多種,這個時候可以爲error打個標籤,什麼樣的error做什麼樣的處理,根據error發送短信或者郵件,a error發送給這些人,b error發送給那些人。

流處理過程

一般用Flume採集來的數據,可以分爲兩個方向:
在這裏插入圖片描述
前面Flume通過Kafka sink到Kafka topic是屬於Flume,後面Kafka到SparkStreaming,是屬於SparkStreaming的內容。

Spark Streaming案例

數據源爲TCP socket(演示一下,生產上很少用這種方式),數據內容爲word,統計word的數量,然後打印出來。


需要添加依賴:

    <dependency>
      <groupId>org.apache.spark</groupId>
      <artifactId>spark-streaming_2.11</artifactId>
      <version>${spark.version}</version>
    </dependency>


先導入相關的類、隱式轉換。
導入包:

import org.apache.spark._
import org.apache.spark.streaming._
import org.apache.spark.streaming.StreamingContext._


Spark core RDD裏面要有一個SparkContext,SparkSQL DF/DS裏面有SparkSession,在Spark Streaming裏面要有StreamingContext。
StreamingContext是所有streaming功能的入口點,創建一個StreamingContext,設置成兩個執行線程、每秒一個批次。
(spark2.x之後,可以使用統一的SparkSession)

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

//TODO業務邏輯。。。。

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

④業務邏輯

package com.ruozedata.spark.com.ruozedata.spark.streaming
import org.apache.spark._
import org.apache.spark.streaming._
import org.apache.spark.streaming.StreamingContext._

//這個作業是一直在跑的,一直在運行的,這個不是離線的,離線是跑完作業就沒了,就會停下來
//這個作業要是停掉了,數據就接收不了,就會丟的
object ExampleStreamingApp {
  def main(args: Array[String]): Unit = {
    //這個master要是2個core
    val conf = new SparkConf().setMaster("local[2]").setAppName("ExampleStreamingApp")
    val ssc = new StreamingContext(conf, Seconds(10))
    //批次的時間是10秒,10秒處理一次


    //這個是把server數據源轉換成了DStream
    val lines = ssc.socketTextStream("hadoop001",9999)

    //下面就是之前的wordcount代碼
    val words = lines.flatMap(_.split(" "))
    val pairs = words.map(word => (word, 1))
    val wordCounts = pairs.reduceByKey(_ + _)

    //把這個DStream產生的每個RDD的前10個元素打印到控制檯上
    wordCounts.print()


    //開始計算
    ssc.start()
    //等待計算結束
    ssc.awaitTermination()

  }
}

小知識點:

  def socketTextStream(
      hostname: String,
      port: Int,
      //默認存儲級別爲:內存、磁盤序列化 2  ,這個和Spark core裏面不一樣
      storageLevel: StorageLevel = StorageLevel.MEMORY_AND_DISK_SER_2
    ): ReceiverInputDStream[String] = withNamedScope("socket text stream") {
    socketStream[String](hostname, port, SocketReceiver.bytesToLines, storageLevel)
  }

上面運行起來之後,要在命令行啓動Netcat,在控制檯輸入:

//如果沒有nc命令,需要yum install 安裝一下
[root@hadoop001 ~]# nc -lk 9999
aaa bbb aaa  bbb
aaa
bb  cc  aaa
//這個是時間戳,可以轉換爲我們平時看到的時間的
-------------------------------------------
Time: 1564322940000 ms
-------------------------------------------
-------------------------------------------
Time: 1564322960000 ms
-------------------------------------------
-------------------------------------------
Time: 1564323020000 ms
-------------------------------------------
(bbb,2)
(,3)
(bb,1)
(cc,1)
(aaa,4)

看頁面:http://localhost:4040
在這裏插入圖片描述
下面這個Streaming在調優的時候必須要用到的
Streaming Statistics 流處理統計信息
Running batches of 10 seconds for 9 minutes 32 seconds since 2019/07/28 22:05:09 (58 completed batches, 11 records)
從什麼時候開始運行了多少個批次。
從下面可以看到, Input Rate、SocketReceiver-0、Scheduling Delay、Processing Time、Total Delay信息。這些信息很重要的。
在生產上面,如果kafka過來的數據太多,可能會有很大的延遲。在生產上面,想辦法要去保證一個批次的作業在一個批次裏把它完成。如果保證不了,就是說,這個批次沒有完成,那麼下個批次又來了,那麼後面會越積越多。(可以是kafka限速,或者Spark Streaming限流與背壓原理)
在這裏插入圖片描述
在這裏插入圖片描述

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