集群/会话复制操作指南

重要说明

您也可以查看 配置参考文档。

目录

对于没有耐心的人

只需添加

<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"/>

到您的 <Engine><Host> 元素以启用集群。

使用上述配置将启用使用 DeltaManager 进行全对全会话复制以复制会话增量。全对全意味着每个会话都将复制到集群中的所有其他节点。这对于较小的集群非常有效,但我们不建议将其用于更大的集群(超过 4 个节点左右)。此外,在使用 DeltaManager 时,Tomcat 会将会话复制到所有节点,即使是未部署应用程序的节点
为了解决这些问题,您需要使用 BackupManagerBackupManager 只将会话数据复制到一个备份节点,并且只复制到已部署应用程序的节点。一旦您使用 DeltaManager 运行了一个简单的集群,您可能希望在增加集群中的节点数量时迁移到 BackupManager

以下是一些重要的默认值

  1. 多播地址为 228.0.0.4
  2. 多播端口为 45564(端口和地址一起决定集群成员资格)。
  3. 广播的 IP 地址为 java.net.InetAddress.getLocalHost().getHostAddress()(确保不要广播 127.0.0.1,这是一个常见的错误)
  4. 用于监听复制消息的 TCP 端口是 4000-4100 范围内第一个可用的服务器套接字
  5. 监听器配置为 ClusterSessionListener
  6. 配置了两个拦截器 TcpFailureDetectorMessageDispatchInterceptor

以下是默认的集群配置

        <Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"
                 channelSendOptions="8">

          <Manager className="org.apache.catalina.ha.session.DeltaManager"
                   expireSessionsOnShutdown="false"
                   notifyListenersOnReplication="true"/>

          <Channel className="org.apache.catalina.tribes.group.GroupChannel">
            <Membership className="org.apache.catalina.tribes.membership.McastService"
                        address="228.0.0.4"
                        port="45564"
                        frequency="500"
                        dropTime="3000"/>
            <Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver"
                      address="auto"
                      port="4000"
                      autoBind="100"
                      selectorTimeout="5000"
                      maxThreads="6"/>

            <Sender className="org.apache.catalina.tribes.transport.ReplicationTransmitter">
              <Transport className="org.apache.catalina.tribes.transport.nio.PooledParallelSender"/>
            </Sender>
            <Interceptor className="org.apache.catalina.tribes.group.interceptors.TcpFailureDetector"/>
            <Interceptor className="org.apache.catalina.tribes.group.interceptors.MessageDispatchInterceptor"/>
          </Channel>

          <Valve className="org.apache.catalina.ha.tcp.ReplicationValve"
                 filter=""/>
          <Valve className="org.apache.catalina.ha.session.JvmRouteBinderValve"/>

          <Deployer className="org.apache.catalina.ha.deploy.FarmWarDeployer"
                    tempDir="/tmp/war-temp/"
                    deployDir="/tmp/war-deploy/"
                    watchDir="/tmp/war-listen/"
                    watchEnabled="false"/>

          <ClusterListener className="org.apache.catalina.ha.session.ClusterSessionListener"/>
        </Cluster>

我们将在本文档的后面部分更详细地介绍本节内容。

安全

集群实现基于所有集群相关网络流量使用安全、可信网络的假设。在不安全、不可信的网络上运行集群是不安全的。

为 Tomcat 集群提供安全、可信网络有很多选择,包括

  • 私有 LAN
  • 虚拟专用网络 (VPN)
  • IPSEC

EncryptInterceptor 提供机密性和完整性保护,但它不能防止与在不可信网络上运行 Tomcat 集群相关的所有风险,特别是 DoS 攻击。

集群基础

要在 Tomcat 10 容器中运行会话复制,应完成以下步骤

  • 所有会话属性必须实现 java.io.Serializable
  • 取消 server.xml 中 Cluster 元素的注释
  • 如果您定义了自定义集群阀门,请确保在 server.xml 中的 Cluster 元素下也定义了 ReplicationValve
  • 如果您的 Tomcat 实例在同一台机器上运行,请确保每个实例的 Receiver.port 属性都是唯一的,在大多数情况下,Tomcat 足够智能,可以通过自动检测 4000-4100 范围内的可用端口来自行解决此问题
  • 确保您的 web.xml 包含 <distributable/> 元素
  • 如果您使用的是 mod_jk,请确保在您的 Engine 中设置了 jvmRoute 属性 <Engine name="Catalina" jvmRoute="node01" >,并且 jvmRoute 属性值与 workers.properties 中的工作程序名称匹配
  • 确保所有节点具有相同的时间并与 NTP 服务同步!
  • 确保您的负载均衡器配置为粘性会话模式。

负载均衡可以通过多种技术实现,如 负载均衡 章节所述。

注意:请记住,您的会话状态由 cookie 跟踪,因此您的 URL 从外部看起来必须相同,否则将创建新的会话。

Cluster 模块使用 Tomcat JULI 日志记录框架,因此您可以通过常规的 logging.properties 文件配置日志记录。要跟踪消息,您可以在以下键上启用日志记录:org.apache.catalina.tribes.MESSAGES

概述

为了在 Tomcat 中启用会话复制,可以遵循三种不同的路径来实现相同的效果。

  1. 使用会话持久化,并将会话保存到共享文件系统(PersistenceManager + FileStore)。
  2. 使用会话持久化,并将会话保存到共享数据库(PersistenceManager + JDBCStore)。
  3. 使用内存内复制,使用 Tomcat 自带的 SimpleTcpCluster(lib/catalina-tribes.jar + lib/catalina-ha.jar)。

Tomcat 可以使用 DeltaManager 对会话状态进行全对全复制,或者使用 BackupManager 对单个节点进行备份复制。全对全复制算法仅在集群规模较小时才有效。对于较大的集群,应使用 BackupManager 来使用主备会话复制策略,其中会话仅存储在一个备份节点上。
目前,您可以使用域工作者属性(mod_jk > 1.2.8)来构建集群分区,并有可能使用 DeltaManager 创建更可扩展的集群解决方案(您需要为此配置域拦截器)。为了在全对全环境中降低网络流量,您可以将集群分成更小的组。这可以通过为不同组使用不同的组播地址轻松实现。一个非常简单的设置如下所示

        DNS Round Robin
               |
         Load Balancer
          /           \
      Cluster1      Cluster2
      /     \        /     \
  Tomcat1 Tomcat2  Tomcat3 Tomcat4

这里需要重点说明的是,会话复制只是集群化的开始。另一个用于实现集群的流行概念是“农场”,即您只将应用程序部署到一台服务器,而集群将在整个集群中分发部署。所有这些功能都可以通过 FarmWarDeployer 实现(请参阅 server.xml 中的集群示例)。

在下一节中,我们将深入探讨会话复制的工作原理以及如何配置它。

集群信息

成员资格是使用组播心跳建立的。因此,如果您希望细分集群,可以通过更改 <Membership> 元素中的组播 IP 地址或端口来实现。

心跳包含 Tomcat 节点的 IP 地址和 Tomcat 监听复制流量的 TCP 端口。所有数据通信都通过 TCP 进行。

ReplicationValve 用于找出请求何时完成并启动复制(如果有)。只有当会话发生更改(通过在会话上调用 setAttribute 或 removeAttribute)时,才会复制数据。

性能考量中最重要的一点是同步复制和异步复制。在同步复制模式下,请求只有在复制的会话通过网络发送并重新实例化到所有其他集群节点后才会返回。同步与异步是使用 `channelSendOptions` 标志配置的,它是一个整数值。`SimpleTcpCluster/DeltaManager` 组合的默认值为 8,表示异步。有关各种 `channelSendOptions` 值的更多讨论,请参阅 配置参考

为了方便起见,`channelSendOptions` 可以通过名称而不是整数来设置,这些名称在启动时会转换为相应的整数值。有效的选项名称包括: "asynchronous"(别名 "async"),"byte_message"(别名 "byte"),"multicast","secure","synchronized_ack"(别名 "sync"),"udp","use_ack"。使用逗号分隔多个名称,例如,传递 "async, multicast" 以获取选项 `SEND_OPTIONS_ASYNCHRONOUS | SEND_OPTIONS_MULTICAST`。

您可以在 发送标志(概述)发送标志(javadoc) 中了解更多信息。在异步复制期间,请求在数据复制之前返回。异步复制可以缩短请求时间,而同步复制可以保证会话在请求返回之前被复制。

在崩溃后将会话绑定到故障转移节点

如果您使用的是 mod_jk 并且没有使用粘性会话,或者由于某些原因粘性会话不起作用,或者您只是在进行故障转移,则需要修改会话 ID,因为它之前包含了先前 Tomcat 的工作程序 ID(由 Engine 元素中的 jvmRoute 定义)。为了解决这个问题,我们将使用 JvmRouteBinderValve。

JvmRouteBinderValve 会重写会话 ID,以确保在故障转移后,下一个请求将保持粘性(不会回退到随机节点,因为工作程序不再可用)。该阀门会重写 cookie 中的 JSESSIONID 值,并使用相同的名称。如果没有这个阀门,在 mod_jk 模块发生故障的情况下,将难以确保粘性。

请记住,如果您在 server.xml 中添加了自己的阀门,则默认值将不再有效,请确保添加所有由默认值定义的适当阀门。

提示
使用属性 sessionIdAttribute,您可以更改包含旧会话 ID 的请求属性名称。默认属性名称是 org.apache.catalina.ha.session.JvmRouteOriginalSessionID

技巧
您可以在将节点降级到所有备份节点之前,通过 JMX 启用此 mod_jk 轮换模式!在所有 JvmRouteBinderValve 备份上设置 enable 为 true,在 mod_jk 上禁用 worker,然后将节点降级并重新启动!然后启用 mod_jk Worker 并再次禁用 JvmRouteBinderValves。此用例意味着仅迁移请求的会话。

配置示例

        <Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"
                 channelSendOptions="6">

          <Manager className="org.apache.catalina.ha.session.BackupManager"
                   expireSessionsOnShutdown="false"
                   notifyListenersOnReplication="true"
                   mapSendOptions="6"/>
          <!--
          <Manager className="org.apache.catalina.ha.session.DeltaManager"
                   expireSessionsOnShutdown="false"
                   notifyListenersOnReplication="true"/>
          -->
          <Channel className="org.apache.catalina.tribes.group.GroupChannel">
            <Membership className="org.apache.catalina.tribes.membership.McastService"
                        address="228.0.0.4"
                        port="45564"
                        frequency="500"
                        dropTime="3000"/>
            <Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver"
                      address="auto"
                      port="5000"
                      selectorTimeout="100"
                      maxThreads="6"/>

            <Sender className="org.apache.catalina.tribes.transport.ReplicationTransmitter">
              <Transport className="org.apache.catalina.tribes.transport.nio.PooledParallelSender"/>
            </Sender>
            <Interceptor className="org.apache.catalina.tribes.group.interceptors.TcpFailureDetector"/>
            <Interceptor className="org.apache.catalina.tribes.group.interceptors.MessageDispatchInterceptor"/>
            <Interceptor className="org.apache.catalina.tribes.group.interceptors.ThroughputInterceptor"/>
          </Channel>

          <Valve className="org.apache.catalina.ha.tcp.ReplicationValve"
                 filter=".*\.gif|.*\.js|.*\.jpeg|.*\.jpg|.*\.png|.*\.htm|.*\.html|.*\.css|.*\.txt"/>

          <Deployer className="org.apache.catalina.ha.deploy.FarmWarDeployer"
                    tempDir="/tmp/war-temp/"
                    deployDir="/tmp/war-deploy/"
                    watchDir="/tmp/war-listen/"
                    watchEnabled="false"/>

          <ClusterListener className="org.apache.catalina.ha.session.ClusterSessionListener"/>
        </Cluster>

分解一下!

        <Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"
                 channelSendOptions="6">

主要元素,在这个元素内部可以配置所有集群细节。channelSendOptions 是附加到 SimpleTcpCluster 类发送的每个消息或调用 SimpleTcpCluster.send 方法的任何对象的标志。发送标志的描述可在 我们的 javadoc 网站 上找到。DeltaManager 使用 SimpleTcpCluster.send 方法发送信息,而备份管理器则直接通过通道发送信息。
更多信息,请访问 参考文档

          <Manager className="org.apache.catalina.ha.session.BackupManager"
                   expireSessionsOnShutdown="false"
                   notifyListenersOnReplication="true"
                   mapSendOptions="6"/>
          <!--
          <Manager className="org.apache.catalina.ha.session.DeltaManager"
                   expireSessionsOnShutdown="false"
                   notifyListenersOnReplication="true"/>
          -->

这是一个管理器配置的模板,如果在 <Context> 元素中没有定义管理器,则将使用此模板。在 Tomcat 5.x 中,每个标记为可分发的 webapp 都必须使用相同的管理器,现在不再是这种情况,因为在 Tomcat 中,您可以为每个 webapp 定义一个管理器类,这样您就可以在集群中混合管理器。显然,一个节点应用程序上的管理器必须与另一个节点上相同应用程序上的相同管理器相对应。如果未为 webapp 指定管理器,并且 webapp 标记为 <distributable/>,Tomcat 将使用此管理器配置并创建一个克隆此配置的管理器实例。
更多信息,请访问 参考文档

          <Channel className="org.apache.catalina.tribes.group.GroupChannel">

通道元素是 Tribes,Tomcat 内部使用的组通信框架。此元素封装了与通信和成员资格逻辑有关的所有内容。
更多信息,请访问 参考文档

            <Membership className="org.apache.catalina.tribes.membership.McastService"
                        address="228.0.0.4"
                        port="45564"
                        frequency="500"
                        dropTime="3000"/>

成员资格是使用组播完成的。请注意,如果您想将成员资格扩展到组播之外的点,Tribes 还支持使用 StaticMembershipInterceptor 进行静态成员资格。address 属性是使用的组播地址,port 是组播端口。这两个属性一起创建集群分离。如果您想要一个 QA 集群和一个生产集群,最简单的配置是让 QA 集群使用与生产集群不同的组播地址/端口组合。
成员资格组件将自身的 TCP 地址/端口广播到其他节点,以便节点之间可以通过 TCP 进行通信。请注意,广播的地址是 Receiver.address 属性的地址。
更多信息,请访问 参考文档

            <Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver"
                      address="auto"
                      port="5000"
                      selectorTimeout="100"
                      maxThreads="6"/>

在 Tribes 中,发送和接收数据的逻辑被分解成两个功能组件。接收器,顾名思义,负责接收消息。由于 Tribes 堆栈是无线程的(现在其他框架也采用的一个流行改进),此组件中有一个线程池,它具有 maxThreads 和 minThreads 设置。
地址属性是成员资格组件将广播到其他节点的主机地址。
更多信息,请访问 参考文档

            <Sender className="org.apache.catalina.tribes.transport.ReplicationTransmitter">
              <Transport className="org.apache.catalina.tribes.transport.nio.PooledParallelSender"/>
            </Sender>

发送器组件,顾名思义,负责将消息发送到其他节点。发送器有一个外壳组件,ReplicationTransmitter,但实际工作是在子组件 Transport 中完成的。Tribes 支持拥有一个发送器池,以便可以并行发送消息,如果使用 NIO 发送器,您也可以并发发送消息。
并发意味着同时向多个发送器发送一条消息,而并行意味着同时向多个发送器发送多条消息。
更多信息,请访问 参考文档

            <Interceptor className="org.apache.catalina.tribes.group.interceptors.TcpFailureDetector"/>
            <Interceptor className="org.apache.catalina.tribes.group.interceptors.MessageDispatchInterceptor"/>
            <Interceptor className="org.apache.catalina.tribes.group.interceptors.ThroughputInterceptor"/>
          </Channel>

Tribes 使用一个堆栈来发送消息。堆栈中的每个元素都称为拦截器,其工作方式与 Tomcat servlet 容器中的阀门非常相似。使用拦截器,逻辑可以分解成更易于管理的代码片段。上面配置的拦截器是
TcpFailureDetector - 通过 TCP 验证崩溃的成员,如果多播数据包丢失,此拦截器可以防止误报,即节点被标记为崩溃,即使它仍然处于活动状态并正在运行。
MessageDispatchInterceptor - 将消息调度到一个线程(线程池)以异步发送消息。
ThroughputInterceptor - 打印关于消息流量的简单统计信息。
请注意,拦截器的顺序很重要。它们在 server.xml 中定义的方式就是它们在通道堆栈中表示的方式。可以将其视为一个链表,头部是第一个拦截器,尾部是最后一个拦截器。
更多信息,请访问 参考文档

          <Valve className="org.apache.catalina.ha.tcp.ReplicationValve"
                 filter=".*\.gif|.*\.js|.*\.jpeg|.*\.jpg|.*\.png|.*\.htm|.*\.html|.*\.css|.*\.txt"/>

集群使用阀门来跟踪对 Web 应用程序的请求,我们上面提到了 ReplicationValve 和 JvmRouteBinderValve。<Cluster> 元素本身不是 Tomcat 中管道的一部分,而是集群将阀门添加到其父容器中。如果 <Cluster> 元素在 <Engine> 元素中配置,则阀门将被添加到引擎中,依此类推。
更多信息,请访问 参考文档

          <Deployer className="org.apache.catalina.ha.deploy.FarmWarDeployer"
                    tempDir="/tmp/war-temp/"
                    deployDir="/tmp/war-deploy/"
                    watchDir="/tmp/war-listen/"
                    watchEnabled="false"/>

默认的 Tomcat 集群支持农场部署,即集群可以在其他节点上部署和取消部署应用程序。此组件的状态目前处于变化中,但很快就会得到解决。Tomcat 5.0 和 5.5 之间的部署算法发生了一些变化,在那时,此组件的逻辑发生了变化,部署目录必须与 webapps 目录匹配。
更多信息,请访问 参考文档

          <ClusterListener className="org.apache.catalina.ha.session.ClusterSessionListener"/>
        </Cluster>

由于 SimpleTcpCluster 本身是 Channel 对象的发送者和接收者,组件可以将自己注册为 SimpleTcpCluster 的监听器。上面的监听器 ClusterSessionListener 监听 DeltaManager 复制消息,并将增量应用于管理器,进而应用于会话。
更多信息,请访问 参考文档

集群架构

组件级别

         Server
           |
         Service
           |
         Engine
           |  \
           |  --- Cluster --*
           |
         Host
           |
         ------
        /      \
     Cluster    Context(1-N)
        |             \
        |             -- Manager
        |                   \
        |                   -- DeltaManager
        |                   -- BackupManager
        |
     ---------------------------
        |                       \
      Channel                    \
    ----------------------------- \
        |                          \
     Interceptor_1 ..               \
        |                            \
     Interceptor_N                    \
    -----------------------------      \
     |          |         |             \
   Receiver    Sender   Membership       \
                                         -- Valve
                                         |      \
                                         |       -- ReplicationValve
                                         |       -- JvmRouteBinderValve
                                         |
                                         -- LifecycleListener
                                         |
                                         -- ClusterListener
                                         |      \
                                         |       -- ClusterSessionListener
                                         |
                                         -- Deployer
                                                \
                                                 -- FarmWarDeployer

工作原理

为了便于理解集群的工作原理,我们将带您逐步了解一系列场景。在本场景中,我们只计划使用两个 Tomcat 实例 TomcatATomcatB。我们将涵盖以下事件序列

  1. TomcatA 启动
  2. TomcatB 启动(等待 TomcatA 启动完成)
  3. TomcatA 接收请求,创建会话 S1
  4. TomcatA 崩溃
  5. TomcatB 接收会话 S1 的请求
  6. TomcatA 启动
  7. TomcatA 接收请求,对会话 (S1) 调用失效操作。
  8. TomcatB 接收新会话 (S2) 的请求。
  9. TomcatA 会话 S2 由于 inactivity 而过期。

好的,现在我们已经有了良好的序列,我们将带您了解会话复制代码中究竟发生了什么。

  1. TomcatA 启动

    Tomcat 使用标准启动序列启动。当 Host 对象创建时,会与它关联一个集群对象。当解析上下文时,如果 web.xml 文件中存在 distributable 元素,Tomcat 会要求 Cluster 类(在本例中为 SimpleTcpCluster)为复制的上下文创建一个管理器。因此,在启用集群的情况下,在 web.xml 中设置 distributable,Tomcat 将为该上下文创建一个 DeltaManager,而不是 StandardManager。集群类将启动一个成员资格服务(组播)和一个复制服务(TCP 单播)。有关架构的更多信息,请参见本文档后面的内容。

  2. TomcatB 启动

    当 TomcatB 启动时,它遵循与 TomcatA 相同的序列,只有一个例外。集群启动并建立成员资格(TomcatA、TomcatB)。TomcatB 现在将从集群中已存在的服务器(在本例中为 TomcatA)请求会话状态。TomcatA 响应请求,在 TomcatB 开始监听 HTTP 请求之前,状态已从 TomcatA 传输到 TomcatB。如果 TomcatA 没有响应,TomcatB 将在 60 秒后超时,发出日志条目,并继续启动。会话状态将为每个在 web.xml 中具有 distributable 的 Web 应用程序传输。(注意:为了有效地使用会话复制,所有 Tomcat 实例都应配置相同。)

  3. TomcatA 接收请求,创建会话 S1

    进入 TomcatA 的请求处理方式与没有会话复制的情况完全相同,直到请求完成。此时,ReplicationValve 会在响应返回给用户之前拦截请求。此时,它会发现会话已被修改,并使用 TCP 将会话复制到 TomcatB。一旦序列化数据被传递给操作系统的 TCP 逻辑,请求就会返回给用户,并通过阀门管道返回。对于每个请求,整个会话都会被复制,这允许修改会话中属性的代码(即使没有调用 setAttribute 或 removeAttribute)也能被复制。可以使用 useDirtyFlag 配置参数来优化会话复制的次数。

  4. TomcatA 崩溃

    当 TomcatA 崩溃时,TomcatB 会收到通知,表明 TomcatA 已退出集群。TomcatB 会从其成员列表中删除 TomcatA,而 TomcatA 将不再收到 TomcatB 中发生的任何更改的通知。负载均衡器会将来自 TomcatA 的请求重定向到 TomcatB,并且所有会话都是最新的。

  5. TomcatB 接收会话 S1 的请求

    没什么特别的,TomcatB 会像处理其他请求一样处理该请求。

  6. TomcatA 启动

    在启动时,在 TomcatA 开始接收新请求并使其自身可用之前,它将遵循上面描述的启动顺序 1) 2)。它将加入集群,联系 TomcatB 获取所有会话的当前状态。一旦它收到会话状态,它就会完成加载并打开其 HTTP/mod_jk 端口。因此,在它从 TomcatB 收到会话状态之前,不会有任何请求到达 TomcatA。

  7. TomcatA 接收请求,对会话 (S1) 调用失效操作。

    invalidate 调用会被拦截,会话会被排队到失效会话中。当请求完成时,它不会发送已更改的会话,而是向 TomcatB 发送一个“过期”消息,TomcatB 也会使会话失效。

  8. TomcatB 接收新会话 (S2) 的请求。

    与步骤 3) 相同的情况。

  9. TomcatA 会话 S2 由于 inactivity 而过期。

    invalidate 调用与用户使会话失效时的方式相同,会话会被排队到失效会话中。此时,失效会话不会被复制到其他节点,直到另一个请求通过系统并检查失效队列。

呼!:)

成员资格 集群成员资格是使用非常简单的组播 ping 建立的。每个 Tomcat 实例都会定期发送组播 ping,在 ping 消息中,实例会广播其 IP 和用于复制的 TCP 监听端口。如果一个实例在给定的时间范围内没有收到这样的 ping,则该成员被认为已失效。非常简单,也非常有效!当然,您需要在系统上启用组播。

TCP 复制 一旦收到多播 ping 消息,该成员就会被添加到集群中。在下一个复制请求时,发送实例将使用主机和端口信息建立 TCP 套接字。使用此套接字,它会发送序列化数据。我选择 TCP 套接字的原因是它具有内置的流量控制和保证交付。所以我知道,当我发送一些数据时,它会到达那里 :)

分布式锁和使用帧的页面 Tomcat 不会在集群中同步会话实例。实现这种逻辑会产生过多的开销,并导致各种问题。如果您的客户端使用多个请求同时访问同一个会话,则最后一个请求将覆盖集群中的其他会话。

使用 JMX 监控您的集群

当您使用集群时,监控是一个非常重要的议题。一些集群对象是 JMX MBeans。

将以下参数添加到您的启动脚本中。

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

集群 MBeans 列表

名称 描述 MBean 对象名称 - 引擎 MBean 对象名称 - 主机
集群 完整的集群元素 type=Cluster type=Cluster,host=${HOST}
DeltaManager 此管理器控制会话并处理会话复制 type=Manager,context=${APP.CONTEXT.PATH}, host=${HOST} type=Manager,context=${APP.CONTEXT.PATH}, host=${HOST}
FarmWarDeployer 管理将应用程序部署到集群中所有节点的过程 不支持 type=Cluster, host=${HOST}, component=deployer
成员 表示集群中的一个节点 type=Cluster, component=member, name=${NODE_NAME} type=Cluster, host=${HOST}, component=member, name=${NODE_NAME}
ReplicationValve 此阀门控制复制到备份节点 type=Valve,name=ReplicationValve type=Valve,name=ReplicationValve,host=${HOST}
JvmRouteBinderValve 这是一个集群回退阀门,用于将 Session ID 更改为当前 tomcat jvmroute。 type=Valve,name=JvmRouteBinderValve, context=${APP.CONTEXT.PATH} type=Valve,name=JvmRouteBinderValve,host=${HOST}, context=${APP.CONTEXT.PATH}

常见问题解答