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

weixin_33806914發表於2018-11-30

關鍵要點

  • 持續可靠地執行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\u0026lt;String,Object\u0026gt; metrics)方法和public void close()方法。“profilerName”將是“metrics”資料庫中的度量名稱。

  • 由於InfluxDB使用行協議來儲存鍵值對,我們需要處理由Profiler傳送的Map\u0026lt;String,Object\u0026gt;度量資料,並將它們轉換為可以儲存在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 \u0026quot;heapMemoryCommitted\u0026quot; as Committed, \u0026quot;heapMemoryTotalUsed\u0026quot; as Used from \u0026quot;metrics\u0026quot;.\u0026quot;autogen\u0026quot;.\u0026quot;CpuAndMemory” where “role\u0026quot; = 'driver' AND time \u0026gt; now() – 5m

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

select \u0026quot;heapMemoryCommitted\u0026quot; as Committed, \u0026quot;heapMemoryTotalUsed\u0026quot; as Used from \u0026quot;metrics\u0026quot;.\u0026quot;autogen\u0026quot;.\u0026quot;CpuAndMemory” where \u0026quot;processUuid\u0026quot; =~ /^$executorProcessUuid$/ AND time \u0026gt; 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 \u0026quot;spark.driver.extraJavaOptions=-javaagent:/opt/profiler/jvm-profiler-0.0.9.jar=reporter=com.uber.profiling.reporters.InfluxDBOutputReporter,metricInterval=5000,sampleInterval=5000,ioProfiling=true\u0026quot; --conf \u0026quot;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\u0026quot; --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 \u0026quot;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\u0026quot; --conf \u0026quot;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\u0026quot; --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以及持續整合和交付。你可以通過電子郵件baghel_amit@yahoo.com聯絡Baghel。

檢視英文原文:https://www.infoq.com/articles/spark-application-monitoring-influxdb-grafana

相關推薦:

\"\"
12 月 7 日北京 ArchSummit 全球架構師峰會上,來自Uber的講師徐巨集亮和付靜將分享具有Uber特色的技術話題,“Uber搭建基於Kafka的跨資料中心拷貝平臺”、“Uber外賣平臺國際化架構演化之路”相關經驗與實踐。詳情點選 https://bj2018.archsummit.com/schedule

相關文章