鍍金池/ 教程/ Linux/ 監(jiān)控與管理
連接器
JSPs
重寫機制
CGI
Tomcat Manager
Windows 認(rèn)證
代理支持
虛擬主機
安全性注意事項
如何在 Maven 中使用 Tomcat 庫
安裝
MBean 描述符
JNDI 資源
類加載機制
Tomcat Web 應(yīng)用部署
基于 APR 的原生庫
負(fù)載均衡器
安全管理
附加組件
監(jiān)控與管理
Windows 服務(wù)
集群化與會話復(fù)制
高級 IO 機制
SSI(服務(wù)器端嵌入)
WebSocket 支持
JDBC 數(shù)據(jù)源
日志機制
默認(rèn) Servlet
SSL/TLS 配置
Tomcat 的 JDBC 連接池
第一個應(yīng)用
簡介
Realm 配置

監(jiān)控與管理

簡介

監(jiān)控是系統(tǒng)管理中的重要環(huán)節(jié)。系統(tǒng)管理員的日常工作就包括:觀察服務(wù)器的運行細(xì)節(jié),獲取統(tǒng)計數(shù)據(jù),或者重新配置應(yīng)用的某些內(nèi)容。

啟用 JMX 遠(yuǎn)程監(jiān)控

注意:該配置只適用于需用遠(yuǎn)程監(jiān)控 Tomcat 的情況,使用同樣的用戶在本地監(jiān)控 Tomcat 則不需要這么配置。

Oracle 的網(wǎng)站上介紹了如何在 Java 6 上配置 JMX 遠(yuǎn)程:http://docs.oracle.com/javase/6/docs/technotes/guides/management/agent.html。

下面是在 Java 6 上的快速配置向?qū)В?

將下列參數(shù)添加到 Tomcat 的 setenv.bat 腳本(具體詳細(xì)信息請查看 RUNNING.txt)。

注意:該語法格式適用于 Windows 系統(tǒng)。命令行只能寫在同一行中,包裝起來更具可讀性。如果 Tomcat 以 Windows 服務(wù)的形式運行,使用它的系統(tǒng)配置對話設(shè)置該服務(wù)的 java 選項。對于 UN\*X 系統(tǒng)來說,要將命令行開頭的 "set " 去掉。

set CATALINA_OPTS=-Dcom.sun.management.jmxremote
  -Dcom.sun.management.jmxremote.port=%my.jmx.port%
  -Dcom.sun.management.jmxremote.ssl=false
  -Dcom.sun.management.jmxremote.authenticate=false

1.如果需要授權(quán),則添加并修改下列命令:

-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.編輯訪問權(quán)限文件 $CATALINA_BASE/conf/jmxremote.access

monitorRole readonly
controlRole readwrite

3.編輯密碼文件 $CATALINA_BASE/conf/jmxremote.password

monitorRole tomcat
controlRole tomcat

技巧:密碼文件應(yīng)該是只讀的,并且只能被運行 Tomcat 的操作系統(tǒng)用戶所訪問。

注意:JSR 160 JMX 適配器在一個隨機端口上打開了第二個數(shù)據(jù)通道。假如本地安裝了防火墻,這就會出現(xiàn)問題。要想解決它,可以按照偵聽器文檔中介紹的方法,配置一個 JmxRemoteLifecycleListener。

利用 JMX 遠(yuǎn)程 Ant 任務(wù)來管理 Tomcat

為了簡化 JMX 的用法,加入了一些可能會與 antlib 使用的一系列任務(wù)。

antlib:將 catalina-ant.jar 從 $CATALINA_HOME/lib 復(fù)制到 $ANT_HOME/lib

下面的例子展示了 JMX 存儲器的用法。

注意:為了提高可讀性,這里將 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.orginal</em>
    -->
    <jmx:get
      name="Catalina:type=Manager,context=/ClusterTest,host=localhost"
      attribute="maxActiveSessions"
      resultproperty="clustertest.maxActiveSessions.orginal"
      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>

導(dǎo)入:利用 <import file="${CATALINA.HOME}/bin/catalina-tasks.xml" /> 導(dǎo)入 JMX 存取器項目,利用 jmxOpen、jmxSet、jmxGet、jmxQuery、jmxInvoke、jmxEquals 和 jmxCondition 來引用任務(wù)。

JMXAccessorOpenTask - JMX 打開連接任務(wù)

屬性列表

屬性 描述 默認(rèn)值
url 設(shè)定 JMX 連接 URL——service:jmx:rmi:///jndi/rmi://localhost:8050/jmxrmi -
host 設(shè)定主機,縮短長的 URL 格式 localhost
port 設(shè)定遠(yuǎn)程連接端口 8050
username 遠(yuǎn)程 JMX 連接用戶名 -
password 遠(yuǎn)程 JMX 連接密碼 -
ref 內(nèi)部連接引用的名稱。利用該屬性,在同一個 Ant 項目中配置不止一個連接 jmx.server
echo Echo 命令用途(用于訪問分析或調(diào)試) false
if 只有當(dāng)指定名稱的屬性存在于當(dāng)前項目時才執(zhí)行 -
unless 只有當(dāng)指定名稱的屬性不存在于當(dāng)前項目時才執(zhí)行 -

打開新的 JMX 連接的范例如下:

  <jmx:open
    host="${jmx.server.name}"
    port="${jmx.server.port}"
  />  

打開指定 URL 的 JMX 連接的范例,帶有授權(quán)并存儲在其他引用中:

  <jmx:open
    url="service:jmx:rmi:///jndi/rmi://localhost:9024/jmxrmi"
    ref="jmx.server.9024"
    username="controlRole"
    password="tomcat"
  />

打開指定 URL 的 JMX 連接的范例,帶有授權(quán)并存儲在其他引用中,但是必須要求 jmx.if 屬性存在,而 jmx.unless 屬性不存在。

  <jmx:open
    url="service:jmx:rmi:///jndi/rmi://localhost:9024/jmxrmi"
    ref="jmx.server.9024"
    username="controlRole"
    password="tomcat"
    if="jmx.if"
    unless="jmx.unless"
  />   

注意jmxOpen 任務(wù)中所有屬性也存在于其他所有任務(wù)和條件中。

JMXAccessorGetTask: 獲取屬性值的 Ant 任務(wù)

屬性列表

屬性 描述 默認(rèn)值
name 完全限定的 JMX ObjectName——Catalina:type=Server -
attribute 已有的 MBean 屬性(參看上文介紹的 Tomcat MBean 描述) -
ref JMX 連接引用 jmx.server
echo Echo 命令用途(訪問與結(jié)果) false
resultproperty 在該項目屬性中保存結(jié)果 -
delimiter 用分隔符(java.util.StringTokenizier)分隔結(jié)果,使用 resultproperty 作為前綴來保存令牌 -
separatearrayresults 返回值為數(shù)組時,將結(jié)果保存為屬性列表($resultproperty.[0..N]$resultproperty.length true

從默認(rèn)的 JMX 連接中獲取遠(yuǎn)程 MBean 屬性:

  <jmx:get
    name="Catalina:type=Manager,context=/servlets-examples,host=localhost"
    attribute="maxActiveSessions"
    resultproperty="servlets-examples.maxActiveSessions"
  />

獲取結(jié)果數(shù)組,并將其分隔成獨立的一些屬性:

  <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 屬性加以包裝。代碼應(yīng)該位于同一行中,并且不含有空格。

  <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:設(shè)定屬性值的 Ant 任務(wù)

屬性列表

屬性 說明 默認(rèn)值
name 完全限定的 JMX ObjectName——Catalina:type=Server -
attribute 已有的 MBean 屬性(詳情參見上文介紹的 Tomcat MBean 說明) -
value 設(shè)定為屬性的值 -
type 屬性類型 java.lang.String
ref JMX 連接引用 jmx.server
echo Echo 命令用途(訪問與結(jié)果) false

設(shè)定遠(yuǎn)程 MBean 屬性值的范例如下:

  <jmx:set
    name="Catalina:type=Manager,context=/servlets-examples,host=localhost"
    attribute="maxActiveSessions"
    value="500"
    type="int"
  />

JMXAccessorInvokeTask: 調(diào)用 MBean 操作的 Ant 任務(wù)

屬性列表

屬性 說明 默認(rèn)值
name 完全限定的 JMX ObjectName——Catalina:type=Server -
operation 已有的 MBean 操作(funcspecs/fs-admin-opers.html -
ref JMX 連接引用 jmx.server jmx.server
echo Echo 命令用途(訪問與結(jié)果) false
resultproperty 在這一項目屬性中保存結(jié)果 -
delimiter 用分隔符(java.util.StringTokenizier)分隔結(jié)果,使用 resultproperty 作為前綴來保存令牌 -
separatearrayresults 返回值為數(shù)組時,將結(jié)果保存為屬性列表($resultproperty.[0..N]$resultproperty.length true

停止應(yīng)用:

  <jmx:invoke
    name="Catalina:type=Manager,context=/servlets-examples,host=localhost"
    operation="stop"/>

可以在 ${sessions.[0..N} 屬性中找到 sessionid,然后利用 ${sessions.length} 屬性來訪問計數(shù)。

獲取所有 sessionid 的范例如下:

  <jmx:invoke
    name="Catalina:type=Manager,context=/servlets-examples,host=localhost"
    operation="listSessionIds"
    resultproperty="sessions"
    delimiter=" "
  />  

現(xiàn)在你可以在 ${sessions.[0..N} 屬性中找到 sessionid,然后利用 ${sessions.length} 屬性來訪問計數(shù)。

從 ${sessionid.0} 會話中獲取遠(yuǎn)程 MBean 會話屬性:

  <jmx:invoke
    name="Catalina:type=Manager,context=/ClusterTest,host=localhost"
    operation="getSessionAttribute"
    resultproperty="hello">
     <arg value="${sessionid.0}"/>
     <arg value="Hello" />
  </jmx:invoke>

在虛擬主機 localhost 上創(chuàng)建新的訪問日志記錄器值:

 <jmx:invoke
         name="Catalina:type=MBeanFactory"
         operation="createAccessLoggerValve"
         resultproperty="accessLoggerObjectName"
 >
     <arg value="Catalina:type=Host,host=localhost"/>
 </jmx:invoke>

現(xiàn)在可以利用 ${accessLoggerObjectName} 屬性上存儲的名稱找到新的 MBean 了。

JMXAccessorQueryTask: 查詢 MBean 的 Ant 任務(wù)

屬性列表:

屬性 描述 默認(rèn)值
name JMX ObjectName 查詢字符串——Catalina:type=Manager,* -
ref JMX 連接引用 jmx.server
echo Echo 命令用途(訪問及結(jié)果) false
resultproperty 將項目屬性名做為前綴加到所有已建立的 MBean 上(mbeans.[0..N].objectname -
attributebinduing 除了 name 之外,綁定所有的 MBean 屬性 false
delimiter 用分隔符(java.util.StringTokenizier)分隔結(jié)果,使用 resultproperty 作為前綴來保存令牌 -
separatearrayresults 返回值為數(shù)組時,將結(jié)果保存為屬性列表($resultproperty.[0..N]$resultproperty.length true

從所有的服務(wù)及主機中獲取所有的 Manager ObjectName:

  <jmx:query
    name="Catalina:type=Manager,*
    resultproperty="manager" />

現(xiàn)在,在 ${manager.[0..N].name} 屬性上可以找到 Session Manager,利用 ${manager.length} 屬性來訪問結(jié)果對象計數(shù)器。

servlet-examples 程序中獲取 Manager,并綁定所有的 MBean 屬性:

  <jmx:query
    name="Catalina:type=Manager,context=/servlet-examples,host=localhost*"
    attributebinding="true"
    resultproperty="manager.servletExamples" />

現(xiàn)在我們可以在 ${manager.servletExamples.0.name} 屬性中找到 manager,并利用 ${manager.servletExamples.0.[manager attribute names]} 訪問該 manager 的所有屬性。MBean 的結(jié)果對象計數(shù)器被保存在 ${manager.length} 屬性中。

在下面范例中,從服務(wù)器中獲取所有的 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>

現(xiàn)在就可以在 mbeans.properties 文件中找到所有的 MBean 了。

JMXAccessorCreateTask: 遠(yuǎn)程創(chuàng)建 MBean 的 Ant 任務(wù)

屬性列表

屬性 描述 默認(rèn)值
name 完全限定的 JMX ObjectName——Catalina:type=MBeanFactory -
className 已有的 MBean 完全限定的類名(參見上文的 Tomcat MBean 說明) -
classLoader 服務(wù)器或 Web 應(yīng)用類加載器的 ObjectName
Catalina:type=ServerClassLoader,name=[server,common,shared]Catalina:type=WebappClassLoader,context=/myapps,host=localhost
-
ref JMX 連接引用 jmx.server
echo Echo 命令用途(訪問及結(jié)果) false

創(chuàng)建遠(yuǎn)程 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 一經(jīng)創(chuàng)建就沒有與父級連接。Valve、集群以及Realm 的 MBean 都不會自動與父級相連。作為替代,可以使用 MBeanFactory 來創(chuàng)建操作。

JMXAccessorUnregisterTask: 遠(yuǎn)程注銷 MBean Ant 任務(wù)

屬性列表

屬性 描述 默認(rèn)值
name 完全限定的 JMX ObjectName——Catalina:type=MBeanFactory =
ref JMX 連接引用 jmx.server
echo Echo 命令使用(訪問及結(jié)果) false

注銷遠(yuǎn)程 MBean 范例如下:

  <jmx:unregister
    name="Catalina:type=MBeanFactory"
  />

警告:許多 Tomcat MBean 都無法注銷。MBean 無法從其父級脫離。可以使用 MBeanFactory 來移除操作。

JMXAccessorCondition: 表達(dá)條件

屬性列表

屬性 描述 默認(rèn)值
url 設(shè)定 JMX 連接 URL ——service:jmx:rmi:///jndi/rmi://localhost:8050/jmxrmi -
host 設(shè)定主機,將非常長的 URL 格式予以縮短 localhost
port 設(shè)定遠(yuǎn)程連接端口 8050
username 遠(yuǎn)程 JMX 連接用戶名 -
password 遠(yuǎn)程 JMX 連接密碼 -
ref 內(nèi)部連接引用名稱。利用這一屬性,可以在同一個 Ant 項目中配置多個連接。 jmx.server
name 完全限定的 JMX ObjectName——Catalina:type=Server -
echo Echo 命令使用(訪問及結(jié)果) false
if 只有當(dāng)給定名稱的屬性存在于當(dāng)前項目中才執(zhí)行 -
unless 只有當(dāng)給定名稱的屬性不存在于當(dāng)前項目中才執(zhí)行 -
value (必須) 操作的第二個參數(shù) -
type 表達(dá)操作的值類型(支持 longdouble long
operation 提供以下操作
  • == 等于
  • != 不等于
  • >大于(&gt
  • >=大于或等于(&gt;=
  • <小于(&lt
  • <=小于或等于(&lt;=
  • ==

    等待服務(wù)器連接,集群備份節(jié)點可訪問。

    <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 條件對等

    屬性列表

    屬性 描述 默認(rèn)值
    url 設(shè)定 JMX 連接 URL ——service:jmx:rmi:///jndi/rmi://localhost:8050/jmxrmi -
    host 設(shè)定主機,將非常長的 URL 格式予以縮短 localhost
    port 設(shè)定遠(yuǎn)程連接端口 8050
    username 遠(yuǎn)程 JMX 連接用戶名 -
    password 遠(yuǎn)程 JMX 連接密碼 -
    ref 內(nèi)部連接引用名稱。利用這一屬性,可以在同一個 Ant 項目中配置多個連接。 jmx.server
    name 完全限定的 JMX ObjectName——Catalina:type=Server -
    echo Echo 命令使用(訪問及結(jié)果) false

    等待服務(wù)器連接,集群備份節(jié)點可訪問。

    <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 為使用遠(yuǎn)程(或者甚至本地的)JMX 連接提供了一個替代方案:Tomcat 的 JMXProxyServlet,但它仍能讓你訪問 JMX 所提供的任何內(nèi)容。

    JMXProxyServlet 允許客戶端通過 HTTP 接口來發(fā)送 JMX 查詢。相比直接從客戶端程序使用 JMX 來說,該技術(shù)具有以下優(yōu)勢:

    • 無需加載完整的 JVM 并執(zhí)行遠(yuǎn)程 JMX 連接,只需從服務(wù)器上請求一小塊數(shù)據(jù)即可。
    • 無需了解處理 JMX 連接的方式。
    • 無需任何復(fù)雜的配置。
    • 無需用 Java 來編寫客戶端程序。

    常見的服務(wù)器監(jiān)控軟件(比如 Nagios 或 Ichinga)中都存在過度使用 JMX 的問題:如果想通過 JMX 監(jiān)控 10 項,就必須啟動 10 個 JVM,保持 10 個 JMX 連接,每過幾分鐘就要將它們?nèi)筷P(guān)閉。有了 JMXProxyServlet,利用 10 個 HTTP 連接就能搞定了。

    關(guān)于 JMXProxyServlet 的詳細(xì)說明,可查閱 Tomcat Manager。

    上一篇:簡介下一篇:MBean 描述符