Flink 調優:Checkpoint 問題排查

1. Flink Checkpoint 流程

在使用 Flink 時, 我們基本都會用到 Checkpoint,也難免不會遇到 Checkpoint 慢或者失敗等問題,如果想要排查這些問題,那麼必須先知道 Checkpoint 的生產流程。關於 Flink Checkpoint 的流程,在 Flink 原理與實現:Checkpoint 這篇文章中做了比較詳細的介紹。一個 Task 的 Checkpoint 流程包括以下幾個步驟:

  1. JobManager 向 Source 算子發送 Barrier ,初始化 Checkpoint;
  2. Source 算子收到 Barrier 之後,Checkpoint 自己的 State,並向下遊發送 Barrier;
  3. 下游收到 Barrier 後,進行 Barrier Alignment 處理;
  4. Task 開始同步階段的 Snapshot;
  5. Task 開始異步階段的 Snapshot;
  6. Task 做完 Checkpoint 之後,再上報 JobManager。

2. Checkpoint 監控

通過 Flink UI,我們可以看到 Flink Job 的運行狀態、運行日誌、Checkpoint 和反壓等情況。現在我們就認識下 Flink UI 中與 Checkpoint 相關的部分,圖 1 是 Flink 1.6 版本的 UI,1.9 之後 Flink UI 做了優化,不過大同小異。
圖1 Flink Job Overview
在圖 1 中,其中左側側邊欄的:

  1. Task Manager:可以查看各個 Task 的配置、日誌、資源等相關信息;
  2. Job Manager:可以查看 JobManager 的配置、資源、日誌等相關信息。

圖 1 右側下方與 Checkpoint 相關的主要是 Checkpoints,在排查 Checkpoint 的相關問題時,也可能會用到 SubtasksBack Pressures

  • Subtasks:可以查看 JobGraph 的各個節點 Subtask 的吞吐量等情況,能夠據此判斷數據傾斜情況;
  • Back Pressures:用於觀察 JobGraph 各節點算子的反壓情況,其中:
    • OK: 0 <= Ratio <= 0.10
    • LOW: 0.10 < Ratio <= 0.5
    • HIGH: 0.5 < Ratio <= 1
  • Checkpoints:與 Checkpoint 相關的信息基本都在這裏了。
    • Overview:相當於是 Checkpoint Dashboard;
    • History:各個 Checkpoint 的執行信息;
    • Summary:整個 Job 所有 Checkpoint 的 End to End Duration、State Size 和 Buffered During Alignment 的最大值、最小值和均值;
    • Configuration:Checkpoint 的配置信息,也就是 Flink 調優:Checkpoint 配置 的一些配置。

Summary 和 Configuration 比較簡單就不多做贅述了,而 Overview 則如圖 1 所示,比較簡潔明瞭,需要說明的是 ID 都是 Checkpoint ID——可用於在 Task Manager 日誌和 Job Manager 日誌中查找對應的信息,More details 是該 Checkpoint 的生產明細信息。而 History 如圖 2 所示:
圖 2 Checkpoint history
History 也有 More details,和 Overview 中的 More details 是一樣的。History 的 End to End Duration、State Size、Buffered During Alignment 與 Summary 中的含義一樣。需要注意的一點是,Checkpoint 失敗時的 More details 與 Checkpoint 成功時的 More details 顯示的內容略有差異。
圖 3 More details of successful checkpoint
圖 4 More details of failure checkpoint
圖 3 是成功的 Checkpoint 的 More details,不同的兩列是 Discarded 和 Path;而圖 4 是失敗的 Checkpoint 的 More details,不同的兩列是 Failure Time 和 Failure Message。其他幾列是:

  1. ID:Checkpoint ID,可以在日誌中查找相關信息;
  2. Status:Checkpoint 的生產狀態:In Progress、Completed、Failed;
  3. Acknowledged:Job Manager 已 Acknowledged 的 Checkpoint 個數和需要 Acknowledge 的 Checkpoint 個數;
  4. Trigger Time:Job Manager Trigger Checkpoint 的時間;
  5. Latest Acknowledgement:Job Manager 最近一次 Acknowledged Checkpoint 的時間;
  6. End to End Duration:Job 的 Checkpoint 從被 Trigger 至最近的 Subtask 的 Checkpoint 被 Acknowledged 的時間間隔。
  7. State Size:Job 的所有 Subtasks 的 State Size 之和;
  8. Buffered During Alignment:在對所有 Acknowledged Subtasks 進行 Barrier Alignment 期間緩衝的字節數。如果該值大於 0,說明在 Checkpoint 生產期間發生了 Barrier Alignment。如果 Checkpoint 使用的是 AT_LEAST_ONCE 模式,那麼該值始終是 0。

在圖 3 和圖 4 中,從 Subtasks 的 Checkpoint 生產信息,可以得到如下信息:

  1. Checkpoint 的 delay = end_to_end - sync - async。但是,太長的 delay 意味着反壓,反壓則表示應用程序資源配置不足。其中 End to End Duration 簡寫爲 end_to_end、Checkpoint Duration(Sync) 簡寫爲 sync、Checkpoint Duration(Async) 簡寫爲 async。
  2. 根據 Checkpoint Duration(Sync) 和 Checkpoint Duration(Async),可以計算 Snapshot 生產耗時。但是,耗時過長意味着:第一,每個節點的 State 太大;第二,Snapshot 存儲無法跟上負載(低帶寬)。
  3. Alignment Buffered 和 Alignment Duration 是評估穩健性非常重要的指標。

3. Checkpoint 失敗

對於追查 Checkpoint 失敗的具體原因,從日誌角度來說大體有這幾個步驟:

  1. 在 Flink UI 的 Checkpoints 中,找到失敗的 Checkpoint 的 ID;
  2. 用 Checkpoint ID 去 Job Manager 日誌中,定位該 Checkpoint 失敗發生的 Execution 以及 Task Manager;
  3. 在 Task Manager 查找該 Checkpoint 失敗的具體原因。

通常情況下,Checkpoint 大概失敗有兩種情況:

  • Checkpoint Decline
  • Checkpoint Expire

3.1 Checkpoint Decline

按照前文的思路,假設我們已經在 Flink UI 中找到了失敗的 Checkpoint ID 是 16883。然後,我們就去 Job Manager 日誌中定位 ID 16883:

Decline checkpoint 16883 by task ab66f08bf898b7d25b4fe69bc74ce2e1 of job 7af7749825e6bef10cbd909f2746acfc

其中,ab66f08bf898b7d25b4fe69bc74ce2e1 是 Execution ID,7af7749825e6bef10cbd909f2746acfc 是當前 Job ID,圖 1 右側面板的左上角和 Job Name 一起的那一串字符串就是這個 Job ID。

然後,用 Execution ID ab66f08bf898b7d25b4fe69bc74ce2e1 在 Job Manager 日誌中定位發生在哪個 Task Manager。

******** (18/36) (ab66f08bf898b7d25b4fe69bc74ce2e1) switched from SCHEDULED to DEPLOYING.
Deploying ******** (18/36) (attempt #0) to slot container_e12_1590211490022_8088_03_102035_2 on HOSTNAME

我們發現該 Execution 被調度到了 HOSTNAME 的 container_e12_1590211490022_8088_03_102035_2 Slot 上,然後再去對應的 Task Manager 中查找失敗的具體原因即可。

社區還給出了另一種 Checkpoint Decline 發生在 Checkpoint Cancel 的時候:如果 Flink 在較小的 Checkpoint ID 還沒有對齊的時候,收到了更大的 Checkpoint ID,則會把較小的 Checkpoint ID 給取消掉。會有如下日誌

Received checkpoint barrier for checkpoint 20 before completing current checkpoint 19. Skipping current checkpoint

這個日誌表示,當前 Checkpoint 19 還在對齊階段,就收到了 Checkpoint 20 的 Barrier。然後,會逐級通知到下游的 Task Checkpoint 19 被取消了,同時也會通知 Job Manager 當前 Checkpoint 被 Decline 了。

3.2 Checkpoint Expire

Flink 調優:Checkpoint 配置 中講到過 Checkpoint 是有超時時間的,如果 Checkpoint 生產時間大於超時時間,該 Checkpoint 就會以失敗而告終。按照前文的方法,假設我們已經在 Flink UI 中找到了失敗的 Checkpoint ID 是 16881,接着去 Job Manager 日誌中定位 ID 16881。

Checkpoint 16881 of job 7af7749825e6bef10cbd909f2746acfc expired before completing.
......
Received late message for now expired checkpoint attempt 16881 from a9c6af93c028b7d25b4fe693e4aaf09f of job 7af7749825e6bef10cbd909f2746acfc.

可以看到日誌描述了,7af7749825e6bef10cbd909f2746acfc 這個 Job 的 Checkpoint 16881 在生產完成之前因超時而過期了,並且發生在 a9c6af93c028b7d25b4fe693e4aaf09f 這個 Execution 上。然後,按照上一節的步驟繼續排查,就可以在 Task Manager 的日誌中定位的失敗的具體原因。

4. Checkpoint 慢

Flink 調優:Checkpoint 配置 一文中介紹過 Checkpoint 有很多配置項,如果配置不當,會導致 Checkpoint 慢或者 Checkpoint 失敗,最終都會影響應用程序的性能及穩定性。下面我們按照 Checkpoint 的流程逐一討論。

4.1 Source Trigger Checkpoint 慢

這種情況很少見,筆者暫時還未遇到過。從資料中可以發現,因爲 Source 做 Snapshot 並往下游發送 Barrier 的時候,需要搶鎖(目前社區已經用 MailBox 替代當前搶鎖的方式)。如果一直搶不到鎖的話,則可能導致 Checkpoint 一直得不到機會進行。如果在 Source 所在的 Task Manager 日誌中找不到開始做 Checkpoint 的日誌,則可以考慮是否屬於這種情況,可以通過 jstack 進行進一步確認鎖的持有情況。

4.2 Barrier Alignment 慢

Checkpoint 時,會在 Barrier Alignment 之後進入 Snapshot 的同步階段和異步階段。如果應用程序 Checkpoint 時有 Barrier Alignment,而上游某些 Barrier 還未抵達,那麼就無法開始產生 Snapshot,Checkpoint 也就不能繼續。如果 Checkpoint 使用的是 AT_LEAST_ONCE 模式,就不需要進行 Barrier Alignment。我們通過 Flink UI 就可以在 Checkpoint 的 More details 中找到 Barrier 的對齊情況。
圖5 Barrier Alignment

4.3 同步階段慢

一般情況下,同步階段不會太慢。但是,如果我們通過 Flink UI 或日誌發現同步階段比較慢的話,對於 FsStateBackend 可以考慮查看是否開啓了異步 Snapshot,如果開啓了異步 Snapshot 還是慢,需要看整個 JVM 的使用情況。對於 RocksDBBackend 來說,需要用 iostate 查看磁盤的使用,另外可以查看 Task Manager 日誌中關於 RocksDBBackend 的信息。

4.4 異步階段慢

在異步階段,Task Manager 主要將 State 持久化到存儲上。對於 FsStateBackend,主要瓶頸來自於網絡傳輸,這個階段可以觀察網絡相關的 Metric,或者對應機器上能夠觀察到網絡流量的情況。對於 RocksDBBackend,則需要從本地讀取文件,寫入到遠程的持久化存儲上,所以不僅需要考慮網絡的瓶頸,還需要考慮本地磁盤的性能。如果覺得網絡流量不是瓶頸,但是上傳比較慢的話,還可以嘗試開啓多線程上傳功能。

4.5 主線程沒機會做 Snapshot

在 Task Manager 中,數據處理和 Barrier 處理都由主線程處理。如果主線程在處理速度太慢,就會導致 Barrier 處理慢,從而影響 Checkpoint 進度。這時候就需要使用 jstack、JProfier 或者 async-profiler 等工具分析應用層的堆棧、CPU使用情況。

4.6 Checkpoint 時間配置不當

Checkpoint 與時間相關的配置有:

  • 時間間隔:env.enableCheckpointing()
  • 超時時間:CheckpointConfig.setCheckpointTimeout()
  • 停頓時間:CheckpointConfig.setMinPauseBetweenCheckpoints()

關於 Checkpoint 的配置原則請移步 Flink 調優:Checkpoint 配置 ,我們配置的目標是避免由於 Checkpoint 時間間隔過長,導致生成的 State 過大,從而使網絡傳輸過慢;避免 Checkpoint 超時時間小於生產時間。下圖描述了 Checkpoint 的時間關係。
圖 6 Checkpoint 時間關係

4.7 使用增量 Checkpoint

Flink Checkpoint 有兩種模式,全量 Checkpoint 和增量 Checkpoint,其中全量 Checkpoint 會把當前的 State 全部備份一次到持久化存儲;而增量 Checkpoint 則只備份上一次 Checkpoint 中不存在的 State,因此增量 Checkpoint 在速度上會有更大的優勢。但是,目前的 Flink 中僅 RocksDBStateBackend 支持增量 Checkpoint,如果你已經使用 RocksDBStateBackend,建議通過開啓增量 Checkpoint 來加速。

4.8 反壓

Flink 應用程序的反壓情況可在 Flink UI 中看到,如下圖:
圖 7 Back Pressure
如圖 7 中應用程序中 Subtask 被標記爲 HIGH,表示此時反壓很嚴重,同時會導致下游接受很晚才能接到 Barrier,進而拖慢 Checkpoint 進度。

4.9 數據傾斜

無論是離線計算(包括 SQL、Code),還是實時計算(包括 SQL、Code),數據傾斜(Data Skew)都是不得不面對的一個問題。而且實時計算的數據傾斜解決方案,要比離線計算的解決方案要複雜一些。雖然發生數據傾斜有很多種情況,不過,其解決方案的思想確實大同小異(這些內容不屬於本文的討論範疇,後期文章有專題討論,盡請關注)。

言歸正傳,對於 Flink 應用程序,我們可以在 Flink UI 中看觀察是否有 Subtask 發生了數據傾斜。通過 Subtask 的 Records Received、Bytes Received 這類 TPS 指標,就可以知道哪些 Subtask 處理的數據量較大,即哪些 Subtask 發生了數據傾斜。
圖 8 Data Skew

5. 總結

Checkpoint 是 Flink 比較核心的特性,也是經常用到的特性,所以難免會遇到 Checkpoint 慢或者失敗等問題,本文介紹瞭如何查看 Checkpoint 的各項指標,怎樣定位 Checkpoint 失敗的根因,以及導致 Checkpoint 慢的因素。

掃碼關注公衆號:冰山烈焰的黑板報
在這裏插入圖片描述

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