SparkStreaming控制消費速率(反壓機制)

反壓機制:

spark1.5以後,通過動態收集系統的一些數據來自動的適配集羣數據處理能力
在默認情況下,Spark Streaming 通過 receivers (或者是 Direct 方式) 以生產者生產數據的速率接收數據。當 batch processing time > batch interval 的時候,也就是每個批次數據處理的時間要比 Spark Streaming 批處理間隔時間長;越來越多的數據被接收,但是數據的處理速度沒有跟上,導致系統開始出現數據堆積,可能進一步導致 Executor 端出現 OOM 問題而出現失敗的情況。
而在 Spark 1.5 版本之前,爲了解決這個問題,對於 Receiver-based 數據接收器,我們可以通過配置 spark.streaming.receiver.maxRate 參數來限制每個 receiver 每秒最大可以接收的記錄的數據;對於 Direct Approach 的數據接收,我們可以通過配置 spark.streaming.kafka.maxRatePerPartition 參數來限制每次作業中每個 Kafka 分區最多讀取的記錄條數。

spark.streaming.kafka.maxRatePerPartition:設定對目標topic每個partition每秒鐘拉取的數據條數。
假設bacth interval =10s ,maxRatePerPartition設置爲2,該topic設置的分區爲3
則一個批次里拉取的總條數=2*3*10=60條數據,也就是當前的吞吐量

這種方法雖然可以通過限制接收速率,來適配當前的處理能力,但這種方式存在以下幾個問題:

● 我們需要事先估計好集羣的處理速度以及消息數據的產生速度;
● 這兩種方式需要人工參與,修改完相關參數之後,我們需要手動重啓 Spark Streaming 應用程序;
● 如果當前集羣的處理能力高於我們配置的 maxRate,而且 producer 產生的數據高於 maxRate,這會導致集羣資源利用率低下,而且也會導致數據不能夠及時處理。
● 那麼有沒有可能不需要人工干預,Spark Streaming 系統自動處理這些問題呢?當然有了!Spark 1.5 引入了反壓(Back Pressure)機制,其通過動態收集系統的一些數據來自動地適配集羣數據處理能力。詳細的記錄請參見 SPARK-7398 裏面的說明。
Spark Streaming 1.5 以前的體系結構
在 Spark 1.5 版本之前,Spark Streaming 的體系結構如下所示:
在這裏插入圖片描述
● 數據是源源不斷的通過 receiver 接收,當數據被接收後,其將這些數據存儲在 Block Manager 中;爲了不丟失數據,其還將數據備份到其他的 Block Manager 中;
● Receiver Tracker 收到被存儲的 Block IDs,然後其內部會維護一個時間到這些 block IDs 的關係;
● Job Generator 會每隔 batchInterval 的時間收到一個事件,其會生成一個 JobSet;
● Job Scheduler 運行上面生成的 JobSet。
Spark Streaming 1.5 之後的體系結構
在這裏插入圖片描述
● 爲了實現自動調節數據的傳輸速率,在原有的架構上新增了一個名爲 RateController 的組件,這個組件繼承自 StreamingListener,其監聽所有作業的 onBatchCompleted 事件,並且基於 processingDelay、schedulingDelay 、當前 Batch 處理的記錄條數以及處理完成事件來估算出一個速率;這個速率主要用於更新流每秒能夠處理的最大記錄的條數。速率估算器(RateEstimator)可以又多種實現,不過目前的 Spark 2.2 只實現了基於 PID 的速率估算器。
● InputDStreams 內部的 RateController 裏面會存下計算好的最大速率,這個速率會在處理完 onBatchCompleted 事件之後將計算好的速率推送到 ReceiverSupervisorImpl,這樣接收器就知道下一步應該接收多少數據了。
● 如果用戶配置了 spark.streaming.receiver.maxRate 或 spark.streaming.kafka.maxRatePerPartition,那麼最後到底接收多少數據取決於三者的最小值。也就是說每個接收器或者每個 Kafka 分區每秒處理的數據不會超過 spark.streaming.receiver.maxRate 或 spark.streaming.kafka.maxRatePerPartition 的值。
詳細的過程如下圖所示:
在這裏插入圖片描述

如何啓用?

啓用反壓:sparkConf.set(“spark.streaming.backpressure.enabled”, “true”)。spark會在作業執行結束後,調用RateController.onBatchCompleted更新batch的元數據信息:batch處理結束時間、batch處理時間、調度延遲時間、batch接收到的消息量等.

在 Spark 啓用反壓機制很簡單,只需要將 spark.streaming.backpressure.enabled 設置爲 true 即可,這個參數的默認值爲 false。反壓機制還涉及以下幾個參數,包括文檔中沒有列出來的:
● spark.streaming.backpressure.initialRate: 啓用反壓機制時每個接收器接收第一批數據的初始最大速率。默認值沒有設置。
● spark.streaming.backpressure.rateEstimator:速率估算器類,默認值爲 pid ,目前 Spark 只支持這個,大家可以根據自己的需要實現。
● spark.streaming.backpressure.pid.proportional:用於響應錯誤的權重(最後批次和當前批次之間的更改)。默認值爲1,只能設置成非負值。weight for response to “error” (change between last batch and this batch)
● spark.streaming.backpressure.pid.integral:錯誤積累的響應權重,具有抑制作用(有效阻尼)。默認值爲 0.2 ,只能設置成非負值。weight for the response to the accumulation of error. This has a dampening effect.
● spark.streaming.backpressure.pid.derived:對錯誤趨勢的響應權重。 這可能會引起 batch size 的波動,可以幫助快速增加/減少容量。默認值爲0,只能設置成非負值。weight for the response to the trend in error. This can cause arbitrary/noise-induced fluctuations in batch size, but can also help react quickly to increased/reduced capacity.
● spark.streaming.backpressure.pid.minRate:可以估算的最低費率是多少。默認值爲 100,只能設置成非負值。
原文鏈接:https://blog.csdn.net/java_soldier/article/details/83384087

設置spark.streaming.kafka.maxRatePerPartition的原則

spark.streaming.kafka.maxRatePerPartition這個參數是控制吞吐量的,一般和spark.streaming.backpressure.enabled=true一起使用。那麼應該怎麼算這個值呢?

如例要10分鐘的吞吐量控制在5000,0000,kafka分區是10個。

spark.streaming.kafka.maxRatePerPartition的值 * kafka分區數 * (10 *60)(每秒時間)
50000000/10/600s =8400

也就是我們該設置maxrRatePerPartition這個參數爲8400,每秒拉取8400條數據。

spark.streaming.kafka.maxRatePerPartition控制spark讀取的每個分區最大消息數。從上面的分析過程可以預見到,每個分區接收到的消息量<=batchDuration * spark.streaming.kafka.maxRatePerPartition.

以下兩種場景需要啓用反壓,可以有效防止應用程序過載:

1、首次啓動Streaming應用,kafka保留了大量未消費歷史消息,並且auto.offset.reset=latest,可以防止第一個batch接收大量消息、處理時間過長和內存溢出

2、防止kafka producer突然生產大量消息,一個batch接收到大量數據,導致batch之間接收到的數據傾斜

Spark Streaming是先從broker裏查詢到每個分區的latestOffset,這樣就可以得到每個分區的offset range,再用range和上一步預估的速率做對比計算就可以確定每個分區的處理的消息量。整個計算步驟:

1、offset range的消息量 totalLag

2、有效速率=取設置的maxRatePerPartition和預估的速率最小值

3、一個batch的每個分區每秒接收到的消息量=batchDuration*有效速率

offset管理

enable.auto.commit參數必須設置false,因爲在自動commit的情況下,可能在一個batch內的數據還沒有處理完、或者處理失敗,但offset就自動提交了,就會導致數據丟失。下面是在zk中管理offset的思路,zk簡單方便而且保證了可用性。

在spark Streaming作業開始時,readOffsets函數用於從zk讀取上次應用保存的最後處理的消息偏移量,有以下兩種不同處理場景:

  • 1、Spark Streaming應用程序首次運行時,從zk read不到數據,那麼就創建一個KafkaConsumer對象,用consumer.position的方式獲取offset,這時獲取到的offset取決於auto.offset.reset參數的設置

  • 2、如果是重啓Spark Streaming應用程序,那可以直接從zk讀取到應用上次保存的offset
    整體: 在這裏插入圖片描述

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