本文主要介紹了下Uber的開源項目jvm-profiler的産生背景,設計原理以及架構, 後面也設計了一套落地方案,用于采集spark、hive任務的資源消耗相關名額,可用于後續分析以及資源調優.
背景
主要介紹針對平台的spark應用程式,在不修改使用者程式的情況下 如何采集其資源和性能名額為後續分析使用,如性能優化,資源使用計價等.
分析挑戰
在應用程式級别關聯大量程序的名額
在分布式環境中,多個 Spark 應用程式運作在同一台伺服器上,每個 Spark 應用程式都有大量的程序(例如數千個執行程式)在許多伺服器上運作.
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLicmbw5SV5YEe5czLcdDMvwVMw8CXyIDMy8CXt92YugXM4FmL0M3Lc9CX6MHc0RHaiojIsJye.png)
- 需要一個解決方案,該解決方案可以為每個程序收集名額,并将它們關聯到每個應用程式的流程中
- 我們不知道這些流程何時啟動以及需要多長時間。為了能夠在這種環境中收集名額,分析器需要随每個程序自動啟動。
使名額收集對任意使用者代碼無幹擾
為了跟上資料基礎設施的不斷增長,我們需要能夠随時測量任何應用程式,而無需更改代碼。
例如,如果我們在 Hadoop 分布式檔案系統 (HDFS) NameNode 上遇到高延遲,我們希望檢查從每個 Spark 應用程式觀察到的延遲,以確定這些問題沒有被複制。由于 NameNode 用戶端代碼嵌入在我們的 Spark 庫中,是以修改其源代碼以添加此特定名額很麻煩。
JVM Profiler 引入
主要受 https://github.com/etsy/statsd-jvm-profiler 啟發建構了更多功能的分析器
JVM Profiler 由三個關鍵功能組成,可以更輕松地收集性能和資源使用名額,然後将這些名額(例如 Apache Kafka)提供給其他系統進行進一步分析:
- java agent: 通過将 Java agent 合并到我們的分析器中,使用者可以以分布式方式收集 JVM 程序的各種名額(例如 CPU/記憶體使用情況)和堆棧跟蹤
- 進階分析功能:JVM Profiler 允許我們跟蹤使用者代碼中的任意 Java 方法和參數,而無需進行任何實際代碼更改。此功能可用于跟蹤 Spark 應用程式的 HDFS NameNode RPC 調用延遲并識别慢速方法調用。它還可以跟蹤每個 Spark 應用程式讀取或寫入的 HDFS 檔案路徑,以識别熱檔案以進行進一步優化。
- 資料分析報告:在 Uber,我們使用分析器向 Kafka topic和 Apache Hive 表報告名額,使資料分析更快更容易。
JVM Profiler 使用場景
- 大小合适的 executor:使用 JVM Profiler 的記憶體名額來跟蹤每個 executor 的實際記憶體使用情況,以便我們可以為 Spark“executor-memory”參數設定正确的值。
- 監控 HDFS NameNode RPC 延遲:我們分析Spark 應用程式中org.apache.hadoop.hdfs.protocolPB.ClientNamenodeProtocolTranslatorPB類上的方法,并識别 NameNode 調用的長時間延遲
- 監控驅動程式丢棄事件: 分析像org.apache.spark.scheduler.LiveListenerBus.onDropEvent這樣的方法來跟蹤 Spark 驅動程式事件隊列變得太長并丢棄事件的情況。
- 跟蹤資料:在org.apache.hadoop.hdfs.protocolPB.ClientNamenodeProtocolTranslatorPB.getBlockLocations和org.apache.hadoop.hdfs.protocolPB.ClientNamenodeProtocolTranslatorPB.addBlock方法上分析檔案路徑參數,以跟蹤 Spark 讀取和寫入的檔案應用
實作細節及可擴充性
為了使實作盡可能無縫,JVM Profiler 具有非常簡單且可擴充的設計。人們可以輕松添加額外的分析器實作來收集更多名額,還可以部署自己的自定義報告器,将名額發送到不同的系統進行資料分析。
一旦程序啟動,JVM Profiler 代碼就會通過Java agent 參數加載到 Java 程序中。它由三個主要部分組成:
- Class File Transformer:在程序内檢測 Java 方法位元組碼以分析任意使用者代碼并将名額儲存在内部名額緩沖區中。
- Metric Profilers
- CPU/Memory Profiler:通過JMX收集 CPU/記憶體使用名額并将其發送給報告者。
- Method Duration Profiler:從名額緩沖區讀取方法持續時間(延遲)名額并發送給報告者。
- Method Argument Profiler: 從名額緩沖區讀取方法參數值并将其發送給報告者。
- Reporters
- Console Reporter: 在控制台輸出中寫入名額
- Kafka Reporter :将名額發送到 Kafka topic中
如何自定義reporter發送名額
使用者可以實作自己的報告器并使用 -javaagent 選項指定它:
-javaagent:jvm-profiler-0.0.5.jar= reporter=com.uber.profiling.reporters.CustomReporter
JVM Profiler 在Uber資料基礎設施內建
基礎設施內建實作:
- 叢集範圍的資料分析:名額首先發送到 Kafka 并攝取到 HDFS,然後使用者使用 Hive/Presto/Spark 進行查詢。
- 實時 Spark 應用程式調試:使用 Flink 實時聚合單個應用程式的資料并寫入MySQL 資料庫,然後使用者可以通過基于 Web 的界面檢視名額。
如何落地的
擴充設計
整體流程:
- spark應用在啟動的時候指定jvm-profiler jar, 運作時收集記憶體,cpu,gc.io等名額,定制實作的profile
- 使用自定的reproter,主要将名額通過http 發送到接收服務
- 接收服務負責将資料寫入kafka
- kafka經flink 消費清洗分别寫入influxdb以及hive中,用于後續展示和分析
- hive 一樣執行時,指定相關參數
- 通過解析/.staging/下job.xml 擷取queryId 及sql相關資訊
- 後續流程一樣
部署
spark: 上傳jvm-profiler jar 包到 hdfs上,送出任務時參數指定
hive: 部署jar到 hiveserver2 節點對應libs下面
總結
參考
https://eng.uber.com/jvm-profiler/
https://github.com/uber-common/jvm-profiler
本文作者: chaplinthink, 關注領域:大資料、基礎架構、系統設計, 一個熱愛學習、分享的大資料工程師