監控和管理 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

  1. 變更並新增此內容
      -Dcom.sun.management.jmxremote.ssl=true
      -Dcom.sun.management.jmxremote.registry.ssl=true
    
  2. 若要組態通訊協定和/或加密套件,請使用
      -Dcom.sun.management.jmxremote.ssl.enabled.protocols=%my.jmx.ssl.protocols%
      -Dcom.sun.management.jmxremote.ssl.enabled.cipher.suites=%my.jmx.cipher.suites%
    
  3. 若要使用用戶端憑證驗證,請使用
      -Dcom.sun.management.jmxremote.ssl.need.client.auth=%my.jmx.ssl.clientauth%

如果您需要授權(強烈建議始終將 TLS 與驗證搭配使用)

  1. 變更並新增此內容
      -Dcom.sun.management.jmxremote.authenticate=true
      -Dcom.sun.management.jmxremote.password.file=../conf/jmxremote.password
      -Dcom.sun.management.jmxremote.access.file=../conf/jmxremote.access
  2. 編輯存取授權檔案 $CATALINA_BASE/conf/jmxremote.access
    monitorRole readonly
    controlRole readwrite
  3. 編輯密碼檔案 $CATALINA_BASE/conf/jmxremote.password
    monitorRole tomcat
    controlRole tomcat
    提示:密碼檔案應為唯讀,且僅供 Tomcat 執行的作業系統使用者存取。
  4. 或者,您可以使用下列方式組態 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 專案,並使用 jmxOpenjmxSetjmxGetjmxQueryjmxInvokejmxEqualsjmxCondition 參照這些工作。

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 僅在目前的專案中不存在指定名稱的屬性時執行。
值(必要) 操作的第二個引數
類型 表達操作的值類型(支援 longdouble long
操作 表達一個
  • == 等於
  • != 不等於
  • > 大於 (&gt;)
  • >= 大於或等於 (&gt;=)
  • < 小於 (&lt;)
  • <= 小於或等於 (&lt;=)
==

等待伺服器連線和叢集備份節點可存取

<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 的更多資訊。