1. 程式人生 > >使用 jvm-profiler 分析 spark 記憶體使用

使用 jvm-profiler 分析 spark 記憶體使用

文章目錄

背景

在生產環境中,為了提高任務提交的響應速度,我們研發了類似 Spark Jobserver 的服務,各種型別的 spark 任務複用已經啟動的 Spark Application,避免了 sparkContext 初始化冷啟動的過程。

可複用Spark服務的記憶體是固定的,因此又開放了使用者自定義 Executor 記憶體的許可權,使用者為了避免自己的任務因記憶體不足而失敗,往往會把記憶體設定的很大,從而帶來了記憶體濫用的問題。

jvm-profiler

一般來說監控 spark 記憶體有2種方式

  1. 通過 Spark ListenerBus 獲取 Executor 內部的記憶體使用情況 ,現在能獲取的相關資訊還比較少,在 https://github.com/apache/spark/pull/21221 合進來後就能採集到executor 記憶體各個邏輯分割槽的使用情況。
  2. 通過 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 的最大使用值和設定值,可以解決下述問題。

  1. 記憶體濫用
  2. 監控應用記憶體使用趨勢,防止資料增長導致記憶體不足
  3. Spark Executor 預設記憶體設定不合理

根據應用的使用情況預計記憶體減少

  • executor 預設記憶體減少10%,平均每個任務能釋放 60G 記憶體
  • 自定義記憶體排程任務利用率提高到 70%,平均每個任務能釋放 450G 記憶體
  • 自定義記憶體開發任務利用率提高到 70%,平均每個任務能釋放 550G 記憶體

最後對預設引數進行調整,並後臺巡檢對記憶體使用率較低的任務傳送通知後,叢集整體記憶體利用率提高了20%左右,如下圖所示:
在這裡插入圖片描述
在這裡插入圖片描述

對預設記憶體進行調整:
在這裡插入圖片描述

參考

JVM Profiler: An Open Source Tool for Tracing Distributed JVM Applications at Scale