作者:田志聲
前言
Flink 是目前最流行的大資料及流式計算架構之一,使用者可以使用 Java/Scala/Python 的 DataStream 接口或者标準 SQL 語言來快速實作一個分布式高可用的流式應用,通過内部的 Java JIT、off-heap 記憶體管理等技術優化性能,并且有完整的 Source、Sink、WebUI、Metrics 等功能內建,讓 Flink 幾乎成為了流式計算的事實标準。
但是當處理海量資料的時候,很容易出現各種異常和性能瓶頸,這時我們需要優化系統性能時,常常需要分析程式運作行為和性能瓶頸。Profiling 技術是一種在應用運作時收集程式相關資訊的動态分析手段,常用的 JVM Profiler 可以從多個方面對程式進行動态分析,如 CPU、Memory、Thread、Classes、GC 等,其中 CPU Profiling 的應用最為廣泛。CPU Profiling 經常被用于分析代碼的執行熱點,如“哪個方法占用 CPU 的執行時間最長”、“每個方法占用 CPU 的比例是多少”等等,通過 CPU Profiling 得到上述相關資訊後,研發人員就可以輕松針對熱點瓶頸進行分析和性能優化,進而突破性能瓶頸,大幅提升系統的吞吐量。
本文介紹我們在做性能優化常用的火焰圖以及為如何內建火焰圖到通用的 Flink 作業中。
火焰圖介紹
火焰圖是《性能之巅》作者以及 DTrace 等一系列 Linux 系統優化工具作者 Brendan Gregg 大神的作品之一,可以非常清晰地展示應用程式的函數調用棧以及函數調用時間占比,基本原理是通過各種 agent 在程式運作時采樣并輸出日志,使用 FlameGraph 工具把日志提取出來輸出可在浏覽器互動式檢視的 SVG圖檔。
Uber 開源了 jvm-profiler 項目,介紹如何為 Spark 應用和 Java 應用添加火焰圖支援,但是目前 Flink 社群和 jvm-profiler 官網都還沒有相關的使用教程。
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLicGcq5SMkZTY4QWZ3MGOmRWZxIWOxM2Y0UTMhBTYmZzYyEWZ38CX5d2bs92Yl1iclB3bsVmdlR2LcNWaw9CXt92Yu4GZjlGbh5yYjV3Lc9CX6MHc0RHaiojIsJye.jpg)
實際上基于 JVM 的程式都可以使用這個工具,本文将基于 jvm-profiler 來介紹如何生成 Flink 作業的火焰圖。
下載下傳和編譯 jvm-profiler
git clone git clone https://github.com/uber-common/jvm-profiler.git
mvn clean install -DskipTests=true -Dcheckstyle.skip -Dfast -T 8C
編譯好了之後,将項目 target 目錄下的 jvm-profiler-1.0.0.jar 複制一份到 flink 的 lib 目錄下面。
cp target/jvm-profiler-1.0.0.jar /usr/local/flink-1.11.1/lib
下載下傳 FlameGraph
由于 jvm-profiler 支援生成火焰圖需要的日志檔案,将日志轉化成互動式 SVG 圖檔還是使用 Brendan Gregg 的FlameGraph 工具。
git clone https://github.com/brendangregg/FlameGraph.git
下載下傳項目源碼即可,後面會使用 flamegraph.pl 工具來生成圖檔檔案。
配置 Flink
對于 Flink 應用,我們隻需要在 TaskManager 中注入打點的 Java agent 即可,這裡測試,我就使用本地 standalone 模式,修改 Flink conf 目錄下的 flink-conf.yaml 檔案,添加一下如下配置:
env.java.opts.taskmanager: "-javaagent:/usr/local/flink-1.11.1/lib/jvm-profiler-1.0.0.jar=sampleInterval=50"
目前最小的采樣間隔就是 50 毫秒,然後啟動叢集和運作一個 Flink 作業:
./bin/start-cluster.sh
//運作一個作業
./bin/flink run ./examples/streaming/StateMachineExample.jar
運作之後可以看到 TaskManager 的 stdout 裡面列印如下:
因為已經注入 Java agent,是以在标準輸出中會定期添加火焰圖所需要的打點資料,然後使用下面的指令提取相關日志,并且使用 jvm-profiler 和 FlameGraph 提供的工具來生成 SVG 圖檔檔案。
//1、提取 stdout 檔案中的相關日志
cat log/flink-zhisheng-taskexecutor-0-zhisheng.out | grep "ConsoleOutputReporter - Stacktrace:" | awk '{print substr($0,37)}' > stacktrace.json
//2、在 jvm-profiler 目錄下執行下面指令
python ./stackcollapse.py -i /usr/local/flink-1.11.1/stacktrace.json > stacktrace.folded
//3、在 FlameGraph 目錄下執行下面指令生成 SVG 圖檔
./flamegraph.pl /Users/zhisheng/Documents/github/jvm-profiler/stacktrace.folded > stacktrace.svg
然後用浏覽器打開剛才生成的 SVG 圖檔就可以看到火焰圖資訊。
總結
本文主要目的在于教大家如何利用 jvm-profiler 去生成 Flink 作業的運作火焰圖,這樣可以在遇到性能瓶頸問題的時候會很友善大家去定位問題,關于如何去讀懂生成的火焰圖,後面可以再分享系列文章。
參考資料
- JVM CPU Profiler技術原理及源碼深度解析
- jvm-profile
更多 Flink 技術交流可加入 Apache Flink 社群釘釘交流群: