翻譯自 Apache Flink: Scaling Flink automatically with Reactive Mode
簡介
流式作業(yè)長時間運行過程中常常會經(jīng)歷不同流量負(fù)載的情況。流量負(fù)載會出現(xiàn)周期性的變化撤师,如:白天與晚上商玫、周末與工作日边酒、節(jié)假日與非節(jié)假日,這些波動可能是突發(fā)事件或是業(yè)務(wù)的自然增長。雖然這些波動有些是可預(yù)見的,但是如果想要在所有場景下保證相同的服務(wù)質(zhì)量休傍,那么就需要解決如何讓作業(yè)資源隨著需求的變化而動態(tài)調(diào)整。
一個簡單的衡量當(dāng)前所需資源與可用資源是否匹配的方法是:計算當(dāng)前負(fù)載與可用的 workers 數(shù)之間的面積尼夺。如下圖所示尊残,左圖中分配了固定的資源量,可用看到:實際負(fù)載與可用的 workers 之間有很大的差距 —— 因此造成了資源的浪費淤堵。右圖中展示了彈性資源分配的情況寝衫,紅線與黑線之間的距離在負(fù)載的變化中不斷的努力減小。
多虧了 Flink 1.2 引入的可擴展?fàn)顟B(tài)(rescalable state)拐邪,我們可以手動對 Flink 作業(yè)擴/縮容慰毅,即可以通過調(diào)整并行度、重啟任務(wù)的方式來調(diào)整資源扎阶。例如汹胃,如果你的 Flink Job 當(dāng)前的并行度是 100,當(dāng)負(fù)載升高時可以上調(diào)并行度到 200 并重啟應(yīng)用來應(yīng)對負(fù)載的升高东臀。
這種方式的問題在于你需要手動的借助一些自研工具來進行資源的計算與評估着饥,并重新部署來進行合理的擴/縮容,不僅如此惰赋,這其中還可能包括一些異常的處理宰掉,以及對其他有相似情況的任務(wù)做同樣的工作。
Flink 1.13 引入的響應(yīng)模式(reactive mode)給你提供了另一種選擇:這種模式下你只需要監(jiān)控你的 Flink 集群赁濒,然后根據(jù)一些監(jiān)控指標(biāo)添加/移除相應(yīng)的資源轨奄,剩下的事情 Flink 會幫你完成。響應(yīng)式模式下 JobManager 會嘗試引入所有可用的 TaskManager 資源用于當(dāng)前的流數(shù)據(jù)處理拒炎。
響應(yīng)式模式的一個巨大優(yōu)勢在于你不再需要詳細(xì)的去了解 Flink 擴容相關(guān)知識就可以達到適應(yīng)性擴容的目的挪拟。基本上可以把 Flink 看做一個服務(wù)器集群(如同 web 服務(wù)器击你、緩存玉组、批處理),你可以根據(jù)所需進行擴/縮容丁侄。當(dāng)前自動擴容在業(yè)界已經(jīng)有非常成熟的方案球切,眾多基礎(chǔ)設(shè)施都提供相應(yīng)的支持:主流的云服務(wù)都提供相關(guān)的指標(biāo)監(jiān)控組件,并適應(yīng)性進行資源調(diào)整绒障。例如,AWS 基于 Auto Scaling groups 提供支持捍歪、Google Cloud 的 Managed Instance groups户辱。相應(yīng)的鸵钝,Kubernetes 提供了 Horizontal Pod Autoscalers。
不同于其他支持自動擴容“服務(wù)器集群”庐镐,F(xiàn)link 是一個包含狀態(tài)的系統(tǒng)恩商,通常需要處理重要的數(shù)據(jù)并保證強一致性(類似于數(shù)據(jù)庫)。但并不像傳統(tǒng)數(shù)據(jù)庫那樣必逆,F(xiàn)link 可以彈性的調(diào)整資源(基于 checkpoint 和狀態(tài)后端)來優(yōu)化當(dāng)前的集群負(fù)載怠堪,而且沒有太多的要求(如一個簡單的 blob 存儲用于狀態(tài)備份即可)。
開始使用
通過以下步驟你可以在本地的 Flink 1.13.0 版本中體驗一下響應(yīng)模式:
# These instructions assume you are in the root directory of a Flink distribution.
# Put Job into usrlib/ directory
mkdir usrlib
cp ./examples/streaming/TopSpeedWindowing.jar usrlib/
# Submit Job in Reactive Mode
./bin/standalone-job.sh start -Dscheduler-mode=reactive -Dexecution.checkpointing.interval="10s" -j org.apache.flink.streaming.examples.windowing.TopSpeedWindowing
# Start first TaskManager
./bin/taskmanager.sh start
你已經(jīng)開啟了一個基于響應(yīng)式模式的 Flink 任務(wù)名眉。你可以通過 Flink Web UI 查看到剛剛啟動的一個 TaskManager粟矿。如果想要擴容只需要簡單的添加另外一個 TaskManager 即可:
# Start additional TaskManager
./bin/taskmanager.sh start
To scale down, remove a TaskManager instance:
# Remove a TaskManager
./bin/taskmanager.sh stop
基于 Docker 或 standalone Kubernetes 部署的 Flink 集群都可以在響應(yīng)模式下部署任務(wù)(以上都需要基于 application 部署模式)
基于 Kubernetes 的示例
此章節(jié),我們會演示一個真實場景中基于響應(yīng)模式部署的示例损拢。你可以將本示例作為自己部署自動擴容式集群的起點或模板陌粹。
操作流程
本示例的核心思路是基于 Kubernetes 的 Horizontal Pod Autoscaler,該組件會監(jiān)控所有 TaskManager pods 的 CPU 負(fù)載來相應(yīng)的調(diào)整副本因子(replication factor)福压。當(dāng) CPU 負(fù)載升高時掏秩,autoscaler 會增加 TaskManager 資源來平攤壓力;當(dāng)負(fù)載降低時荆姆,autoscaler 會減少 TaskManager 資源蒙幻。
整體的部署情況如下圖所示:
我們來逐一介紹一下:
Flink
JobManager 是基于 Kubernetes job 部署。提交的 container 是基于官方的 Flink Docker 鏡像胆筒,其中還包含了一個 Flink 任務(wù)的 jar 包邮破。該 Flink 任務(wù)會從 Kafka topic 中讀取數(shù)據(jù),然后對讀取的事件進行復(fù)雜的數(shù)學(xué)運算腐泻。通過復(fù)雜的數(shù)學(xué)運算來使 CPU 負(fù)載升高。這種方式下派桩,我們不需要部署大型的 Kafka 集群就可以模擬高負(fù)載的場景构诚。
TaskManager 也基于 Kubernetes 部署,并通過 Horizontal Pod Autoscaler 進行擴容铆惑。本示例中范嘱,autoscaler 將會監(jiān)控 pods 的 CPU 負(fù)載。pods 的數(shù)量會在 1~15 之間調(diào)整员魏。
其他的組件:
我們部署了 Zookeeper 和 Kafka(各占用一個 pod)丑蛤,并創(chuàng)建了一個 topic 作為 Flink 任務(wù)的讀數(shù)據(jù)源。
還有一個數(shù)據(jù)生成器(Data Generator) 的 pod 來周期性的向 Kafka topic 中寫入 string 類型數(shù)據(jù)撕阎。在本示例中受裹,寫入速率的周期遵循正弦函數(shù)。
我們還部署了 Prometheus 和 Grafana 來用于監(jiān)控。
如果你想自己嘗試一下棉饶,以上都可以從 Github 中獲取厦章。
結(jié)果
我們將以上組件全部部署在了僅包含一臺主機的 Kubernetes 集群中,并運行了幾天照藻。以下的 Grafana 看板截圖中展示了這幾天運行的成果:
讓我們更仔細(xì)的觀察一下這個監(jiān)控看板:
左上角圖中是 Kafka 消費延遲監(jiān)控袜啃,基于 Flink Kafka consumer(source 算子)上報的指標(biāo)。該看板用于監(jiān)控消費延遲的消息數(shù)幸缕。指標(biāo)升高表示 Flink消費速度低于 Kafka producer 生產(chǎn)速度群发,此時需要擴容。該看板也反映了 Kafka 的吞吐量发乔,最高的吞吐量約 75k熟妓,最小時為 0。
右上角看板表示 Flink 每秒吞吐量監(jiān)控列疗,基于 Flink 的 reports per second 指標(biāo)上報滑蚯。該指標(biāo)走向與正弦曲線大致相同,峰值約 6k/s抵栈,峰谷接近 0告材。
左下角的看板中展示了每個 TaskManager 的 CPU 負(fù)載監(jiān)控。Kubernetes pod autoscaler 會基于該指標(biāo)調(diào)整 TaskManager 的副本數(shù)量古劲〕飧常可以看到每當(dāng) CPU 負(fù)載到達某個值時 TaskManager 的數(shù)量就會隨之增加。
右下角圖中展示了 TaskManager 數(shù)量产艾。當(dāng)吞吐(或 CPU 負(fù)載)升高時疤剑,我們可以看到 TaskManager 數(shù)量增大到 5(部分峰值下漲到了 8 個),最小時為 1 個闷堡。該圖很好的展示了響應(yīng)模式的工作過程:TaskManager 數(shù)量隨著負(fù)載的變化而變化隘膘。
經(jīng)驗總結(jié):將心跳超時配置降低能夠讓縮容更平順
在我們剛剛開啟實驗時,我們從圖標(biāo)中注意到一些 Flink 反常的表現(xiàn):
上面所有圖中杠览,我們可以看到會有毛刺出現(xiàn):消費延遲曲線會突然增大到 600k(是平時 75k 正常峰值的 8 倍)弯菊。在“TaskManager 數(shù)量”監(jiān)控看板中我們發(fā)現(xiàn) TaskManager 數(shù)量某些情況下并沒有很好的追隨吞吐量曲線的變化。導(dǎo)致我們浪費了大量配置的 TaskManager 資源踱阿。
我們還發(fā)現(xiàn)這種情況只有在負(fù)載降低時才會發(fā)生管钳,但是響應(yīng)模式也是支持縮容場景的。那到底是什么原因?qū)е旅坛霈F(xiàn)以及 TaskManager 縮容不及時的呢软舌?
在 Flink 中才漆,JobManager 會定期發(fā)送心跳信息給 TaskManager 來確定 TaskManager 是否還存活。默認(rèn)心跳的發(fā)送頻率是 50s 一次佛点。這個默認(rèn)值看上去像是很高醇滥,但是在高負(fù)載情況下可能出現(xiàn)網(wǎng)絡(luò)波動、gc 停滯或其他情況導(dǎo)致心跳數(shù)據(jù)發(fā)送延遲。我們不希望將短暫的中斷判斷成 TaskManager 徹底失聯(lián)腺办。
然而焰手,這個默認(rèn)值在本次實驗中帶來了問題:當(dāng) Kubernetes autoscaler 監(jiān)控到 CPU 負(fù)載降低時會降低 TaskManager 數(shù)量,停止 TaskManager 實例怀喉。隨之 Flink 會因為數(shù)據(jù)傳輸層(data transport layer)與這些 TaskManager 失聯(lián)而立即停止數(shù)據(jù)處理,而且 JobMaster 將會等待 50s 后才會認(rèn)定 TaskManager 真正被關(guān)閉了船响。
在 JobManager 等待期間吞吐量會降到 0躬拢,數(shù)據(jù)也會因此積壓在 Kafka 中(消費延遲看板出現(xiàn)毛刺的原因)。當(dāng) Flink 重新運行起來后會對積壓數(shù)據(jù)進行消費见间,從而造成了 CPU 負(fù)載的升高聊闯。autoscaler 監(jiān)控到負(fù)載變化后會分配更多的 TaskManager,因此造成了 TaskManager 的浪費米诉。
我們觀察發(fā)現(xiàn)這種情況只會發(fā)生在縮容的場景中菱蔬,因為縮容更加容易引起不穩(wěn)定的情況的發(fā)生相比于擴容。擴容時史侣,TaskManager 資源增加拴泌,數(shù)據(jù)停止處理僅發(fā)生在任務(wù)重啟階段(重啟動作很快,僅會造成 Kafka 少量數(shù)據(jù)積壓)惊橱;然而縮容時蚪腐,數(shù)據(jù)停止處理的時間大約 50s。
我們通過調(diào)整 heartbeat.timeout
為 8s 來緩解了以上問題的發(fā)生税朴。另外回季,我們期望后續(xù)社區(qū)能夠優(yōu)化 JobMaster 判斷 TaskManager 失聯(lián)的策略,能夠更好正林、更快的的處理失聯(lián)的場景泡一。
總結(jié)
本文中我們介紹了 Flink 響應(yīng)模式,這是 Flink 向動態(tài)資源規(guī)劃觅廓、提升資源利用率方向邁進的重要一步鼻忠。本文還演示了響應(yīng)模式在 Kubernetes 中的實踐,以及一些實踐經(jīng)驗的總結(jié)與學(xué)習(xí)哪亿。
響應(yīng)模式是 Flink 1.13 中的新特性被記錄在產(chǎn)品開發(fā)文檔的 MVP(Minimal Viable Product)章節(jié)粥烁。在使用之前你還需要認(rèn)真查看官方文檔中相關(guān)的使用限制。里面提到的最大限制是:只有在獨立應(yīng)用部署模式(standalone application mode)下才支持響應(yīng)模式(即蝇棉,不能在 active resource managers 部署模式或 session 部署模式中的集群使用)
社區(qū)非常期待大家針對這一特性的反饋讨阻,從而提升 Flink 彈性化資源管理能力。如何你有任何反饋請通過 Flink 開發(fā)者郵件列表告訴我們篡殷,或在 Twitter 里面 @ 我钝吮。
譯者:可可 @ 歡迎郵件聯(lián)系我