- 簡介
- 啟用 JMX Remote
- 使用 JMX Remote Ant 任務管理 Tomcat
- JMXAccessorOpenTask - JMX 開啟連線任務
- JMXAccessorGetTask:取得屬性值 Ant 任務
- JMXAccessorSetTask:設定屬性值 Ant 任務
- JMXAccessorInvokeTask:呼叫 MBean 作業 Ant 任務
- JMXAccessorQueryTask:查詢 MBean Ant 任務
- JMXAccessorCreateTask:遠端建立 MBean Ant 任務
- JMXAccessorUnregisterTask:遠端取消註冊 MBean Ant 任務
- JMXAccessorCondition:表達條件
- JMXAccessorEqualsCondition:等於 MBean Ant 條件
- 使用 JMXProxyServlet
監控和管理 Tomcat
目錄
簡介
監控是系統管理的一項重要面向。查看正在執行的伺服器、取得一些統計資料或重新設定應用程式的某些面向,都是日常管理任務。
啟用 JMX Remote
注意:僅當您要遠端監控 Tomcat 時,才需要此組態。如果您要使用與 Tomcat 執行相同的使用者,在本地監控 Tomcat,則不需要此組態。
Oracle 網站包含選項清單,以及如何在 Java 11 上組態 JMX Remote: http://docs.oracle.com/javase/6/docs/technotes/guides/management/agent.html。
以下是 Java 11 的快速組態指南
將下列參數新增到 Tomcat 的 setenv.bat
腳本(有關詳細資訊,請參閱 RUNNING.txt)。
注意:此語法適用於 Microsoft Windows。指令必須在同一行。換行僅為增加可讀性。如果 Tomcat 以 Windows 服務執行,請使用其組態對話方塊設定服務的 java 選項。對於 Linux、MacOS 等,請從行首移除 "set "
。
set CATALINA_OPTS=-Dcom.sun.management.jmxremote.port=%my.jmx.port%
-Dcom.sun.management.jmxremote.rmi.port=%my.rmi.port%
-Dcom.sun.management.jmxremote.ssl=false
-Dcom.sun.management.jmxremote.authenticate=false
如果您未設定 com.sun.management.jmxremote.rmi.port
,JSR 160 JMX-Adaptor 將隨機選取一個埠,這可能會讓您難以組態防火牆以允許存取。
如果您需要 TLS
- 變更並新增此內容
-Dcom.sun.management.jmxremote.ssl=true -Dcom.sun.management.jmxremote.registry.ssl=true
- 若要組態通訊協定和/或加密套件,請使用
-Dcom.sun.management.jmxremote.ssl.enabled.protocols=%my.jmx.ssl.protocols% -Dcom.sun.management.jmxremote.ssl.enabled.cipher.suites=%my.jmx.cipher.suites%
- 若要使用用戶端憑證驗證,請使用
-Dcom.sun.management.jmxremote.ssl.need.client.auth=%my.jmx.ssl.clientauth%
如果您需要授權(強烈建議始終將 TLS 與驗證搭配使用)
- 變更並新增此內容
-Dcom.sun.management.jmxremote.authenticate=true -Dcom.sun.management.jmxremote.password.file=../conf/jmxremote.password -Dcom.sun.management.jmxremote.access.file=../conf/jmxremote.access
- 編輯存取授權檔案 $CATALINA_BASE/conf/jmxremote.access
monitorRole readonly controlRole readwrite
- 編輯密碼檔案 $CATALINA_BASE/conf/jmxremote.password
提示:密碼檔案應為唯讀,且僅供 Tomcat 執行的作業系統使用者存取。
monitorRole tomcat controlRole tomcat
- 或者,您可以使用下列方式組態 JAAS 登入模組
-Dcom.sun.management.jmxremote.login.config=%login.module.name%
如果您需要指定一個主機名稱,以用於傳送給用戶端的 RMI stub(例如,因為必須用於連線的公用主機名稱與本機主機名稱不同),則您可以設定
set CATALINA_OPTS=-Djava.rmi.server.hostname
如果您需要為 JMX 服務指定特定介面以進行繫結,則您可以設定
set CATALINA_OPTS=-Dcom.sun.management.jmxremote.host
使用 JMX Remote Ant 任務管理 Tomcat
若要簡化使用 Ant 的 JMX,我們提供了一組可與 antlib 搭配使用的任務。
antlib:將您的 catalina-ant.jar 從 $CATALINA_HOME/lib 複製到 $ANT_HOME/lib。
下列範例顯示 JMX Accessor 的使用方式
注意: name
屬性值會在此處換行以提高可讀性。它必須在同一行,沒有空格。
<project name="Catalina Ant JMX"
xmlns:jmx="antlib:org.apache.catalina.ant.jmx"
default="state"
basedir=".">
<property name="jmx.server.name" value="localhost" />
<property name="jmx.server.port" value="9012" />
<property name="cluster.server.address" value="192.168.1.75" />
<property name="cluster.server.port" value="9025" />
<target name="state" description="Show JMX Cluster state">
<jmx:open
host="${jmx.server.name}"
port="${jmx.server.port}"
username="controlRole"
password="tomcat"/>
<jmx:get
name=
"Catalina:type=IDataSender,host=localhost,
senderAddress=${cluster.server.address},senderPort=${cluster.server.port}"
attribute="connected"
resultproperty="IDataSender.backup.connected"
echo="false"
/>
<jmx:get
name="Catalina:type=ClusterSender,host=localhost"
attribute="senderObjectNames"
resultproperty="senderObjectNames"
echo="false"
/>
<!-- get current maxActiveSession from ClusterTest application
echo it to Ant output and store at
property <em>clustertest.maxActiveSessions.original</em>
-->
<jmx:get
name="Catalina:type=Manager,context=/ClusterTest,host=localhost"
attribute="maxActiveSessions"
resultproperty="clustertest.maxActiveSessions.original"
echo="true"
/>
<!-- set maxActiveSession to 100
-->
<jmx:set
name="Catalina:type=Manager,context=/ClusterTest,host=localhost"
attribute="maxActiveSessions"
value="100"
type="int"
/>
<!-- get all sessions and split result as delimiter <em>SPACE</em> for easy
access all session ids directly with Ant property sessions.[0..n].
-->
<jmx:invoke
name="Catalina:type=Manager,context=/ClusterTest,host=localhost"
operation="listSessionIds"
resultproperty="sessions"
echo="false"
delimiter=" "
/>
<!-- Access session attribute <em>Hello</em> from first session.
-->
<jmx:invoke
name="Catalina:type=Manager,context=/ClusterTest,host=localhost"
operation="getSessionAttribute"
resultproperty="Hello"
echo="false"
>
<arg value="${sessions.0}"/>
<arg value="Hello"/>
</jmx:invoke>
<!-- Query for all application manager.of the server from all hosts
and bind all attributes from all found manager MBeans.
-->
<jmx:query
name="Catalina:type=Manager,*"
resultproperty="manager"
echo="true"
attributebinding="true"
/>
<!-- echo the create properties -->
<echo>
senderObjectNames: ${senderObjectNames.0}
IDataSender.backup.connected: ${IDataSender.backup.connected}
session: ${sessions.0}
manager.length: ${manager.length}
manager.0.name: ${manager.0.name}
manager.1.name: ${manager.1.name}
hello: ${Hello}
manager.ClusterTest.0.name: ${manager.ClusterTest.0.name}
manager.ClusterTest.0.activeSessions: ${manager.ClusterTest.0.activeSessions}
manager.ClusterTest.0.counterSend_EVT_SESSION_EXPIRED:
${manager.ClusterTest.0.counterSend_EVT_SESSION_EXPIRED}
manager.ClusterTest.0.counterSend_EVT_GET_ALL_SESSIONS:
${manager.ClusterTest.0.counterSend_EVT_GET_ALL_SESSIONS}
</echo>
</target>
</project>
import:使用 <import file="${CATALINA.HOME}/bin/catalina-tasks.xml" /> 匯入 JMX Accessor 專案,並使用 jmxOpen、jmxSet、jmxGet、jmxQuery、jmxInvoke、jmxEquals 和 jmxCondition 參照這些工作。
JMXAccessorOpenTask - JMX 開啟連線任務
屬性清單
屬性 | 說明 | 預設值 |
---|---|---|
url | 設定 JMX 連線 URL - service:jmx:rmi:///jndi/rmi://127.0.0.1:8050/jmxrmi | |
host | 設定主機,簡化非常長的 URL 語法。 | localhost |
port | 設定遠端連線埠 | 8050 |
username | 遠端 JMX 連線使用者名稱。 | |
password | 遠端 JMX 連線密碼。 | |
ref | 內部連線參照名稱。使用此屬性,您可以在同一個 Ant 專案中設定多個連線。 | jmx.server |
echo | 回顯指令使用方式(用於存取分析或除錯) | false |
if | 僅在目前的專案中存在指定名稱的屬性時執行。 | |
unless | 僅在目前的專案中不存在指定名稱的屬性時執行。 |
開啟新 JMX 連線範例
<jmx:open
host="${jmx.server.name}"
port="${jmx.server.port}"
/>
從 URL 開啟 JMX 連線,使用授權並儲存在其他參照範例
<jmx:open
url="service:jmx:rmi:///jndi/rmi://127.0.0.1:9024/jmxrmi"
ref="jmx.server.9024"
username="controlRole"
password="tomcat"
/>
從 URL 開啟 JMX 連線,使用授權並儲存在其他參照,但僅在屬性 jmx.if 存在且 jmx.unless 不存在時
<jmx:open
url="service:jmx:rmi:///jndi/rmi://127.0.0.1:9024/jmxrmi"
ref="jmx.server.9024"
username="controlRole"
password="tomcat"
if="jmx.if"
unless="jmx.unless"
/>
注意: jmxOpen 工作中的所有屬性也存在於所有其他工作和條件中。
JMXAccessorGetTask:取得屬性值 Ant 任務
屬性清單
屬性 | 說明 | 預設值 |
---|---|---|
name | 完全限定的 JMX 物件名稱 -- Catalina:type=Server | |
attribute | 現有的 MBean 屬性(請參閱上述 Tomcat MBean 說明) | |
ref | JMX 連線參照 | jmx.server |
echo | 回顯指令使用方式(存取和結果) | false |
resultproperty | 將結果儲存在此專案屬性 | |
delimiter | 使用分隔符號 (java.util.StringTokenizer) 分割結果,並使用 resultproperty 作為前置詞來儲存代幣。 | |
separatearrayresults | 當回傳值為陣列時,將結果儲存為屬性清單 ($resultproperty.[0..N] 和 $resultproperty.length) | true |
範例取得預設 JMX 連線的遠端 MBean 屬性
<jmx:get
name="Catalina:type=Manager,context=/servlets-examples,host=localhost"
attribute="maxActiveSessions"
resultproperty="servlets-examples.maxActiveSessions"
/>
範例取得結果陣列並將其拆分為個別屬性
<jmx:get
name="Catalina:type=ClusterSender,host=localhost"
attribute="senderObjectNames"
resultproperty="senderObjectNames"
/>
使用下列方式存取 senderObjectNames 屬性
${senderObjectNames.length} give the number of returned sender list.
${senderObjectNames.[0..N]} found all sender object names
範例取得僅在叢集組態時連線的 IDataSender 屬性。
注意: name
屬性值會在此處換行以提高可讀性。它必須在同一行,沒有空格。
<jmx:query
failonerror="false"
name="Catalina:type=Cluster,host=${tomcat.application.host}"
resultproperty="cluster"
/>
<jmx:get
name=
"Catalina:type=IDataSender,host=${tomcat.application.host},
senderAddress=${cluster.backup.address},senderPort=${cluster.backup.port}"
attribute="connected"
resultproperty="datasender.connected"
if="cluster.0.name" />
JMXAccessorSetTask:設定屬性值 Ant 任務
屬性清單
屬性 | 說明 | 預設值 |
---|---|---|
name | 完全限定的 JMX 物件名稱 -- Catalina:type=Server | |
attribute | 現有的 MBean 屬性(請參閱上述 Tomcat MBean 說明) | |
值 | 設定至屬性的值 | |
類型 | 屬性的類型。 | java.lang.String |
ref | JMX 連線參照 | jmx.server |
echo | 回顯指令使用方式(存取和結果) | false |
範例設定遠端 MBean 屬性值
<jmx:set
name="Catalina:type=Manager,context=/servlets-examples,host=localhost"
attribute="maxActiveSessions"
value="500"
type="int"
/>
JMXAccessorInvokeTask:呼叫 MBean 作業 Ant 任務
屬性清單
屬性 | 說明 | 預設值 |
---|---|---|
name | 完全限定的 JMX 物件名稱 -- Catalina:type=Server | |
操作 | 現有的 MBean 操作 | |
ref | JMX 連線參照 | jmx.server |
echo | 回顯指令使用方式(存取和結果) | false |
resultproperty | 將結果儲存在此專案屬性 | |
delimiter | 使用分隔符號 (java.util.StringTokenizer) 分割結果,並使用 resultproperty 作為前置詞來儲存代幣。 | |
separatearrayresults | 當回傳值為陣列時,將結果儲存為屬性清單 ($resultproperty.[0..N] 和 $resultproperty.length) | true |
停止應用程式
<jmx:invoke
name="Catalina:type=Manager,context=/servlets-examples,host=localhost"
operation="stop"/>
現在您可以在 ${sessions.[0..N} 屬性中找到 sessionid,並使用 ${sessions.length} 屬性存取計數。
範例取得所有 sessionid
<jmx:invoke
name="Catalina:type=Manager,context=/servlets-examples,host=localhost"
operation="listSessionIds"
resultproperty="sessions"
delimiter=" "
/>
現在您可以在 ${sessions.[0..N} 屬性中找到 sessionid,並使用 ${sessions.length} 屬性存取計數。
範例從 ${sessionid.0} 會話取得遠端 MBean 會話屬性
<jmx:invoke
name="Catalina:type=Manager,context=/ClusterTest,host=localhost"
operation="getSessionAttribute"
resultproperty="hello">
<arg value="${sessionid.0}"/>
<arg value="Hello" />
</jmx:invoke>
範例在 vhost localhost 中建立新的存取記錄器閥門
<jmx:invoke
name="Catalina:type=MBeanFactory"
operation="createAccessLoggerValve"
resultproperty="accessLoggerObjectName"
>
<arg value="Catalina:type=Host,host=localhost"/>
</jmx:invoke>
現在您可以在 ${accessLoggerObjectName} 屬性中找到儲存名稱的新 MBean。
JMXAccessorQueryTask:查詢 MBean Ant 任務
屬性清單
屬性 | 說明 | 預設值 |
---|---|---|
name | JMX ObjectName 查詢字串 -- Catalina:type=Manager,* | |
ref | JMX 連線參照 | jmx.server |
echo | 回顯指令使用方式(存取和結果) | false |
resultproperty | 將專案屬性名稱加為所有已找到 MBean 的前綴 (mbeans.[0..N].objectname) | |
attributebinding | 除了 name 之外,還繫結所有 MBean 屬性 | false |
delimiter | 使用分隔符號 (java.util.StringTokenizer) 分割結果,並使用 resultproperty 作為前置詞來儲存代幣。 | |
separatearrayresults | 當回傳值為陣列時,將結果儲存為屬性清單 ($resultproperty.[0..N] 和 $resultproperty.length) | true |
從所有服務和主機取得所有 Manager ObjectNames
<jmx:query
name="Catalina:type=Manager,*
resultproperty="manager" />
現在您可以在 ${manager.[0..N].name} 屬性中找到 Session Manager,並使用 ${manager.length} 屬性存取結果物件計數器。
範例從 servlet-examples 應用程式取得 Manager 並繫結所有 MBean 屬性
<jmx:query
name="Catalina:type=Manager,context=/servlet-examples,host=localhost*"
attributebinding="true"
resultproperty="manager.servletExamples" />
現在您可以在 ${manager.servletExamples.0.name} 屬性中找到 manager,並可以使用 ${manager.servletExamples.0.[manager 屬性名稱]} 存取此 manager 的所有屬性。MBean 的結果物件計數器儲存在 ${manager.length} 屬性中。
範例從伺服器取得所有 MBean 並儲存在外部 XML 屬性檔案中
<project name="jmx.query"
xmlns:jmx="antlib:org.apache.catalina.ant.jmx"
default="query-all" basedir=".">
<property name="jmx.host" value="localhost"/>
<property name="jmx.port" value="8050"/>
<property name="jmx.username" value="controlRole"/>
<property name="jmx.password" value="tomcat"/>
<target name="query-all" description="Query all MBeans of a server">
<!-- Configure connection -->
<jmx:open
host="${jmx.host}"
port="${jmx.port}"
ref="jmx.server"
username="${jmx.username}"
password="${jmx.password}"/>
<!-- Query MBean list -->
<jmx:query
name="*:*"
resultproperty="mbeans"
attributebinding="false"/>
<echoproperties
destfile="mbeans.properties"
prefix="mbeans."
format="xml"/>
<!-- Print results -->
<echo message=
"Number of MBeans in server ${jmx.host}:${jmx.port} is ${mbeans.length}"/>
</target>
</project>
現在您可以在 mbeans.properties 檔案中找到所有 MBean。
JMXAccessorCreateTask:遠端建立 MBean Ant 任務
屬性清單
屬性 | 說明 | 預設值 |
---|---|---|
name | 完整限定的 JMX ObjectName -- Catalina:type=MBeanFactory | |
className | 現有的 MBean 完整限定類別名稱 (請參閱上述 Tomcat MBean 說明) | |
classLoader | 伺服器或 Web 應用程式類別載入器的 ObjectName ( Catalina:type=ServerClassLoader,name=[server,common,shared] 或 Catalina:type=WebappClassLoader,context=/myapps,host=localhost) |
|
ref | JMX 連線參照 | jmx.server |
echo | 回顯指令使用方式(存取和結果) | false |
範例建立遠端 MBean
<jmx:create
ref="${jmx.reference}"
name="Catalina:type=MBeanFactory"
className="org.apache.commons.modeler.BaseModelMBean"
classLoader="Catalina:type=ServerClassLoader,name=server">
<arg value="org.apache.catalina.mbeans.MBeanFactory" />
</jmx:create>
警告:許多 Tomcat MBean 一旦建立,就無法連結至其父代。
Valve、Cluster 和 Realm MBean 不會自動
與其父項連接。使用 MBeanFactory 建立
操作。
JMXAccessorUnregisterTask:遠端取消註冊 MBean Ant 任務
屬性清單
屬性 | 說明 | 預設值 |
---|---|---|
name | 完整限定的 JMX ObjectName -- Catalina:type=MBeanFactory | |
ref | JMX 連線參照 | jmx.server |
echo | 回顯指令使用方式(存取和結果) | false |
取消註冊遠端 MBean 的範例
<jmx:unregister
name="Catalina:type=MBeanFactory"
/>
警告:許多 Tomcat MBean 無法取消註冊。
MBean 未與其父項取消連結。使用 MBeanFactory
移除操作。
JMXAccessorCondition:表達條件
屬性清單
屬性 | 說明 | 預設值 |
---|---|---|
url | 設定 JMX 連線 URL - service:jmx:rmi:///jndi/rmi://127.0.0.1:8050/jmxrmi | |
host | 設定主機,簡化非常長的 URL 語法。 | localhost |
port | 設定遠端連線埠 | 8050 |
username | 遠端 JMX 連線使用者名稱。 | |
password | 遠端 JMX 連線密碼。 | |
ref | 內部連線參照名稱。使用此屬性,您可以在同一個 Ant 專案中設定多個連線。 | jmx.server |
name | 完全限定的 JMX 物件名稱 -- Catalina:type=Server | |
echo | 迴音條件使用(存取和結果) | false |
if | 僅在目前的專案中存在指定名稱的屬性時執行。 | |
unless | 僅在目前的專案中不存在指定名稱的屬性時執行。 | |
值(必要) | 操作的第二個引數 | |
類型 | 表達操作的值類型(支援 long 和 double) | long |
操作 | 表達一個
|
== |
等待伺服器連線和叢集備份節點可存取
<target name="wait">
<waitfor maxwait="${maxwait}" maxwaitunit="second" timeoutproperty="server.timeout" >
<and>
<socket server="${server.name}" port="${server.port}"/>
<http url="${url}"/>
<jmx:condition
operation="=="
host="localhost"
port="9014"
username="controlRole"
password="tomcat"
name=
"Catalina:type=IDataSender,host=localhost,senderAddress=192.168.111.1,senderPort=9025"
attribute="connected"
value="true"
/>
</and>
</waitfor>
<fail if="server.timeout" message="Server ${url} don't answer inside ${maxwait} sec" />
<echo message="Server ${url} alive" />
</target>
JMXAccessorEqualsCondition:等於 MBean Ant 條件
屬性清單
屬性 | 說明 | 預設值 |
---|---|---|
url | 設定 JMX 連線 URL - service:jmx:rmi:///jndi/rmi://127.0.0.1:8050/jmxrmi | |
host | 設定主機,簡化非常長的 URL 語法。 | localhost |
port | 設定遠端連線埠 | 8050 |
username | 遠端 JMX 連線使用者名稱。 | |
password | 遠端 JMX 連線密碼。 | |
ref | 內部連線參照名稱。使用此屬性,您可以在同一個 Ant 專案中設定多個連線。 | jmx.server |
name | 完全限定的 JMX 物件名稱 -- Catalina:type=Server | |
echo | 迴音條件使用(存取和結果) | false |
等待伺服器連線和叢集備份節點可存取
<target name="wait">
<waitfor maxwait="${maxwait}" maxwaitunit="second" timeoutproperty="server.timeout" >
<and>
<socket server="${server.name}" port="${server.port}"/>
<http url="${url}"/>
<jmx:equals
host="localhost"
port="9014"
username="controlRole"
password="tomcat"
name=
"Catalina:type=IDataSender,host=localhost,senderAddress=192.168.111.1,senderPort=9025"
attribute="connected"
value="true"
/>
</and>
</waitfor>
<fail if="server.timeout" message="Server ${url} don't answer inside ${maxwait} sec" />
<echo message="Server ${url} alive" />
</target>
使用 JMXProxyServlet
Tomcat 提供一種使用遠端(或甚至是本機)JMX 連線的替代方案,同時仍讓您存取 JMX 提供的所有功能:Tomcat 的 JMXProxyServlet。
JMXProxyServlet 允許客戶端透過 HTTP 介面發出 JMX 查詢。與直接從客戶端程式使用 JMX 相比,此技術提供下列優點
- 您不必啟動完整的 JVM 並建立遠端 JMX 連線,只要從執行中伺服器要求一小段資料即可
- 您不必知道如何使用 JMX 連線
- 您不需要本頁面其餘部分中涵蓋的任何複雜組態
- 您的客戶端程式不必以 Java 編寫
可以在 Nagios 或 Icinga 等熱門伺服器監控軟體中看到 JMX 過度使用的完美範例:如果您想透過 JMX 監控 10 個項目,您必須啟動 10 個 JVM,建立 10 個 JMX 連線,然後每隔幾分鐘關閉它們。使用 JMXProxyServlet,您可以建立 10 個 HTTP 連線並完成它。
您可以在 Tomcat 管理員 的文件中找到有關 JMXProxyServlet 的更多資訊。