摘要:本文整理自阿里云開發(fā)工程師,Apache Flink Contributor 鐘旭陽,在 Flink Forward Asia 2022 生產(chǎn)實(shí)踐的分享。本篇內(nèi)容主要分為四個(gè)部分:
歷史背景
框架簡介
案例介紹
未來規(guī)劃

一、歷史背景

批作業(yè)在算子實(shí)際處理數(shù)據(jù)時(shí),可以提前感知到要處理的這部分?jǐn)?shù)據(jù)有多大。從而可以根據(jù)數(shù)據(jù)量的大小,選擇合適的資源處理數(shù)據(jù)。但流作業(yè)是一種 long-running 的作業(yè),它的特點(diǎn)是流量會(huì)隨著時(shí)間進(jìn)行變化。
我們沒有辦法在流作業(yè)剛啟動(dòng)時(shí),就預(yù)估到未來的流量有多少,需要多少資源。沒有一份初始的通用資源配置可以適用于一個(gè)流作業(yè)的所有場景。
并且,在通常情況下,用戶需要維護(hù)許多的 Flink 作業(yè),其中會(huì)有很多邏輯復(fù)雜、節(jié)點(diǎn)很多的作業(yè)。如果靠每個(gè)用戶手工配置這些作業(yè)的資源配置,這一過程是比較繁瑣的。對(duì)于每個(gè)用戶來說,也是不太現(xiàn)實(shí)的。
同時(shí),因?yàn)?Flink SQL 的廣泛推廣,用戶只需要關(guān)心自己的業(yè)務(wù)邏輯,就能夠使用 Flink 的能力。但也正是因?yàn)?Flink SQL 易用性,讓用戶缺乏對(duì) Flink 內(nèi)部實(shí)現(xiàn)細(xì)節(jié)的了解,調(diào)優(yōu)成本會(huì)比較高。
綜合以上的種種問題,給作業(yè)資源配置和調(diào)優(yōu)帶來一定的困難。

如果一份作業(yè)設(shè)置了不太合理的資源配置,在資源配置設(shè)置較高時(shí),會(huì)增加業(yè)務(wù)的成本。從作業(yè)上看,資源的利用率會(huì)更低。在資源配置設(shè)置比較低的時(shí)候,會(huì)使整個(gè)作業(yè)的處理能力不足,導(dǎo)致作業(yè)出現(xiàn)吞吐比較低,延遲攀升的情況。在資源嚴(yán)重不足時(shí),還會(huì)導(dǎo)致出現(xiàn) Failover 的情況大大增加,從而影響整個(gè)作業(yè)的平穩(wěn)運(yùn)行。

我們期望作業(yè)自動(dòng)調(diào)優(yōu)的目標(biāo)比較簡單,即配置一份在保障作業(yè)無延遲的前提下,盡可能的提高作業(yè)整體的吞吐量,提高作業(yè)的資源利用率,讓資源不再成為作業(yè)的瓶頸。
二、框架簡介

在 2016 年,我們支持使用資源配置、文件配置的方式,為作業(yè)設(shè)置一些資源。當(dāng)時(shí)作業(yè)以 DataStream 作業(yè)和 TableApi 作業(yè)為主。
我們通過提前預(yù)編譯的方式,將每個(gè)節(jié)點(diǎn)的初始資源配置進(jìn)行輸出。讓用戶根據(jù)這份初始的資源配置,進(jìn)行修改。然后,在提交作業(yè)運(yùn)行時(shí),通過參數(shù),帶上這份最新的配置,就可以讓這份新配置生效。但是,由于作業(yè)資源存放在文件當(dāng)中,我們很難將需要修改的節(jié)點(diǎn),和實(shí)際使用運(yùn)行的節(jié)點(diǎn),建立起對(duì)應(yīng)的關(guān)系。
對(duì)于大作業(yè)來說,它們的資源文件過于復(fù)雜。比如我需要調(diào)節(jié) 50 個(gè)節(jié)點(diǎn)中某個(gè) AGG 的算子,但是該作業(yè)中 AGG 算子一共有四、五個(gè)。很難確認(rèn)哪一個(gè) AGG 算子,才是我們需要調(diào)整的那個(gè)算子。
因此,在 2017 年我們對(duì)其進(jìn)行了改進(jìn),支持了可視化的配置。用戶可以通過可視化的拓?fù)鋱D,來修改指定的節(jié)點(diǎn)資源。它的好處是,映射關(guān)系會(huì)更加的清晰,用戶修改起來會(huì)更加的簡單方便。
隨著 SQL 作業(yè)的廣泛應(yīng)用,在這個(gè)版本里我們也增加了對(duì) SQL 作業(yè)的調(diào)優(yōu)支持,來彌補(bǔ)社區(qū)不支持細(xì)粒度設(shè)置 SQL 作業(yè)每個(gè)算子資源配置的不足。但這個(gè)版本仍然存在一些問題,比如大作業(yè)的拓?fù)鋱D仍然很復(fù)雜,用戶定位任務(wù)瓶頸時(shí),需要多次運(yùn)行作業(yè),不斷地重試調(diào)節(jié)可能有問題的節(jié)點(diǎn)。
在 2018 年,我們支持了半自動(dòng)配置 AutoConf。它的特點(diǎn)是,能夠結(jié)合作業(yè)的歷史運(yùn)行情況,通過一系列的算法,計(jì)算出此次啟動(dòng)時(shí),需要多少推薦資源。但是它的缺點(diǎn)也很明顯,針對(duì)無歷史運(yùn)行記錄的作業(yè),第一份配置通常是比較保守的,需要用戶經(jīng)過多輪迭代啟停才能最終確定一份比較合理的資源配置。
在 2019 年,我們支持了全自動(dòng)的配置 AutoScale。它能夠在作業(yè)運(yùn)行時(shí)動(dòng)態(tài)自適應(yīng)的修改資源配置。這個(gè)版本基本不需要用戶干預(yù),它能夠很好的支持改并存、改內(nèi)存等修改資源配置的能力。但這個(gè)版本依然存在一些問題,由于 AutoScale 是運(yùn)行在JM內(nèi)部的,因此天然不支持一些類似動(dòng)態(tài)啟停、查看運(yùn)行歷史記錄等等的運(yùn)維需求,在 JM 異常時(shí),調(diào)優(yōu)也無法繼續(xù)工作,同時(shí)也不支持修改拓?fù)涞炔呗?,版本升?jí)比較依賴 Flink 自身的版本。
在 2020 年,推出了獨(dú)立部署的調(diào)優(yōu)服務(wù) Autopilot。相比于它的前身,Autopilot 的調(diào)優(yōu)服務(wù)會(huì)更加易用。用戶可以在界面手動(dòng)看到的調(diào)優(yōu)歷史,明確的知道 Autopilot 根據(jù)作業(yè)的哪些情況,做過哪些調(diào)整。整個(gè)流程對(duì)用戶更加透明化。即使沒有開啟 Autopilot,也可以為每個(gè)用戶的作業(yè),提供一些輔助的調(diào)用信息,給用戶手工調(diào)優(yōu)帶來一定的幫助。
在 Autopilot 中,我們支持了更加豐富的調(diào)優(yōu)策略,例如 JM 的資源優(yōu)化,動(dòng)態(tài)拆遷 chain 優(yōu)化作業(yè)等。

Autopilot 調(diào)優(yōu)主要調(diào)節(jié)的資源配置分為以下兩種,分別是基礎(chǔ)模式和專家模式。
在基礎(chǔ)模式中,用戶可以統(tǒng)一配置 TM 的 CPU 和內(nèi)存,以及作業(yè)并發(fā)度。對(duì)于所有算子而言,這些資源都是同構(gòu)的,TM 數(shù)量取決于每個(gè) TM 中,可以有多少的 Slot?;A(chǔ)模式的特點(diǎn)是,配置簡單,適合每個(gè)節(jié)點(diǎn)資源差異比較小的作業(yè)。
在專家模式中,用戶可以單獨(dú)配置每個(gè)算子所需要的 CPU、內(nèi)存、并發(fā)等等,高度定制化,各個(gè)算子的資源是異構(gòu)的。使用專家模式可以更好的提高資源的利用率,滿足作業(yè)高吞吐的需求,節(jié)省資源。適合每一個(gè)節(jié)點(diǎn)資源差異比較大的作業(yè)。

Autopilot 自動(dòng)調(diào)優(yōu)框架,主要有以下幾個(gè)特點(diǎn)。
首先,它支持多個(gè)類型的 Flink 作業(yè),F(xiàn)link SQL 作業(yè)、DataStream 作業(yè)和 Python 作業(yè),都可以使用 Autopilot 的調(diào)優(yōu)能力。
其次,它支持多種運(yùn)行模式。
在半自動(dòng)模式下,我們支持定時(shí)調(diào)優(yōu),讓用戶指定不同的時(shí)間段,選擇不同的資源配置運(yùn)行。適合一些突出的流量高峰場景和低谷場景。
在全自動(dòng)的模式下,我們細(xì)分了資源分析模式和自動(dòng)調(diào)優(yōu)模式。在資源分析模式下,Autopilot 僅給出建議,不會(huì)自動(dòng)重啟作業(yè),適合一些不能啟停作業(yè)的敏感時(shí)期,比如大促期間。自動(dòng)調(diào)優(yōu)模式將根據(jù)流量的變化,自適應(yīng)的改變作業(yè)的資源結(jié)構(gòu),最大程度的幫用戶解決成本問題,比較適合日常的作業(yè)運(yùn)行。

Autopilot 調(diào)優(yōu)的基本思路如下。
首先,我們會(huì)從 Flink 上采集當(dāng)前作業(yè)的 Metrics,也會(huì)從一些其他的診斷系統(tǒng),拿到一些作業(yè)的運(yùn)行指標(biāo),進(jìn)行分析。
然后,通過這些原始的指標(biāo)分析,得到一些復(fù)合型指標(biāo)。通過所有的指標(biāo)生成多個(gè)帶有資源配置優(yōu)化方案的調(diào)優(yōu)計(jì)劃。在執(zhí)行計(jì)劃時(shí),從眾多的資源配置方案中,選擇一份最緊急的或最優(yōu)的方案,更新作業(yè)配置。
在更新作業(yè)配置時(shí),會(huì)優(yōu)先查看調(diào)優(yōu)計(jì)劃是不是滿足熱更新的要求。如果滿足熱更新要求,會(huì)調(diào)用 JM 的 Rest 接口更新作業(yè)。如果不滿足條件,會(huì)用 backup 方案,讓作業(yè)管理平臺(tái)啟停作業(yè)。

在采集分析 Metric 階段,除了使用原始的 Metric 信息,例如 CPU 利用率,Slot 利用率,內(nèi)存利用率,Source 的延遲等等,也會(huì)生成復(fù)合型 Metric。比如當(dāng)前延遲是不是可以 catch up,當(dāng)前數(shù)據(jù)的傾斜程度是不是很嚴(yán)重等等,從而生成不同資源配置的調(diào)優(yōu)計(jì)劃。

常見的調(diào)優(yōu)計(jì)劃分為以下幾種:拆 chain、提高/減少并發(fā)度、提高/減少內(nèi)存、添加 Flink conf 等等。最終,從多項(xiàng)調(diào)優(yōu)計(jì)劃中,選擇一份最佳的計(jì)劃執(zhí)行。

目前,Autopilot 支持兩種更新作業(yè)的方式。
熱更新作業(yè)配置,它的好處是處理速度更快,重啟的成本更低,但目前僅僅支持調(diào)節(jié)并發(fā)度。
調(diào)用管理平臺(tái),重啟作業(yè)的 API。它的好處是可以支持所有的調(diào)優(yōu)場景,來做一個(gè)最終的 backup。

如上圖所示,是作業(yè)平臺(tái)啟停流程和作業(yè)熱更新流程。我們以修改并發(fā)度為例,在作業(yè)平臺(tái)啟停流程時(shí),我們需要將原作業(yè)停止,然后提交新的作業(yè)。等待新的作業(yè)在 K8s 等平臺(tái)上重新部署和運(yùn)行。在整個(gè)流程中,作業(yè)斷流的時(shí)間較長,修改帶來的代價(jià)會(huì)比較高。
右圖是作業(yè)熱更新流程。我們通過 Rest 接收一份更新請(qǐng)求。然后,在 Job Master 里,基于當(dāng)前作業(yè)修改生成新的作業(yè),然后再停止老的作業(yè),最終部署一份新的作業(yè)。相較于作業(yè)平臺(tái),熱更新節(jié)省了啟動(dòng)初始化 Master 節(jié)點(diǎn)的時(shí)間,比作業(yè)平臺(tái)啟停,起停的成本更低。

上圖是 100 并發(fā)度作業(yè)擴(kuò)縮容斷流時(shí)間對(duì)比,在擴(kuò)容到 150 并發(fā)度時(shí),作業(yè)平臺(tái)啟動(dòng)需要花費(fèi) 40 秒左右,熱更新重啟只需要 1.5 秒左右。
在縮容到 50 并發(fā)度時(shí),作為平臺(tái)重啟需要 30 秒左右,熱更新重啟僅需要花費(fèi) 0.4 秒。
從這張圖可以看到,熱更新重啟比調(diào)優(yōu)作業(yè)平臺(tái)重啟,在重啟時(shí)間上有更加明顯的優(yōu)勢(shì)。從而能夠最大限度的降低用戶作業(yè)斷流的風(fēng)險(xiǎn),減少修改資源配置的成本。

潮汐流量是指流量的高峰和低谷,時(shí)間段具有周期性和可預(yù)見性。以電商平臺(tái)每年的雙十一活動(dòng)為例,雙十一時(shí)的配置和平時(shí)閑時(shí)的配置差異比較大。直播平臺(tái)白天的配置,和晚上的配置差異也比較大。在這種流量高峰低谷的時(shí)間段比較明顯,并且時(shí)間段比較固定的場景,應(yīng)用定時(shí)策略會(huì)更加的簡單高效。

定時(shí)策略主要針對(duì)自動(dòng)調(diào)優(yōu)無法覆蓋的場景。在應(yīng)用自動(dòng)調(diào)優(yōu)時(shí),如果流量頻繁抖動(dòng)的化,最終會(huì)導(dǎo)致作業(yè)不斷進(jìn)行調(diào)用,從而使作業(yè)不斷重啟。
在流量變化比較慢的時(shí)候,由于作業(yè)在一段時(shí)間內(nèi),Autopilot 只感知到當(dāng)前最高的流量。因此,可能會(huì)出現(xiàn)無法一次調(diào)優(yōu)到位的情況,需要經(jīng)過很多次迭代才會(huì)達(dá)到比較好的效果。
定時(shí)策略就是為了解決以上問題。它能夠允許用戶針對(duì)作業(yè)的業(yè)務(wù)特點(diǎn),設(shè)置作業(yè)的最佳資源狀態(tài)。在流量抖動(dòng)比較頻繁時(shí),不會(huì)重啟作業(yè)。當(dāng)用戶有一份流量在高峰或低谷時(shí)需要用多少資源配置的先驗(yàn)知識(shí)時(shí),能夠用定時(shí)調(diào)優(yōu)一次性的將作業(yè)調(diào)到一個(gè)比較好的狀態(tài),也能夠避開一些作業(yè)的敏感時(shí)期。

上圖是定時(shí)調(diào)優(yōu)的基本思路。Autopilot 在內(nèi)部維護(hù)了多個(gè)資源配置的日歷,當(dāng)某個(gè)時(shí)間點(diǎn)需要觸發(fā)定時(shí)策略,會(huì)選用該時(shí)間點(diǎn)的資源配置,更新作業(yè)配置。
這里的更新同樣可以分為熱更新和作業(yè)管理平臺(tái)進(jìn)行重啟。Autopilot 也會(huì)自動(dòng)檢查新增或更新的定時(shí)策略時(shí)間是否和已有的定時(shí)策略時(shí)間沖突。
三、案例介紹

上圖是作業(yè) Slot 處理能力達(dá)到瓶頸的案例,可以看到在左圖右邊的節(jié)點(diǎn)上,該節(jié)點(diǎn)每個(gè)值都很高,基本上達(dá)到了百分百,表明當(dāng)前 Slot 的利用率很高。如果作業(yè)長時(shí)間處于這種狀態(tài),會(huì)引起 Failover,影響作業(yè)的穩(wěn)定性。前面的算子已經(jīng)被該算子反壓,導(dǎo)致延時(shí)會(huì)不斷增加。
為了解決這個(gè)問題,Autopilot 將該算子的并發(fā)提高到 320。修改之后,出現(xiàn)了右圖所示的情況,該算子的 Slot 利用率,降低到比較正常的水準(zhǔn)。

上圖是一個(gè) TM 內(nèi)存使用率過低的案例,可以看到用戶在一開始申請(qǐng)了 4G 內(nèi)存,但在實(shí)際作業(yè)中,TM 只使用了 1G 左右,造成了內(nèi)存浪費(fèi)。作業(yè)成本較高,白白花費(fèi)了 3G 內(nèi)存的錢。
Autopilot 識(shí)別到這種情況,將 TM 內(nèi)存從 4G 降低到 1.6G,幫助用戶降低了作業(yè)成本。之所以降到了 1.6G,是因?yàn)?Flink 側(cè)有最低內(nèi)存設(shè)定的限制。如果調(diào)優(yōu)太低,會(huì)導(dǎo)致作業(yè)直接起不來。

上圖是一個(gè)業(yè)務(wù)流量周期變化的案例,可以看到,左上角作業(yè)的 TPS 有一個(gè)先高、后低、再高的過程。下面部分是,Autopilot 識(shí)別到流量變化,自動(dòng)調(diào)整了作業(yè)的并發(fā)度。
在流量低谷時(shí),降低了整體并發(fā)度,因此需要的數(shù)量大大降低。在流量高峰時(shí),出現(xiàn)延遲,重新進(jìn)行擴(kuò)容,保障高流量下作業(yè)的平穩(wěn)運(yùn)行。最終實(shí)現(xiàn)資源的彈性擴(kuò)縮容,有效降低了資源的使用,節(jié)約成本的同時(shí),提高了作業(yè)的穩(wěn)定性。

上圖是大促之后自動(dòng)降低資源,節(jié)約成本的案例。在大促期間,作業(yè)一般會(huì)使用比較高額的資源。一般情況下,用戶無法知道大促的流量什么時(shí)候結(jié)束,什么時(shí)候需要將作業(yè)資源配置,切換到較低的閑時(shí)狀態(tài)。
如果我們切換的較早,會(huì)導(dǎo)致預(yù)判流量失誤,造成較大的流量沖擊作業(yè),導(dǎo)致作業(yè)不穩(wěn)定。如果切換較晚,會(huì)浪費(fèi)過量的資源。Autopilot 輔助業(yè)務(wù)方在大促結(jié)束后,根據(jù)流量來平穩(wěn)、并且快速降低作業(yè)使用的資源,節(jié)約成本。

上圖是一個(gè)設(shè)定不同時(shí)間段的定時(shí)策略案例。我們可以設(shè)定早上 9 點(diǎn)到晚上 7 點(diǎn),為業(yè)務(wù)的高峰期。在這段高峰期中,使用 30 并發(fā)度。在晚上 7 點(diǎn)到早上 9 點(diǎn),為業(yè)務(wù)的低谷期,在這期間用 10 并發(fā)度。圖中是具體設(shè)置資源和設(shè)置資源時(shí)間段的示意圖。
四、未來規(guī)劃

未來,Autopilot 的主要目標(biāo)是,進(jìn)一步幫助用戶降本增效。Autopilot 將從三個(gè)角度不斷努力。
首先,我們將致力于提高 Autopilot 的易用性,方便用戶使用。我們將支持插件化的能力,允許用戶自定義一些調(diào)優(yōu)能力。比如自己排列組合一些 Metric,設(shè)定一些調(diào)優(yōu)策略,來滿足自身業(yè)務(wù)的需要。 增強(qiáng)外部集成的能力,開發(fā)提供 SDK 和 Open API 接口。
其次,我們將讓 Autopilot 更加智能、更加專業(yè)。一個(gè)方向是,探索機(jī)器學(xué)習(xí)的一些策略,依靠現(xiàn)在成熟的機(jī)器學(xué)習(xí)算法,提前進(jìn)行流量預(yù)測,并發(fā)預(yù)測等工作。另一個(gè)方向是,結(jié)合集群信息和上游依賴作業(yè)信息,進(jìn)行調(diào)優(yōu)。比如在流量高峰時(shí),在上游的作業(yè)被自動(dòng)調(diào)優(yōu)的同時(shí),下游被依賴的作業(yè)也可以順勢(shì)進(jìn)行一定的自動(dòng)調(diào)優(yōu)。
最后,Autopilot 的穩(wěn)定性是我們不斷努力的方向。一方面,我們會(huì)持續(xù)的加強(qiáng)熱更新的能力,讓更多的調(diào)優(yōu)計(jì)劃支持熱更新,減小重啟帶來的斷流等較高的調(diào)優(yōu)成本問題。另一方面,讓 Autopilot 覆蓋更多的場景來滿足不同的作業(yè) Pattern,讓其更加全面,比如說 SQL 的寫法本身就有問題,UDF 實(shí)現(xiàn)方式有問題,有較大的外部 IO、源表 Partition 數(shù)導(dǎo)致無法進(jìn)一步調(diào)高并發(fā)度,維表或結(jié)果表性能不行等等的諸多問題。