使用 jvm-profiler 分析 spark 記憶體使用
阿新 • • 發佈:2018-12-13
文章目錄
背景
在生產環境中,為了提高任務提交的響應速度,我們研發了類似 Spark Jobserver 的服務,各種型別的 spark 任務複用已經啟動的 Spark Application,避免了 sparkContext 初始化冷啟動的過程。
可複用Spark服務的記憶體是固定的,因此又開放了使用者自定義 Executor 記憶體的許可權,使用者為了避免自己的任務因記憶體不足而失敗,往往會把記憶體設定的很大,從而帶來了記憶體濫用的問題。
jvm-profiler
一般來說監控 spark 記憶體有2種方式
- 通過 Spark ListenerBus 獲取 Executor 內部的記憶體使用情況 ,現在能獲取的相關資訊還比較少,在 https://github.com/apache/spark/pull/21221 合進來後就能採集到executor 記憶體各個邏輯分割槽的使用情況。
- 通過 Spark Metrics 將 JVM 資訊傳送到指定的 sink,使用者也可以自定義 Sink 比如傳送到 kafka/Redis。
Uber 最近開源了 jvm-profiler,採集分散式JVM應用資訊,可以用於 debug CPU/mem/io 或者方法呼叫的時間等。比如調整Spark JVM 記憶體大小,監控 HDFS Namenode RPC 延時,分析資料血緣關係。
應用於 Spark 比較簡單
每5S採集一次JVM資訊,傳送到 kafka profiler_CpuAndMemory topic
hdfs dfs -put jvm-profiler-0.0.9.jar hdfs://hdfs_url/lib/jvm-profiler-0.0.9.jar --conf spark.jars=hdfs://hdfs_url/lib/jvm-profiler-0.0.9.jar --conf spark.executor.extraJavaOptions=-javaagent:jvm-profiler-0.0.9.jar=reporter=com.uber.profiling.reporters.KafkaOutputReporter,metricInterval=5000,brokerList=brokerhost:9092,topicPrefix=profiler_
消費後存入HDFS用於分析。
分析
hive 表結構
app_id | process_id | role | heap_mem_max | heap_mem_used | process_cpu_load | epoch_millis |
---|
對使用者自定義記憶體的任務進行分析
使用者自定義記憶體排程任務,75%的任務記憶體使用率低於80%,可以進行優化。
使用者自定義記憶體開發任務,45%的任務記憶體使用率低於20%,使用者存在不良使用習慣。
總結
通過採集 jvm 的最大使用值和設定值,可以解決下述問題。
- 記憶體濫用
- 監控應用記憶體使用趨勢,防止資料增長導致記憶體不足
- Spark Executor 預設記憶體設定不合理
根據應用的使用情況預計記憶體減少
- executor 預設記憶體減少10%,平均每個任務能釋放 60G 記憶體
- 自定義記憶體排程任務利用率提高到 70%,平均每個任務能釋放 450G 記憶體
- 自定義記憶體開發任務利用率提高到 70%,平均每個任務能釋放 550G 記憶體
最後對預設引數進行調整,並後臺巡檢對記憶體使用率較低的任務傳送通知後,叢集整體記憶體利用率提高了20%左右,如下圖所示:
對預設記憶體進行調整:
參考
JVM Profiler: An Open Source Tool for Tracing Distributed JVM Applications at Scale