什么是 JMX?(Trino JMX 實(shí)戰(zhàn)講解)
一、概述
JMX 是 Java Management Extensions(Java管理擴(kuò)展) 的縮寫,它是 Java 平臺(tái)上用于管理和監(jiān)控應(yīng)用程序、系統(tǒng)和網(wǎng)絡(luò)資源的一種標(biāo)準(zhǔn)化的管理和監(jiān)控框架。JMX 提供了一種標(biāo)準(zhǔn)的方式,通過這種方式,開發(fā)人員可以暴露應(yīng)用程序中的各種管理和監(jiān)控信息,然后可以使用 JMX 客戶端工具或應(yīng)用程序來訪問和操作這些信息。
JMX 允許開發(fā)人員定義稱為 MBeans(Managed Beans)的管理組件,這些組件充當(dāng)被管理資源的代理,并通過 JMX 接口公開資源的操作和屬性。通過 MBeans,您可以監(jiān)控和管理各種 Java 應(yīng)用程序和服務(wù)器的性能、狀態(tài)和配置。
JMX 主要用于以下一些方面:
- 監(jiān)控:可以使用 JMX 來監(jiān)視應(yīng)用程序的性能指標(biāo),例如內(nèi)存使用、線程數(shù)、請求處理速度等。這對于實(shí)時(shí)性能分析和故障排除非常有幫助。
- 管理:JMX 允許您在運(yùn)行時(shí)管理應(yīng)用程序,例如修改配置參數(shù)、重新加載資源、觸發(fā)操作等。這有助于實(shí)現(xiàn)動(dòng)態(tài)管理和配置。
- 遠(yuǎn)程管理:JMX 支持遠(yuǎn)程訪問,這意味著您可以在不必物理接觸應(yīng)用程序的情況下,從遠(yuǎn)程位置監(jiān)控和管理應(yīng)用程序。
- 自定義監(jiān)控:您可以編寫自定義 MBeans 來公開特定于您的應(yīng)用程序的監(jiān)控?cái)?shù)據(jù)和操作,以滿足特定的管理需求。
總之,JMX 提供了一個(gè)強(qiáng)大的框架,用于管理和監(jiān)控 Java 應(yīng)用程序,這對于確保應(yīng)用程序的穩(wěn)定性和性能至關(guān)重要。它廣泛用于企業(yè)級應(yīng)用程序和服務(wù)器,如應(yīng)用程序服務(wù)器、數(shù)據(jù)庫服務(wù)器和中間件。
二、JMX 原理
圖片
從圖中我們可以看到,JMX的結(jié)構(gòu)一共分為三層:
- 基礎(chǔ)層:主要是 MBean,被管理的資源。
MBean 分為如下四種,我接下來主要介紹 standard MBean
類型 | 描述 |
standard MBean | 這種類型的MBean最簡單,它能管理的資源(包括屬性,方法,時(shí)間)必須定義在接口中,然后MBean必須實(shí)現(xiàn)這個(gè)接口。它的命名也必須遵循一定的規(guī)范,例如我們的MBean為Hello,則接口必須為HelloMBean。 |
dynamic MBean | 必須實(shí)現(xiàn)javax.management.DynamicMBean接口,所有的屬性,方法都在運(yùn)行時(shí)定義 |
open MBean | 此MBean的規(guī)范還不完善,正在改進(jìn)中 |
model MBean | 與標(biāo)準(zhǔn)和動(dòng)態(tài)MBean相比,你可以不用寫MBean類,只需使用javax.management.modelmbean.RequiredModelMBean即可。RequiredModelMBean實(shí)現(xiàn)了ModelMBean接口,而ModelMBean擴(kuò)展了DynamicMBean接口,因此與DynamicMBean相似,Model MBean的管理資源也是在運(yùn)行時(shí)定義的。與DynamicMBean不同的是,DynamicMBean管理的資源一般定義在DynamicMBean中(運(yùn)行時(shí)才決定管理那些資源),而model MBean管理的資源并不在MBean中,而是在外部(通常是一個(gè)類),只有在運(yùn)行時(shí),才通過set方法將其加入到model MBean中。后面的例子會(huì)有詳細(xì)介紹 |
- 適配層:MBeanServer,主要是提供對資源的注冊和管理。
- 接入層:提供遠(yuǎn)程訪問的入口。
三、實(shí)戰(zhàn)操作(開啟 Trino JMX)
1)環(huán)境部署
Trino官方文檔:https://trino.io/docs/current/
這里為了快速部署就選擇docke-compose部署了。
git clone https://gitee.com/hadoop-bigdata/docker-compose-presto.git
cd docker-compose-presto
# 啟動(dòng)服務(wù)
docker-compose -f docker-compose.yaml up -d
# 查看
docker-compose -f docker-compose.yaml ps
2)開啟 Trino JMX
官方文檔:https://trino.io/docs/current/admin/jmx.html
1、配置 config.properties
jmx.rmiregistry.port=9080
jmx.rmiserver.port=9081
參數(shù)解釋:
- jmx.rmiregistry.port:指定jmx RMI注冊表的端口。JMX客戶端應(yīng)該連接到此端口。
- jmx.rmiserver.port:指定jmx RMI服務(wù)器的端口。Trino導(dǎo)出許多指標(biāo),這些指標(biāo)對于通過JMX進(jìn)行監(jiān)控非常有用。
2、配置 jvm.config
-Dcom.sun.management.jmxremote.rmi.port=9081
jmx.rmiregistry.port、jmx.rmiserver.port 和 -Dcom.sun.management.jmxremote.rmi.port 這三者都涉及到 Java Management Extensions (JMX)和遠(yuǎn)程管理的端口配置,但它們各自在不同的上下文中起作用:
- jmx.rmiregistry.port:這個(gè)屬性指定了 RMI(Remote Method Invocation:遠(yuǎn)程方法調(diào)用) 注冊表(RMI Registry)的端口號。RMI 注冊表用于注冊 JMX 服務(wù),以便客戶端可以查找并連接到 JMX 服務(wù)。通常情況下,RMI 注冊表使用默認(rèn)端口號 1099。通過設(shè)置 jmx.rmiregistry.port 屬性,你可以指定 RMI 注冊表使用的不同端口號,以防止端口沖突或增加安全性。
- jmx.rmiserver.port:這個(gè)屬性指定了 JMX 服務(wù)本身的 RMI 通信端口號。JMX 服務(wù)使用 RMI 進(jìn)行遠(yuǎn)程通信,客戶端通過這個(gè)端口與 JMX 服務(wù)通信。通常情況下,JMX 服務(wù)也使用默認(rèn)的端口號 1099。通過設(shè)置 jmx.rmiserver.port 屬性,你可以指定 JMX 服務(wù)的 RMI 端口號。
- -Dcom.sun.management.jmxremote.rmi.port:這是 Java 系統(tǒng)屬性,用于配置 JMX 遠(yuǎn)程連接的 RMI 端口號。它指定了客戶端將用來連接到 JMX 服務(wù)的 RMI 端口號。通常情況下,如果不顯式設(shè)置,它會(huì)使用與 jmx.rmiserver.port 相同的端口號。但你也可以使用這個(gè)系統(tǒng)屬性來指定不同的端口號,以確??蛻舳丝梢赃B接到正確的端口。
這三者之間的關(guān)系是:
jmx.rmiregistry.port 和 jmx.rmiserver.port 分別指定 RMI 注冊表和 JMX 服務(wù)的端口號。-Dcom.sun.management.jmxremote.rmi.port 可以用來指定客戶端連接到 JMX 服務(wù)時(shí)所使用的 RMI 端口號,它通常設(shè)置為與 jmx.rmiserver.port 相同的端口號,但你也可以根據(jù)需要將其設(shè)置為不同的端口號。
3、重新啟動(dòng)服務(wù)
docker-compose -f docker-compose.yaml up -d
docker-compose -f docker-compose.yaml ps
4、獲取監(jiān)控?cái)?shù)據(jù)
curl -s -H "X-Trino-User:admin" http://192.168.182.110:30080/v1/jmx/mbean
圖片
通過jmx 接口就可以獲取監(jiān)控?cái)?shù)據(jù)了/v1/jmx/mbean,但是數(shù)據(jù)很多,其實(shí)我們可以拿一些我們需要的指標(biāo)數(shù)據(jù)即可。接下來我們通過jq 拿到各項(xiàng)監(jiān)控的子接口。jq 命令的使用可以參考我這篇文章:Linux jq 命令講解與實(shí)戰(zhàn)操作(json字符串解析工具)
# coodinator
curl -s -H "X-Trino-User:admin" http://192.168.182.110:30080/v1/jmx/mbean|jq '.[].objectName'
圖片
訪問具體接口指標(biāo)
# 內(nèi)存指標(biāo)接口
curl -s -H "X-Trino-User:admin" http://192.168.182.110:30080/v1/jmx/mbean|jq '.[].objectName'|grep -i memory
# 指標(biāo)名稱
curl -s -H "X-Trino-User:admin" http://192.168.182.110:30080/v1/jmx/mbean/java.lang:type=Memory|jq '.attributes[].name'
# 指標(biāo)值
curl -s -H "X-Trino-User:admin" http://192.168.182.110:30080/v1/jmx/mbean/java.lang:type=Memory|jq '.attributes[].value'
# 指標(biāo)名稱
curl -s -H "X-Trino-User:admin" http://192.168.182.110:30080/v1/jmx/mbean/trino.memory:type=MemoryPool,name=general|jq '.attributes[].name'
# 指標(biāo)值
curl -s -H "X-Trino-User:admin" http://192.168.182.110:30080/v1/jmx/mbean/trino.memory:type=MemoryPool,name=general|jq '.attributes[].value'
圖片
# worker 節(jié)點(diǎn),coodinator與worker節(jié)點(diǎn)的指標(biāo)會(huì)有些不一樣
curl -s -H "X-Trino-User:admin" http://192.168.182.110:49153/v1/jmx/mbean|jq '.[].objectName'
# 獲取內(nèi)存接口
curl -s -H "X-Trino-User:admin" http://192.168.182.110:49153/v1/jmx/mbean|jq '.[].objectName'|grep -i memory
# 指標(biāo)名稱
curl -s -H "X-Trino-User:admin" http://192.168.182.110:30080/v1/jmx/mbean/trino.memory:type=MemoryPool,name=general|jq '.attributes[].name'
# 指標(biāo)值
curl -s -H "X-Trino-User:admin" http://192.168.182.110:30080/v1/jmx/mbean/trino.memory:type=MemoryPool,name=general|jq '.attributes[].value'
圖片
3)通過 jconsole 連接 JMX
JConsole 是一個(gè)基于JMX的GUI工具,用于連接正在運(yùn)行的JVM,不過此JVM需要使用可管理的模式啟動(dòng)。如果要把一個(gè)應(yīng)用以可管理的形式啟動(dòng),可以在啟動(dòng)是設(shè)置 com.sun.management.jmxremote。
找到j(luò)ava安裝bin目錄,目錄下有個(gè)jconsole可執(zhí)行文件,雙擊點(diǎn)擊打開。
圖片
也可以通過 VisualVM 連接 JMX 查看數(shù)據(jù)
圖片
4)常用的 Trino 指標(biāo)接口和指標(biāo)
查詢所有jmx子接口:
curl -s -H "X-Trino-User:admin" http://192.168.182.110:30080/v1/jmx/mbean|jq '.[].objectName'
# 查詢指標(biāo)名稱和值,示例如下:
# 指標(biāo)名稱
curl -s -H "X-Trino-User:admin" http://192.168.182.110:30080/v1/jmx/mbean/java.lang:type=Memory|jq '.attributes[].name'
# 指標(biāo)值
curl -s -H "X-Trino-User:admin" http://192.168.182.110:30080/v1/jmx/mbean/java.lang:type=Memory|jq '.attributes[].value'
以下就是常用的指標(biāo)接口和指標(biāo)說明:
指標(biāo)接口 | 指標(biāo) | 說明 | 指標(biāo)范圍 |
java.lang:type=Memory | HeapMemoryUsage | JVM內(nèi)存使用量。 | Worker 和 Coodinator |
java.lang:type=Memory | NonHeapMemoryUsage | 非堆內(nèi)存使用量。 | worker 和 Coodinator |
trino.execution:name=QueryManager | QueuedQueries | 排隊(duì)數(shù) | Coodinator |
trino.execution:name=QueryManager | RunningQueries | 正在運(yùn)行的查詢總數(shù) | Coodinator |
trino.execution:name=QueryManager | ExternalFailures.OneMinute.Count | 每分鐘外部異常導(dǎo)致的失敗查詢數(shù)。 | Coodinator |
trino.execution:name=QueryManager | SubmittedQueries.OneMinute.Count | 每分鐘提交的查詢總數(shù)。 | Coodinator |
trino.execution:name=QueryManager | CanceledQueries.OneMinute.Count | 已取消查詢的數(shù)。 | Coodinator |
trino.execution:name=QueryManager | InsufficientResourcesFailures.OneMinute.Count | 每分鐘資源不足導(dǎo)致的失敗查詢數(shù)。 | Coodinator |
trino.execution:name=QueryManager | UserErrorFailures.OneMinute.Count | 每分鐘異常導(dǎo)致的失敗查詢數(shù)。 | Coodinator |
trino.execution:name=QueryManager | CompletedQueries.OneMinute.Count | 已完成查詢的總數(shù)。 | Coodinator |
trino.execution:name=SqlTaskManager | FailedTasks.OneMinute.Count | 每分鐘失敗的Task數(shù)目。 | Coodinator |
trino.execution:name=SqlTaskManager | InputDataSize.OneMinute.Count | 每分鐘Task輸入數(shù)據(jù)量。 | Coodinator |
trino.execution:name=SqlTaskManager | InputPositions.OneMinute.Count | 每分鐘Task輸入數(shù)據(jù)行數(shù)。 | Coodinator |
trino.execution:name=SqlTaskManager | OutputDataSize.OneMinute.Count | 每分鐘Task輸出數(shù)據(jù)量。 | Coodinator |
trino.execution:name=SqlTaskManager | OutputPositions.OneMinute.Count | 每分鐘Task輸出數(shù)據(jù)行數(shù)。 | Coodinator |
trino.memory:type=MemoryPool,name=general | FreeBytes | 節(jié)點(diǎn)內(nèi)存池可用內(nèi)存。 | worker 和 Coodinator |
trino.memory:type=MemoryPool,name=general | MaxBytes | 節(jié)點(diǎn)內(nèi)存池最大內(nèi)存(JVM*70%)。 | worker 和 Coodinator |
trino.memory:type=MemoryPool,name=general | ReservedBytes | 節(jié)點(diǎn)內(nèi)存池reserved內(nèi)存。 | worker 和 Coodinator |
trino.memory:type=MemoryPool,name=general | ReservedRevocableBytes | 節(jié)點(diǎn)內(nèi)存池revocable reserved內(nèi)存。 | worker 和 Coodinator |
trino.memory:type=ClusterMemoryPool,name=general | ReservedRevocableDistributedBytes | 集群內(nèi)存池revocable reserved內(nèi)存。 | Coodinator |
trino.memory:name=ClusterMemoryManager | QueriesKilledDueToOutOfMemory | oom killed的查詢總數(shù)。 | Coodinator |
trino.memory:type=ClusterMemoryPool,name=general | TotalDistributedBytes | 集群內(nèi)存池總內(nèi)存。 | Coodinator |
trino.memory:type=ClusterMemoryPool,name=general | ReservedDistributedBytes | 集群內(nèi)存池reserved內(nèi)存。 | Coodinator |
trino.memory:name=ClusterMemoryManager | ClusterUserMemoryReservation | 集群reserved user memory。 | Coodinator |
trino.memory:name=ClusterMemoryManager | ClusterTotalMemoryReservation | 集群reserved內(nèi)存。 | Coodinator |
trino.memory:name=ClusterMemoryManager | NumberOfLeakedQueries | 集群內(nèi)存泄漏的查詢總數(shù)。 | Coodinator |
trino.memory:name=ClusterMemoryManager | ClusterMemoryBytes | 集群總內(nèi)存。 | Coodinator |
trino.execution.executor:name=TaskExecutor | WaitingSplits | 任務(wù)執(zhí)行器上等待的splits數(shù)。 | Coodinator |
trino.execution.executor:name=TaskExecutor | RunningSplits | 任務(wù)執(zhí)行器運(yùn)行的splits數(shù)。 | Coodinator |
trino.execution.executor:name=TaskExecutor | RunningSplits | 任務(wù)執(zhí)行器總splits數(shù)。 | Coodinator |
上面只是開啟了 Trino JMX,指標(biāo)數(shù)據(jù)也采集了,怎么展示呢?下一篇文章重點(diǎn)講解通過 JMX-Exporter 采集數(shù)據(jù),然后通過 Prometheus 拉取JMX采集的數(shù)據(jù),最后通過Grafana展示。