如何用Uber JVM Profiler等可視化工具監控Spark應用程序?

關鍵要點

  • 持續可靠地運行Spark應用程序是一項具有挑戰性的任務,而且需要一個良好的性能監控系統。

-在設計性能監控系統時有三個目標——收集服務器和應用程序指標、在時序數據庫中存儲指標,並提供用於數據可視化的儀表盤。

  • Uber JVM Profiler被用於監控Spark應用程序,用到的其他技術還有InfluxDB(用於存儲時序數據)和Grafana(數據可視化工具)。

  • 性能監控系統可幫助DevOps團隊有效地監控系統,用以滿足應用程序的合規性和SLA。

很多行業都在使用Apache Spark構建大數據處理應用程序。Spark爲此類應用程序提供了隱式數據並行性和容錯性。這類應用程序可以是基於流式處理、批處理、SQL數據集處理或機器學習。Spark通過快速的內存數據處理引擎在集羣中運行這些應用程序,並在數據管道中轉換和處理大量數據。持續可靠地運行這些應用程序是一項具有挑戰性的任務,需要一個良好的性能監控系統。隨着Spark被各行各業廣泛採用,性能監控、度量分析和調優Spark應用程序的問題越來越受到關注。Uber最近開源了他們的JVM Profiler。在本文中,我們將討論如何擴展Uber JVM Profiler,並將其與InfluxDB和Grafana一起用於監控和報告Spark應用程序的性能指標。

Spark應用程序性能監控系統

要最大限度地利用可用資源並儘早發現可能存在的問題,需要一個性能監測系統。監控系統需要爲運行中的系統提供綜合性的狀態報告,並在組件發生故障時發送警報。當我們需要在Spark集羣中運行大規模分佈式系統以及Hadoop生態系統的不同組件時,對細粒度性能監視系統的需求就變得不可或缺。Spark應用程序在共享資源上執行數據的分佈式處理,這使得DevOps團隊的工作變得非常複雜。DevOps團隊必須有效地管理可用資源,並密切監控系統的不同組件,以避免出現宕機。性能監控系統提供的完整堆棧可見性有助於DevOps團隊瞭解系統行爲,並對生產問題做出快速反應。這確保了Spark應用程序的可靠性、可伸縮性和性能。

針對這種複雜系統的理想性能監控系統必須具備以下特性:

  • 監控系統應提供有關集羣內每個組件的細粒度可見性。我們應該能夠獲得有關CPU、內存、存儲、本地文件和HDFS的磁盤I/O、堆棧跟蹤等詳細指標。這些指標有助於快速診斷髮生故障的實例。

  • 監控系統應該爲在Spark上運行的應用程序提供代碼級別度量(例如執行時間、方法的參數等)。這將有助於識別運行較慢的方法、磁盤熱點等。

  • 監控系統應存儲每一秒的指標,並允許我們通過瀏覽不同時間段的數據來分析指標。我們應該能夠對這些數據進行二級和二級解剖。我們應該能夠控制數據保留期,並在需要時輕鬆訪問和分析過去的數據。這有助於分析當前趨勢並預測未來趨勢。

  • 監控系統應該要提供有效的方法,用於從連續收集的大量指標中提取有意義信息。包括使用SQL或API查詢數據、過濾數據、聚合值和應用自定義分析。這有助於輕鬆轉換和更快地分析數據。

  • 監控系統應該能夠方便地訪問從度量數據分析中推導出的信息,可以使用不同的形式(如圖表等)在儀表盤中顯示數據,可以基於主機、時間或作業對數據進行分類,用戶應該能夠進一步深入分析不同的數據點,能夠爲用戶定義的閾值配置警報和通知。這有助於DevOps團隊和組織的其他利益相關者在必要時快速獲得所需的信息。

在本文中,我們將使用開源工具和技術開發一個性能監控系統。Spark應用程序性能監控系統的設計有三個目標:

  1. 收集系統(驅動程序和執行程序)和應用程序代碼的性能指標;

  2. 將這些指標存儲在持久存儲中以進行時序分析(批量和實時);

  3. 以圖表的形式生成度量指標報告。

Apache Spark爲指標提供了一個web-ui和REST API。Spark還提供各種接收器,包括控制檯、JMX、Servlet、Graphite等。還有一些其他可用的開源性能監控工具,如dr-elephant、sparklint、prometheus等。這些工具提供的指標主要是服務器級別的指標,其中有一些也提供應用程序的信息。

Uber JVM Profiler同時收集服務器級別和應用程序的度量指標。它可以從驅動程序、執行程序或任已JVM中收集所有指標(cpu、內存、緩衝池等)。它可以在不修改現有代碼的情況下對其進行增強,因此可以收集有關方法、參數和執行時間的指標。爲了存儲用於時序分析的度量指標,我們將使用InfluxDB,它是一個功能強大的時序數據庫。我們將擴展Uber JVM Profiler,併爲InfluxDB添加一個新的Reporter,這樣就可以通過HTTP API保存度量數據。在圖形化的儀表盤方面,我們將使用Grafana,它將從InfluxDB查詢指標數據。

以下是用於Spark應用性能監控系統的工具和技術的詳細信息。

Uber JVM Profiler

Uber JVM Profiler是一個分佈式的分析器,它從集羣的不同節點收集性能指標和資源利用率指標。它作爲Java代理與應用程序一起運行,並收集不同的度量指標。它將這些指標發佈給指定的Reporter,以進行進一步的分析和報告。Uber JVM Profiler是爲分析Spark應用程序而開發的,但它也可以用於分析任何基於JVM的應用程序。Uber JVM Profiler有三個主要組件:

Profiler:Uber JVM Profiler內置了以下的Profiler:

  • CpuAndMemory Profiler——收集緩衝池(直接和映射)、垃圾回收(計數和時間)、堆內存(已提交和已使用)、非堆內存(已提交和已使用)、CPU(加載和時間)、內存池詳細信息(EdenSpace、SurvivorSpace、TenuredGen、CodeCache、CompressedClassSpace、Metaspace)、vmHWM和vmRSS指標。

  • IO Profiler——收集CPU 統計信息(idle、nice、system、user、iowait)和磁盤IO的讀/寫字節。
    Stacktrace Profiler——收集線程名稱、線程狀態和堆棧跟蹤指標。

  • ProcessInfo Profiler——收集代理版本、JVM類路徑、JVM輸入參數和xmxBytes指標。

  • MethodDuration Profiler——收集方法執行時間的指標,其中包括類名、方法名和進程名。

  • MethodArgument Profiler——收集方法參數的指標,其中包括類名、方法名和進程名。

Transformer:這個Class File Transformer用於增強Java方法的字節碼。

Reporter:可用的Reporter包括:

  • KafkaOutputReporter——將性能指標發送到Kafka主題。

  • FileOutputReporter——將指標寫入文件中。

  • ConsoleOutputReporter——將指標發送到控制檯。

  • RedisOutputReporter——將指標存儲到Redis數據庫。

有關JVM Profiler的更多詳細信息,請參閱Uber的博文。

InfluxDB和Grafana

InfluxDB:InfluxDB是一個開源的時序數據庫,用於存儲和查詢大量帶時間戳的數據。這些數據可以是物聯網傳感器數據、實時分析數據、應用程序指標數據或DevOps監控數據。它通過讓舊數據過期和刪除舊數據進行自動數據生命週期管理。它通過類似SQL的查詢語言、HTTP API和客戶端庫提供寫入和查詢功能。請從這裏獲得更多信息。

Grafana:Grafana是一個開源的度量指標儀表盤和圖形編輯器。Grafana還支持警報和通知。它支持很多數據源,如Graphite、InfluxDB、OpenTSDB、Prometheus、Elasticsearch和CloudWatch。很多儀表盤和插件(包括開源的和商業的)都可以在Grafana的網站上找到。有關Grafana的更多詳細信息,請訪問該網站。

系統架構

Spark應用程序運行在集羣網絡上,集羣網絡可能包含幾個節點到數千個節點。爲了從這個分佈式系統收集指標,並將指標發送到其他系統進行進一步分析,我們需要一個具備鬆散耦合和容錯能力的架構。將指標發佈到Kafka主題是最佳解決方案之一。Uber JVM Profiler附帶了“KafkaOutputReporter”,可用於實現這個目的。另一個解決方案是使用InfluxDB。InfluxDB提供了HTTP API,可用於查詢和寫入數據庫。這個API支持Basic和JWT令牌身份驗證,並支持HTTPS訪問。本文中的“InfluxDBOutputReporter”將通過調用Write HTTP Endpoint來存儲由不同的Profiler收集到的指標。Grafana爲InfluxDB提供了豐富的數據源插件。Grafana使用Query HTTP Endpoint從InfluxDB獲取指標數據,並以圖形和表格的形式在儀表盤上顯示數據。這些圖形和表格以固定的時間間隔自動刷新,時間間隔可以在Grafana中設置。

使用Uber JVM Profiler、InfluxDB和Grafana的Spark應用性能監控系統的架構圖如下圖1所示。

image圖1. 性能監控系統架構圖

技術和工具

下面的表格列出了性能監控系統使用的技術和工具。

image請參閱相關文檔以瞭解如何安裝和配置這些工具。

設計與實現

以下部分介紹了Spark應用程序性能監控系統的設計和實現細節。Uber JVM Profiler從驅動程序和執行程序收集指標,這些指標包含了一些詳細信息,如角色、processUuid和主機。這些信息對於識別不同系統和分析這些系統的指標來說非常有用。在InfluxDB中,我們可以使用這些信息來查詢不同執行程序的性能指標。我們可以將processUuid加入到InfluxDB標籤中,以此來提高查詢性能。首先,我們將在InfluxDB中創建“metrics”數據庫,然後在JVM Profiler代碼庫中添加“InfluxDBOutputReporter”,最後配置Grafana儀表盤。

在InfluxDB中創建metrics數據庫

啓動InfluxDB服務器,默認情況下端口爲8086。在Ubuntu系統中打開一個終端並執行“Influxd”命令。

/user/bin$ sudo influxd

在服務器啓動後,在另一個終端啓動“influx”。然後執行命令創建“metrics”數據庫。

/user/bin$ sudo influx

CREATE DATABASE metrics

實現InfluxDBOutputReporter

我們將在JVM-Profile代碼庫中實現“InfluxDBOutputReporter”。請參閱GitHub上的“Influxdb_reporter”分支的InfluxDBOutputReporter.java文件,以瞭解本節所討論的實現細節。

  • 我們通過Influxdb-java庫與InfluxDB數據庫服務器發生交互。它通過HTTP API讀寫InfluxDB數據庫。更新pom.xml文件,添加Influxdb-java依賴項。

  • 在InfluxDBOutputReporter類中定義InfluxDB數據庫服務器的主機、端口和數據庫屬性。這些屬性的默認值分別爲“127.0.0.1”、“8086”和“metrics”。使用Influxdb-java庫提供的API連接InfluxDB。

  • InfluxDBOutputReporter類需要實現com.uber.profiling.Reporter接口。我們需要覆蓋public void report(String profilerName,Map<String,Object> metrics)方法和public void close()方法。“profilerName”將是“metrics”數據庫中的度量名稱。

  • 由於InfluxDB使用行協議來存儲鍵值對,我們需要處理由Profiler發送的Map<String,Object>度量數據,並將它們轉換爲可以存儲在InfluxDB中的格式。我們可以使用指標中的“name”屬性的值(如果可用)作爲字段名稱。如果“name”屬性不可用,可以使用計數器的值。InfluxDB支持在查詢字段中使用正則表達式,因此查詢這些字段不成問題。

  • 使用Influxdb-java庫提供的API創建Point和Batchpoint,並將Batchpoints寫入InfuxDB數據庫。

  • 要從yaml文件中讀取數據庫連接信息,必須使用com.uber.profiling.YamlConfigProvider和com.uber.profiling.Argument類。在Argument類中添加InfluxDBOutputReporter類的引用,並調用setProperties方法傳入yaml文件中定義的屬性。GitHub的resources/Influxdb.yaml是一個yaml示例文件。

在Grafana中添加數據源和儀表盤

本節將介紹在Grafana中添加度量數據圖表所需的步驟。

啓動Grafana服務器。在Ubuntu上,我們可以執行以下命令。默認端口號爲3000。

sudo service grafana-server start

在瀏覽器中打開http://localhost:3000/,併爲InfluxDB創建數據源。將Name設置爲“InfluxDBDataSource”,Type設置爲“InfluxDB”,InfluxDB的默認URL爲“http://localhost:8086”,數據庫名稱爲“metrics”。

單擊“Graph”創建一個新的儀表盤,單擊“Edit”添加查詢。以下是一個查詢示例。

select "heapMemoryCommitted" as Committed, "heapMemoryTotalUsed" as Used from "metrics"."autogen"."CpuAndMemory” where “role" = 'driver' AND time > now() – 5m

Grafana提供了一些選項,用於定義可在查詢中傳遞的模板變量。這對在儀表盤上顯示來自多個執行程序的數據來說非常有用。例如,我們可以爲“executorProcessUuid”和“timeInterval”創建變量,並在查詢中使用它們,如下所示。

select "heapMemoryCommitted" as Committed, "heapMemoryTotalUsed" as Used from "metrics"."autogen"."CpuAndMemory” where "processUuid" =~ /^$executorProcessUuid$/ AND time > now() - $timeInterval

GitHub提供了一個JSON示例文件Spark-Metrics-Dashboar。可以在Grafana服務器上導入這個文件。在瀏覽器中打開http://localhost:3000/dashboard/import,然後單擊“Upload .json File”。

構建和部署

本節將介紹構建和部署性能監控系統的步驟。可以從GitHub上的“Influxdb_reporter”分支克隆應用程序代碼。

使用以下命令構建帶有“InfluxDBOutputReporter”的JVM Profiler。

mvn clean package

將maven創建的JVM Profiler-0.0.9.jar文件複製到某個目錄(例如/opt/profiler)。我們也可以將Influxdb.yaml放在這個目錄中。

我們將使用Apache Spark附帶的JavaNetworkWordCount應用程序進行profiling,源代碼位於/spark-2.3.1-bin-hadoop2.7/examples/src/main/java/org/apache/spark/examples/streaming中。
要運行JavaNetworkWordCount,我們需要使用以下命令運行Netcat服務器。

nc -lk 9999

轉到/spark-2.3.1-bin-hadoop2.7/sbin目錄,並使用以下命令啓動Master。

./start-master.sh

我們可以從日誌文件中獲取Master的URL。將此URL傳給命令來啓動Worker。

./start-slave.sh -c 2 spark://192.168.1.6:7077

轉到/spark-2.3.1-bin-hadoop2.7/bin目錄並執行以下命令。這個命令將執行JavaNetworkWordCount應用程序,並啓動JVM Profiler。有關參數的詳細信息,請查看Uber JVM Profiler的GitHub README頁面。

spark-submit --master spark://192.168.1.6:7077 --conf "spark.driver.extraJavaOptions=-javaagent:/opt/profiler/jvm-profiler-0.0.9.jar=reporter=com.uber.profiling.reporters.InfluxDBOutputReporter,metricInterval=5000,sampleInterval=5000,ioProfiling=true" --conf "spark.executor.extraJavaOptions=-javaagent:/opt/profiler/jvm-profiler-0.0.9.jar=reporter=com.uber.profiling.reporters.InfluxDBOutputReporter,tag=influxdb,configProvider=com.uber.profiling.YamlConfigProvider,configFile=/opt/profiler/influxdb.yaml,metricInterval=5000,sampleInterval=5000,ioProfiling=true" --class org.apache.spark.examples.streaming.JavaSqlNetworkWordCount ../examples/jars/spark-examples_2.11-2.3.1.jar localhost 9999

或者,我們可以使用yaml文件來運行應用程序。在命令中傳遞“configProvider”和“configFile”參數,如下所示。

spark-submit --master spark://192.168.1.6:7077 --conf "spark.driver.extraJavaOptions=-javaagent:/opt/profiler/jvm-profiler-0.0.9.jar=reporter=com.uber.profiling.reporters.InfluxDBOutputReporter,configProvider=com.uber.profiling.YamlConfigProvider,configFile=/opt/profiler/influxdb.yaml,metricInterval=5000,sampleInterval=5000,ioProfiling=true" --conf "spark.executor.extraJavaOptions=-javaagent:/opt/profiler/jvm-profiler-0.0.9.jar=reporter=com.uber.profiling.reporters.InfluxDBOutputReporter,tag=influxdb,configProvider=com.uber.profiling.YamlConfigProvider,configFile=/opt/profiler/influxdb.yaml,metricInterval=5000,sampleInterval=5000,ioProfiling=true" --class org.apache.spark.examples.streaming.JavaSqlNetworkWordCount ../examples/jars/spark-examples_2.11-2.3.1.jar localhost 9999

轉到“influx”終端並執行以下命令。

use metrics
show measurements

我們將獲取到“metrics”數據庫中的“Measurements”名稱,如下所示。

CpuAndMemory
IO
ProcessInfo
Stacktrace

使用以下命令從CpuAndMemory度量中獲取單個記錄。

select * from CpuAndMemory limit 1

以下是示例儀表盤。

image圖2. 用於Spark指標的Grafana儀表盤示例

優點和缺點

我們在本文中討論的性能監控系統使用Uber JVM Profiler收集系統和應用程序的指標,並將它們存儲在InfluxDB時序數據庫中。時序數據庫提供數據保留策略、連續查詢、靈活的時間聚合以及數百萬條記錄的實時處理和批處理。這些時序數據有助於我們分析過去系統發生的變化、系統當前的行爲方式以及預測未來系統將如何變化。我們可以通過關聯指標來識別故障模式。我們使用Grafana創建了一個儀表盤,幫助我們輕鬆訪問不同類型的指標。DevOps團隊可以使用這些圖形和圖表來關聯不同的指標,以瞭解系統行爲,並識別數據中的熱點。這有助於保持合規性並實現應用程序的SLA。總的來說,該性能監控系統有助於實現系統的持續監控。

這個性能監控系統受限於基於代理的Profiler。基於代理的Profiler會消耗一定量的計算資源。有時可能需要進行故障排除和打補丁,這對於大型分佈式系統來說可能很困難。在生產系統上安裝代理之前,你可能需要先做一些調研工作。我們還必須考慮性能監控系統的安全性、可擴展性和可用性。通過正確設計和調整應用程序和系統,可以解決大多數問題。如果不允許在生產系統上安裝代理,可以考慮使用無代理系統,但它也有自己的侷限性,例如更少的細粒度指標和網絡負載開銷。

總結

對於複雜的Spark應用程序來說,識別、調試、解決生產環境的問題並非易事,我們需要一個有效的性能監控系統來幫助我們解決這些問題。Uber JVM Profiler是一個很好的開源工具,我們可以擴展它,添加用於發佈度量指標的Reporter。不同Profiler收集的Spark應用程序性能指標可以存儲在InfluxDB中。我們在本文中討論的“InfluxDBOutputReporter”通過HTTP API將Spark驅動程序和執行程序的度量指標寫入InfluxDB。Grafana爲InfluxDB提供了一個插件,可以通過HTTP API查詢指標。我們可以爲這些指標創建包含圖表的儀表盤,並以固定的時間間隔自動刷新。此處提供了“InfluxDBOutputReporter”的代碼,此處提供了Spark-InfluxDB-Grafana.json文件。

參考

Uber JVM Profiler——https://eng.uber.com/jvm-profiler/

InfluxDB——https://docs.influxdata.com/influxdb/v1.6/

Grafana——http://docs.grafana.org/

關於作者

Amit Baghel是一名軟件架構師,在圍繞Java生態系統的企業應用程序和產品的設計和開發方面擁有超過17年的經驗。他目前重點關注物聯網、雲計算、大數據解決方案、微服務、DevOps以及持續集成和交付。你可以通過電子郵件[email protected]聯繫Baghel。

查看英文原文:

https://www.infoq.com/articles/spark-application-monitoring-influxdb-grafana

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