24.2. 使用 JGroups 进行群集通信

24.2.1. 关于 JGroups

JGroups 是用于可靠消息传递的工具包,可用于创建节点可以互相发送消息的群集。

jgroups 子系统提供对 JBoss EAP 中高可用性服务的组通信支持。它允许您配置指定的频道和协议堆栈,以及查看频道的运行时统计信息。当使用提供高可用性功能的配置(如受管域中的 hafull-ha 配置文件)或 standalone-ha.xml 或 standalone- full-ha. xml 配置文件时,可以使用 jgroups 子系统。

JBoss EAP 预配置了两个 JGroups 堆栈:

udp
群集中的节点使用用户数据报协议(UDP)多播互相通信。这是默认的堆栈。
tcp
群集中的节点使用传输控制协议(TCP)相互通信。
注意

TCP 的开销更大,通常被视为比 UDP 慢,因为它处理错误检查、数据包排序和拥塞控制本身。JGroups 为 UDP 处理这些功能,而 TCP 则保证其自身。在不可靠或高拥塞网络上使用 JGroups 时,或者多播不可用时,TCP 是一种不错的选择。

您可以使用预配置的堆栈或自行定义以满足系统特定要求。有关可用协议及其属性的更多信息,请参见以下部分。

24.2.2. 将默认 JGroups 频道切换为使用 TCP

默认情况下,集群节点使用为 ee JGroups 频道配置的 udp 协议堆栈进行通信。

<channels default="ee">
  <channel name="ee" stack="udp"/>
</channels>
<stacks>
  <stack name="udp">
    <transport type="UDP" socket-binding="jgroups-udp"/>
    <protocol type="PING"/>
    ...
  </stack>
  <stack name="tcp">
    <transport type="TCP" socket-binding="jgroups-tcp"/>
    <protocol type="MPING" socket-binding="jgroups-mping"/>
    ...
  </stack>
</stacks>

使用多播配置 TCP

某些网络仅允许使用 TCP。使用以下管理 CLI 命令,切换 ee 频道以使用预配置的 tcp 堆栈:

/subsystem=jgroups/channel=ee:write-attribute(name=stack,value=tcp)

此默认 tcp 堆栈使用 MPING 协议,它使用 IP 多播来发现初始群集成员资格。

在没有多播的情况下配置 TCP

当安全策略不首选或允许多播时,您可以将默认协议堆栈更改为使用 TCP。要在没有多播的情况下配置基于 TCP 的集群,请执行以下步骤:

  1. 运行以下命令,将 ee 频道切换为使用 JGroups 子系统中预先配置的 tcp 堆栈:

    <channel name="ee" stack="tcp" cluster="ejb"/>
  2. 设置集群节点的名称:

    • 在独立配置模式中,执行以下步骤之一:

      • 运行以下命令:

        <server xmlns="urn:jboss:domain:8.0" name="node_1">
      • 在启动实例时,为系统属性 jboss.node.name 指定唯一名称。
    • 在域模式中,集群服务器在 server 标签的 host-*.xml 文件中列出。默认配置指定以下服务器名称,您可以根据需要进行编辑。

      <servers>
          <server name="server-one" group="main-server-group"/>
          <server name="server-two" group="other-server-group">
              <socket-bindings port-offset="150"/>
          </server>
      </servers>
  3. 选择以下协议之一来发现其他群集成员:

    • TCPGOSSIP :此协议使用外部 Gosip 路由器服务来发现群集成员。这需要配置和管理其他进程,但允许单个 EAP 实例列出其他群集成员。如果群集成员频繁变化,此协议很有用。如需了解更多详细信息,请参阅 TCPPING
    • TCPPING :此协议定义了一个静态群集成员列表,并且要求每个节点列出所有潜在的群集成员。当群集成员地址未知且不会经常更改时,首选此协议。如需了解更多详细信息,请参阅 TCPGOSSIP

24.2.3. 配置 TCPPING

此流程创建一个新的 JGroups 堆栈,它使用 TCPPING 协议来定义静态集群成员资格列表。系统提供了基础脚本,该脚本可创建 tcpping 堆栈并将默认 频道 设置为使用此新堆栈。此脚本中的管理 CLI 命令必须为您的环境自定义,并将作为批处理处理。

  1. 将以下脚本复制到文本编辑器中,并将它保存到本地文件系统。

    # Define the socket bindings
    /socket-binding-group=standard-sockets/remote-destination-outbound-socket-binding=jgroups-host-a:add(host=HOST_A,port=7600)
    /socket-binding-group=standard-sockets/remote-destination-outbound-socket-binding=jgroups-host-b:add(host=HOST_B,port=7600)
    batch
    # Add the tcpping stack
    /subsystem=jgroups/stack=tcpping:add
    /subsystem=jgroups/stack=tcpping/transport=TCP:add(socket-binding=jgroups-tcp)
    /subsystem=jgroups/stack=tcpping/protocol=TCPPING:add(socket-bindings=[jgroups-host-a,jgroups-host-b])
    /subsystem=jgroups/stack=tcpping/protocol=MERGE3:add
    /subsystem=jgroups/stack=tcpping/protocol=FD_SOCK:add
    /subsystem=jgroups/stack=tcpping/protocol=FD_ALL:add
    /subsystem=jgroups/stack=tcpping/protocol=VERIFY_SUSPECT:add
    /subsystem=jgroups/stack=tcpping/protocol=pbcast.NAKACK2:add
    /subsystem=jgroups/stack=tcpping/protocol=UNICAST3:add
    /subsystem=jgroups/stack=tcpping/protocol=pbcast.STABLE:add
    /subsystem=jgroups/stack=tcpping/protocol=pbcast.GMS:add
    /subsystem=jgroups/stack=tcpping/protocol=MFC:add
    /subsystem=jgroups/stack=tcpping/protocol=FRAG3:add
    # Set tcpping as the stack for the ee channel
    /subsystem=jgroups/channel=ee:write-attribute(name=stack,value=tcpping)
    run-batch
    reload

    请注意,定义的协议的顺序非常重要。您还可以通过传递 add-index 值到 add 命令,将协议插入到特定的索引中。索引基于零,因此以下管理 CLI 命令添加 UNICAST3 协议作为第七个协议:

    /subsystem=jgroups/stack=tcpping/protocol=UNICAST3:add(add-index=6)
  2. 为您的环境修改 脚本。

    • 如果您在受管域中运行,则必须通过 /profile= PROFILE_NAME/subsystem=jgroups 命令之前指定要更新的配置集
    • 根据您的环境调整以下属性:

      • 套接字绑定: 以逗号分隔的主机和端口组合列表,这些组合被视为众所周知的,并可用于查找初始成员身份。有关定义 套接字绑定的更多信息,请参阅配置 套接字绑定。
      • initial_hosts :以逗号分隔的主机和端口组合列表,使用语法 HOST[PORT ] 这些 [ PORT ] 被视为广为人知且可用于查找初始成员资格,如 host1[1000],host2[2000]
      • port_range :此属性用于将 initial_hosts 端口范围扩展为指定的值。例如,如果您将 initial_hosts 设置为 host1[1000],host2[2000],并且 port_range 设为 1,则 initial_hosts 设置将扩展到 host1[1000],host1[1001],host2[2000],host2[2001]。此属性仅适用于 initial_hosts 属性。
  3. 通过将 脚本文件传递到管理 CLI 来运行 脚本。

    $ EAP_HOME/bin/jboss-cli.sh --connect --file=/path/to/SCRIPT_NAME

TCPPING 堆栈现已可用,TCP 用于网络通信。

24.2.3.1. 在独立模式中配置 TCPPING

此流程可帮助您在独立模式下为集群应用程序配置 TCP 堆栈和节点。

流程

  1. 在 JGroups 子系统中将默认堆栈从 udp 改为 tcp :

    <channel name="ee" stack="tcp" cluster="ejb"/>
  2. 将 TCP 堆栈配置为使用 TCPPING 协议代替默认的 MPING 协议。在以下代码中,initial_hosts 属性与群集内所有节点的列表相关联,而 7600 表示默认的 jgroups-tcp 端口可以根据您的配置和环境而变化。

    <stack name="tcp">
      <transport type="TCP" socket-binding="jgroups-tcp"/>
      <protocol type="TCPPING">
        <property name="initial_hosts">192.168.1.5[7600],192.168.1.9[7600]</property>
        <property name="port_range">0</property>
      </protocol>
      <protocol type="MERGE3"/>
      <protocol type="FD_SOCK" socket-binding="jgroups-tcp-fd"/>
      <protocol type="FD_ALL"/>
      <protocol type="VERIFY_SUSPECT"/>
      <protocol type="pbcast.NAKACK2"/>
      <protocol type="UNICAST3"/>
      <protocol type="pbcast.STABLE"/>
      <protocol type="pbcast.GMS"/>
      <protocol type="MFC"/>
      <protocol type="FRAG3"/>
    </stack>
    注意

    initial_hosts 中设置的端口号 7600 必须与 jgroups-tcp 套接字绑定定义中定义的端口号相同。如果将 port-offset 功能用于 socket-binding,则需要在 initial_hosts 中指定偏移后相同的值。

  3. 设置专用接口的 IP 地址,供 JGroups 组件使用。IP 地址应与 initial_hosts 中指定的 IP 地址之一相关联:

    <interface name="private">
      <inet-address value="${jboss.bind.address.private:192.168.1.5}"/>
    </interface>
  4. 重复上述步骤来配置集群中的其他节点。配置节点时,启动每个节点并部署集群应用。

验证

  • 您可以检查日志以验证节点是否已启动并在运行:

    INFO  [org.infinispan.remoting.transport.jgroups.JGroupsTransport] (thread-2,ee,node_1) ISPN000094: Received new cluster view for channel server: [node_1|1] (2) [node_1, node_2]
    INFO  [org.infinispan.remoting.transport.jgroups.JGroupsTransport] (thread-2,ee,node_1) ISPN000094: Received new cluster view for channel web: [node_1|1] (2) [node_1, node_2]

24.2.3.2. 在域模式中配置 TCPPING

此流程可帮助您在域模式中为集群应用程序配置 TCP 堆栈和节点。

流程

  1. 如果同一配置集用于多个集群,请将系统属性值设置为 initial_hosts

    <protocol type="TCPPING">
      <property name="initial_hosts">${jboss.cluster.tcp.initial_hosts}</property>
    
    Set the system property at the `server-group` level:
    <server-groups>
      <server-group name="a-server-group" profile="ha">
      <socket-binding-group ref="ha-sockets"/>
      <system-properties>
        <property name="jboss.cluster.tcp.initial_hosts" value="192.168.1.5[7600],192.168.1.9[7600]" />
      </system-properties>
  2. 在主机控制器的 XML 配置中设置专用接口的 IP 地址。专用接口的 IP 地址应当与 initial_hosts 中列出的 IP 地址之一相关联。

    <interfaces>
        ....
      <interface name="private">
        <inet-address value="${jboss.bind.address.private:192.168.1.5}"/>
      </interface>
    </interfaces>

验证

  • 您可以检查日志以验证节点是否已启动并在运行:

    INFO  [org.infinispan.remoting.transport.jgroups.JGroupsTransport] (thread-2,ee,node_1) ISPN000094: Received new cluster view for channel server: [node_1|1] (2) [node_1, node_2]
    INFO  [org.infinispan.remoting.transport.jgroups.JGroupsTransport] (thread-2,ee,node_1) ISPN000094: Received new cluster view for channel web: [node_1|1] (2) [node_1, node_2]

24.2.4. 配置 TCPGOSSIP

此流程创建一个新的 JGroups 堆栈,它使用 TCPGOSSIP 协议来使用外部 Gosip 路由器发现群集的成员。我们提供了一个基础脚本,该脚本可创建 tcpgosip 堆栈,并将 default ee 通道设置为使用此新堆栈。此脚本中的管理 CLI 命令必须为您的环境自定义,并将作为批处理处理。

  1. 将以下脚本复制到文本编辑器中,并将它保存到本地文件系统。

    # Define the socket bindings
    /socket-binding-group=standard-sockets/remote-destination-outbound-socket-binding=jgroups-host-a:add(host=HOST_A,port=13001)
    batch
    # Add the tcpgossip stack
    /subsystem=jgroups/stack=tcpgossip:add
    /subsystem=jgroups/stack=tcpgossip/transport=TCP:add(socket-binding=jgroups-tcp)
    /subsystem=jgroups/stack=tcpgossip/protocol=TCPGOSSIP:add(socket-bindings=[jgroups-host-a])
    /subsystem=jgroups/stack=tcpgossip/protocol=MERGE3:add
    /subsystem=jgroups/stack=tcpgossip/protocol=FD_SOCK:add
    /subsystem=jgroups/stack=tcpgossip/protocol=FD_ALL:add
    /subsystem=jgroups/stack=tcpgossip/protocol=VERIFY_SUSPECT:add
    /subsystem=jgroups/stack=tcpgossip/protocol=pbcast.NAKACK2:add
    /subsystem=jgroups/stack=tcpgossip/protocol=UNICAST3:add
    /subsystem=jgroups/stack=tcpgossip/protocol=pbcast.STABLE:add
    /subsystem=jgroups/stack=tcpgossip/protocol=pbcast.GMS:add
    /subsystem=jgroups/stack=tcpgossip/protocol=MFC:add
    /subsystem=jgroups/stack=tcpgossip/protocol=FRAG3:add
    # Set tcpgossip as the stack for the ee channel
    /subsystem=jgroups/channel=ee:write-attribute(name=stack,value=tcpgossip)
    run-batch
    reload

    请注意,定义的协议的顺序非常重要。您还可以通过传递 add-index 值到 add 命令,将协议插入到特定的索引中。索引基于零,因此以下管理 CLI 命令添加 UNICAST3 协议作为第七个协议:

    /subsystem=jgroups/stack=tcpgossip/protocol=UNICAST3:add(add-index=6)
  2. 为您的环境修改 脚本。

    • 如果您在受管域中运行,则必须通过 /profile= PROFILE_NAME/subsystem=jgroups 命令之前指定要更新的配置集
    • 根据您的环境调整以下属性:

      • 套接字绑定: 以逗号分隔的主机和端口组合列表,这些组合被视为众所周知的,并可用于查找初始成员身份。有关定义 套接字绑定的更多信息,请参阅配置 套接字绑定。
      • initial_hosts :以逗号分隔的主机和端口组合列表,使用语法 HOST[PORT ] 这些 [ PORT ] 被视为广为人知且可用于查找初始成员资格,如 host1[1000],host2[2000]
      • port_range :此属性用于将 initial_hosts 端口范围扩展为指定的值。例如,如果您将 initial_hosts 设置为 host1[1000],host2[2000],并且 port_range 设为 1,则 initial_hosts 设置将扩展到 host1[1000],host1[1001],host2[2000],host2[2001]。此属性仅适用于 initial_hosts 属性。
      • reconnect_interval :断开连接的 stub 尝试重新连接到 gossip 路由器的间隔(以毫秒为单位)。
      • sock_conn_timeout :套接字创建的最大时间。默认值为 1000 毫秒。
      • sock_read_timeout :阻止读取的最大时间(以毫秒为单位)。值 0 将无限期阻止。
  3. 通过将 脚本文件传递到管理 CLI 来运行 脚本。

    $ EAP_HOME/bin/jboss-cli.sh --connect --file=/path/to/SCRIPT_NAME

TCPGOSSIP 堆栈现已可用,TCP 用于网络通信。此堆栈配置为与 gossip 路由器搭配使用,以便 JGroups 群集成员能够查找其他群集成员。

24.2.5. Configure JDBC_PING

您可以使用 JDBC_PING 协议管理和发现群集中的成员资格。

JDBC_PING 使用数据源中指定的数据库来列出群集的成员。

  1. 创建一个数据源,以连接到您要用于管理集群成员资格的数据库。
  2. 将以下脚本复制到文本编辑器中,并将它保存到本地文件系统。

    batch
    # Add the JDBC_PING stack
    /subsystem=jgroups/stack=JDBC_PING:add
    /subsystem=jgroups/stack=JDBC_PING/transport=TCP:add(socket-binding=jgroups-tcp)
    /subsystem=jgroups/stack=JDBC_PING/protocol=JDBC_PING:add(data-source=ExampleDS)
    /subsystem=jgroups/stack=JDBC_PING/protocol=MERGE3:add
    /subsystem=jgroups/stack=JDBC_PING/protocol=FD_SOCK:add
    /subsystem=jgroups/stack=JDBC_PING/protocol=FD_ALL:add
    /subsystem=jgroups/stack=JDBC_PING/protocol=VERIFY_SUSPECT:add
    /subsystem=jgroups/stack=JDBC_PING/protocol=pbcast.NAKACK2:add
    /subsystem=jgroups/stack=JDBC_PING/protocol=UNICAST3:add
    /subsystem=jgroups/stack=JDBC_PING/protocol=pbcast.STABLE:add
    /subsystem=jgroups/stack=JDBC_PING/protocol=pbcast.GMS:add
    /subsystem=jgroups/stack=JDBC_PING/protocol=MFC:add
    /subsystem=jgroups/stack=JDBC_PING/protocol=FRAG3:add
    # Set JDBC_PING as the stack for the ee channel
    /subsystem=jgroups/channel=ee:write-attribute(name=stack,value=JDBC_PING)
    run-batch
    reload

    请注意,定义的协议的顺序非常重要。您还可以通过传递 add-index 值到 add 命令,将协议插入到特定的索引中。索引基于零,因此以下管理 CLI 命令添加 UNICAST3 协议作为第七个协议:

    /subsystem=jgroups/stack=JDBC_PING/protocol=UNICAST3:add(add-index=6)
  3. 为您的环境修改 脚本。

    • 如果您在受管域中运行,则必须通过 /profile= PROFILE_NAME/subsystem=jgroups 命令之前指定要更新的配置集
    • 将 'ExampleDS' 替换为在第 1 步中定义的数据源的名称。
  4. 通过将 脚本文件传递到管理 CLI 来运行 脚本。

    $ EAP_HOME/bin/jboss-cli.sh --connect --file=/path/to/SCRIPT_NAME

JDBC_PING 堆栈现已可用,TCP 用于网络通信。

jdbc_PING: https://developer.jboss.org/wiki/JDBCPING

创建数据源:关于 JBoss EAP 数据源 ???

24.2.6. 将 JGroups 绑定到网络接口

默认情况下,JGroups 仅绑定到 专用 网络接口,后者指向默认配置中的 localhost。出于安全考虑,JGroups 不会绑定到 JBoss EAP 启动期间由 -b 参数定义的网络接口,因为集群流量不应在公共网络接口上公开。

有关如何 配置网络接口的详情, 请查看本指南中的网络配置章节。

重要

出于安全考虑,JGroups 仅应绑定到非公共网络接口。出于性能原因,我们还建议 JGroups 流量的网络接口应该是专用虚拟局域网(VLAN)的一部分。

24.2.7. 保护集群

要安全运行集群,需要解决几个问题:

  • 防止未经授权的节点加入集群。这可以通过需要 身份验证 来解决。
  • 防止非成员与群集成员通信.这可以通过 加密消息 来解决。

24.2.7.1. 配置身份验证

JGroups 身份验证由 AUTH 协议执行。目的是确保只有经过身份验证的节点才能加入群集。

在适用的服务器配置文件中,使用适当的属性设置添加 AUTH 协议。AUTH 协议应该在 pbcast.GMS 协议之前配置。

以下示例演示了如何将 AUTH 与不同类型的授权令牌搭配使用。

带有简单令牌的AUTH
...
<protocol type="pbcast.STABLE"/>
<auth-protocol type="AUTH">
  <plain-token>
    <shared-secret-reference clear-text="my_password"/>
  </plain-token>
</auth-protocol>
<protocol type="pbcast.GMS"/>
...
带有 Digest Algorithm 令牌的 AUTH

此格式可与任何摘要算法一起使用,如 MD5 或 SHA-2。JBoss EAP 7.4 的默认摘要算法是 SHA-256,JVM 支持最强大的摘要算法。很多 JVM 还将实施 SHA-512。

...
<protocol type="pbcast.STABLE"/>
<auth-protocol type="AUTH">
  <digest-token algorithm="SHA-512">
    <shared-secret-reference clear-text="my_password"/>
  </digest-token>
</auth-protocol>
<protocol type="pbcast.GMS"/>
...
带有 X509 令牌的 AUTH

本例在 elytron 子系统中创建新的密钥存储,并在 JGroups AUTH 配置中引用它。

  1. 创建密钥存储:

    $ keytool -genkeypair -alias jgroups_key -keypass my_password -storepass my_password -storetype jks -keystore jgroups.keystore -keyalg RSA
  2. 使用管理 CLI 将密钥存储添加到 elytron 子系统:

    /subsystem=elytron/key-store=jgroups-token-store:add(type=jks,path=/path/to/jgroups.keystore,credential-reference={clear-text=my_password}, required=true)
  3. 在 JGroups 堆栈定义中,将 AUTH 配置为使用密钥存储:

    ...
    <protocol type="pbcast.STABLE"/>
    <auth-protocol type="AUTH">
      <cipher-token algorithm="RSA" key-alias="jgroups_key" key-store="jgroups-token-store">
        <shared-secret-reference clear-text="my_password"/>
        <key-credential-reference clear-text="my_password"/>
      </cipher-token>
    </auth-protocol>
    <protocol type="pbcast.GMS"/>
    ...

24.2.7.2. 配置加密

为加密消息,JGroups 使用由群集成员共享的机密密钥。发送方使用共享机密密钥加密消息,接收方使用相同的机密密钥解密消息。通过使用 SYM_ENCRYPT 协议配置的 对称加密,节点使用共享密钥存储来检索密钥。使用 ASYM_ENCRYPT 协议配置的非 对称加密 时,节点在使用 AUTH 进行身份验证后,从集群的协调人员检索机密密钥。

使用对称加密

要使用 SYM_ENCRYPT,您必须设置一个密钥存储,该存储将在每个节点的 JGroups 配置中引用。

  1. 创建密钥存储.

    在以下命令中,将 VERSION 替换为适当的 JGroups JAR 版本,并将 PASSWORD 替换为密钥存储密码。

    $ java -cp EAP_HOME/modules/system/layers/base/org/jgroups/main/jgroups-VERSION.jar org.jgroups.demos.KeyStoreGenerator --alg AES --size 128 --storeName defaultStore.keystore --storepass PASSWORD --alias mykey

    这将生成一个 defaultStore.keystore 文件,该文件将在 JGroups 配置中引用。

  2. 生成密钥存储后,将使用以下两种方法之一在 SYM_PROTOCOL 中定义它。

注意

使用 SYM_ENCRYPT 时配置 AUTH 是可选的。

通过直接引用密钥存储使用对称加密
  1. jgroups 子系统中配置 SYM_ENCRYPT 协议。

    在适用的服务器配置文件中,使用适当的属性设置添加 SYM_ENCRYPT 协议。此协议将引用之前创建的密钥存储。SYM_ENCRYPT 协议应该在 pbcast.NAKACK2 协议之前立即配置。

    <subsystem xmlns="urn:jboss:domain:jgroups:6.0">
      <stacks>
        <stack name="udp">
          <transport type="UDP" socket-binding="jgroups-udp"/>
          <protocol type="PING"/>
          <protocol type="MERGE3"/>
          <protocol type="FD_SOCK"/>
          <protocol type="FD_ALL"/>
          <protocol type="VERIFY_SUSPECT"/>
          <protocol type="SYM_ENCRYPT">
            <property name="provider">SunJCE</property>
            <property name="sym_algorithm">AES</property>
            <property name="encrypt_entire_message">true</property>
            <property name="keystore_name">/path/to/defaultStore.keystore</property>
            <property name="store_password">PASSWORD</property>
            <property name="alias">mykey</property>
          </protocol>
          <protocol type="pbcast.NAKACK2"/>
          <protocol type="UNICAST3"/>
          <protocol type="pbcast.STABLE"/>
          <protocol type="pbcast.GMS"/>
          <protocol type="UFC"/>
          <protocol type="MFC"/>
          <protocol type="FRAG3"/>
        </stack>
      </stacks>
    </subsystem>
通过 Elytron 使用对称加密
  1. 利用管理 CLI,在 elytron 子系统中创建密钥存储,该子系统引用 使用对称加密 在 中创建的 defaultStore.keystore

    /subsystem=elytron/key-store=jgroups-keystore:add(path=/path/to/defaultStore.keystore,credential-reference={clear-text=PASSWORD},type=JCEKS)
  2. 使用适当的属性设置,在 jgroups 子系统中添加 SYM_ENCRYPT 协议。SYM_ENCRYPT 协议应该在 pbcast.NAKACK2 协议之前配置,如以下配置所示。

    <subsystem xmlns="urn:jboss:domain:jgroups:6.0">
      <stacks>
        <stack name="udp">
          <transport type="UDP" socket-binding="jgroups-udp"/>
          <protocol type="PING"/>
          <protocol type="MERGE3"/>
          <protocol type="FD_SOCK"/>
          <protocol type="FD_ALL"/>
          <protocol type="VERIFY_SUSPECT"/>
          <encrypt-protocol type="SYM_ENCRYPT" key-alias="mykey" key-store="jgroups-keystore">
            <key-credential-reference clear-text="PASSWORD"/>
            <property name="provider">SunJCE</property>
            <property name="encrypt_entire_message">true</property>
          </encrypt-protocol>
          <protocol type="pbcast.NAKACK2"/>
          <protocol type="UNICAST3"/>
          <protocol type="pbcast.STABLE"/>
          <protocol type="pbcast.GMS"/>
          <protocol type="UFC"/>
          <protocol type="MFC"/>
          <protocol type="FRAG3"/>
        </stack>
      </stacks>
    </subsystem>
    注意

    上例使用明文密码;但是,也可以定义凭据存储来定义配置文件外的密码。有关配置此存储的更多信息,请参阅 如何配置服务器安全 指南中 的凭证存储 部分。

使用对称加密

要使用 ASYM_ENCRYPT,必须定义 AUTH 协议。有关在 jgroups 子系统中配置 AUTH 协议的说明,请参阅配置 身份验证 部分。

ASYM_ENCRYPT 使用以下两种方法之一进行配置:

通过生成 secret 密钥使用对称加密
  1. jgroups 子系统中配置 ASYM_ENCRYPT 协议。

    在适用的服务器配置文件中,使用适当的属性设置添加 ASYM_ENCRYPT 协议。ASYM_ENCRYPT 协议应该在 pbcast.NAKACK2 协议之前配置,如以下配置所示。

    <subsystem xmlns="urn:jboss:domain:jgroups:6.0">
      <stacks>
        <stack name="udp">
          <transport type="UDP" socket-binding="jgroups-udp"/>
          <protocol type="PING"/>
          <protocol type="MERGE3"/>
          <protocol type="FD_SOCK"/>
          <protocol type="FD_ALL"/>
          <protocol type="VERIFY_SUSPECT"/>
          <protocol type="ASYM_ENCRYPT">
            <property name="encrypt_entire_message">true</property>
            <property name="sym_keylength">128</property>
            <property name="sym_algorithm">AES/ECB/PKCS5Padding</property>
            <property name="asym_keylength">512</property>
            <property name="asym_algorithm">RSA</property>
          </protocol>
          <protocol type="pbcast.NAKACK2"/>
          <protocol type="UNICAST3"/>
          <protocol type="pbcast.STABLE"/>
          <!-- Configure AUTH protocol here -->
          <protocol type="pbcast.GMS"/>
          <protocol type="UFC"/>
          <protocol type="MFC"/>
          <protocol type="FRAG3"/>
        </stack>
      </stacks>
    </subsystem>
通过 Elytron 使用非对称加密
  1. 创建密钥存储以包含密钥对。以下命令使用 mykey 条目创建一个密钥存储:

    $ keytool -genkeypair -alias mykey -keyalg RSA -keysize 1024 -keystore defaultKeystore.keystore -dname "CN=localhost" -keypass secret -storepass secret
  2. 使用管理 CLI,在 elytron 子系统中创建密钥存储,以引用 defaultStore.keystore

    /subsystem=elytron/key-store=jgroups-keystore:add(path=/path/to/defaultStore.keystore,credential-reference={clear-text=PASSWORD},type=JCEKS)
  3. 使用适当的属性设置,在 jgroups 子系统中添加 ASYM_ENCRYPT 协议。ASYM_ENCRYPT 协议应该在 pbcast.NAKACK2 协议之前配置,如以下配置所示。

    <subsystem xmlns="urn:jboss:domain:jgroups:6.0">
      <stacks>
        <stack name="udp">
          <transport type="UDP" socket-binding="jgroups-udp"/>
          <protocol type="PING"/>
          <protocol type="MERGE3"/>
          <protocol type="FD_SOCK"/>
          <protocol type="FD_ALL"/>
          <protocol type="VERIFY_SUSPECT"/>
          <encrypt-protocol type="ASYM_ENCRYPT" key-alias="mykey" key-store="jgroups-keystore">
            <key-credential-reference clear-text="secret" />
            <property name="encrypt_entire_message">true</property>
          </encrypt-protocol>
          <protocol type="pbcast.NAKACK2"/>
          <protocol type="UNICAST3"/>
          <protocol type="pbcast.STABLE"/>
          <!-- Configure AUTH protocol here -->
          <protocol type="pbcast.GMS"/>
          <protocol type="UFC"/>
          <protocol type="MFC"/>
          <protocol type="FRAG3"/>
        </stack>
      </stacks>
    </subsystem>
    注意

    上例使用明文密码;但是,也可以定义凭据存储来定义配置文件外的密码。有关配置此存储的更多信息,请参阅 如何配置服务器安全 指南中 的凭证存储 部分。

24.2.8. 配置 JGroups 线程池

jgroups 子系统包含 default、internal oobtimer 线程池。可以为任何 JGroups 堆栈配置这些池,并且不影响本地节点上配置的 bean 或其他池。JGroup 线程池用于支持集群通信。

下表列出了您可以为每个线程池配置的属性以及每个线程的默认值。

线程池名称描述keepalive-timemax-threadsMin-threadsqueue-length

default

此池用于处理没有标记为带外的传入信息。

60000L

300

20

100

internal

此池用于处理 EAP 维护所需的内部进程。

60000L

4

2

100

oob

此池用于处理传入的带外信息。

60000L

300

20

0

计时器

此池用于处理时间绑定调度程序消息。

5000L

4

2

500

利用下列语法,通过管理 CLI 配置 JGroups 线程池:

/subsystem=jgroups/stack=STACK_TYPE/transport=TRANSPORT_TYPE/thread-pool=THREAD_POOL_NAME:write-attribute(name=ATTRIBUTE_NAME, value=ATTRIBUTE_VALUE)

以下是管理 CLI 命令的示例,可将 the udp 堆栈 的默认 线程池中的 max-threads 值设置为 500

/subsystem=jgroups/stack=udp/transport=UDP/thread-pool=default:write-attribute(name="max-threads", value="500")

24.2.9. 配置 JGroups 发送和接收缓冲区

解决缓冲区大小警告

默认情况下,JGroups 配置有特定的发送和接收缓冲区值;但是,您的操作系统可能会限制可用的缓冲区大小,JBoss EAP 可能无法使用其配置的缓冲区值。在这种情况下,您将在 JBoss EAP 日志中看到类似如下的警告:

WARNING [org.jgroups.protocols.UDP] (ServerService Thread Pool -- 68)
JGRP000015: the send buffer of socket DatagramSocket was set to 640KB, but the OS only allocated 212.99KB.
This might lead to performance problems. Please set your max send buffer in the OS correctly (e.g. net.core.wmem_max on Linux)
WARNING [org.jgroups.protocols.UDP] (ServerService Thread Pool -- 68)
JGRP000015: the receive buffer of socket DatagramSocket was set to 20MB, but the OS only allocated 212.99KB.
This might lead to performance problems. Please set your max receive buffer in the OS correctly (e.g. net.core.rmem_max on Linux)

要解决这个问题,请查阅您的操作系统文档来了解如何增加缓冲区大小。对于 Red Hat Enterprise Linux 系统,以 root 用户身份编辑 /etc/sysctl.conf,为在系统重启后保留的缓冲区大小配置最大值。例如:

# Allow a 25MB UDP receive buffer for JGroups
net.core.rmem_max = 26214400
# Allow a 1MB UDP send buffer for JGroups
net.core.wmem_max = 1048576

修改 /etc/sysctl.conf 后,运行 sysctl -p 以使更改生效。

配置 JGroups 缓冲器大小

您可以通过在 UDP 和 TCP JGroups 堆栈中设置以下传输属性来配置 JBoss EAP 使用的 JGroups 缓冲区大小:

UDP Stack
  • ucast_recv_buf_size
  • ucast_send_buf_size
  • mcast_recv_buf_size
  • mcast_send_buf_size
TCP Stack
  • recv_buf_size
  • send_buf_size

可以使用管理控制台或管理 CLI 来配置 JGroups 缓冲区大小。

使用以下语法,通过管理 CLI 设置 JGroups 缓冲区大小属性:

/subsystem=jgroups/stack=STACK_NAME/transport=TRANSPORT/property=PROPERTY_NAME:add(value=BUFFER_SIZE)

以下是一个管理 CLI 命令示例,可将 tcp 堆栈上的 recv_buf_size 属性设置为 20000000

/subsystem=jgroups/stack=tcp/transport=TRANSPORT/property=recv_buf_size:add(value=20000000)

也可以使用管理控制台,从 Configuration 选项卡导航到 JGroups 子系统,单击 View,选择 Stack 选项卡,选择适当的堆栈,再单击 传输,编辑 Properties 字段,以此配置 JGroups 缓冲区大小。

24.2.10. 调整 JGroups 子系统

有关监控 jgroups 子系统性能并优化性能的提示,请参阅 性能调优指南中的 JGroups Subsystem Tuning 部分。

24.2.11. JGroups 故障排除

24.2.11.1. 节点不构建集群

确保您的计算机已针对 IP 多播正确设置。JBoss EAP 随附了两个测试程序,它们可用于测试 IP 多播: McastReceiverTestMcastSenderTest

在终端中,启动 McastReceiverTest

$ java -cp EAP_HOME/bin/client/jboss-client.jar org.jgroups.tests.McastReceiverTest -mcast_addr 230.11.11.11 -port 5555

然后,在另一个终端窗口中启动 McastSenderTest

$ java -cp EAP_HOME/bin/client/jboss-client.jar org.jgroups.tests.McastSenderTest -mcast_addr 230.11.11.11 -port 5555

如果要绑定到特定网络接口卡(NIC),请使用 -bind_addr YOUR_BIND_ADDRESS,其中 YOUR_BIND_ADDRESS 是您要绑定的 NIC 的 IP 地址。在发送方和接收方中使用此参数。

McastSenderTest 终端窗口中键入时,您应当会在 McastReceiverTest 窗口中看到输出。如果没有,请尝试以下步骤:

  • 通过向 sender 命令添加 -ttl VALUE 来提高多播数据包的生存时间。此测试程序使用的默认值为 32VALUE 不得大于 255
  • 如果计算机有多个接口,请验证您是否正在使用正确的接口。
  • 联系系统管理员以确保多播能够处理您选择的接口。

旦您知道多播在集群中的每一台机器上正常工作,您可以重复上述测试来测试网络,将发送者放在一台机器上,接收方放在另一台机器上。

24.2.11.2. 缺少 Heartbeats 失败检测的原因

有时,群集成员因故障检测(FD)而怀疑,因为某些时间段内未收到心跳确认,T 是由 超时max_tries 定义的。

例如,节点 A、B、C 和 D 的集群,其中 A ping B、B ping C、C ping D 和 D ping A,C 可能会因为以下原因而怀疑:

  • B 或 C 以 100% CPU 运行,超过 T 秒。因此,即使 C 发送心跳确认到 B,B 可能无法处理它,因为它处于 100% 的 CPU 使用率。
  • B 或 C 是垃圾收集方式,导致的情况与上方相同。
  • 以上两个案例的组合。
  • 网络丢失数据包。网络中有很多流量时通常会出现这种情况,交换机开始丢弃数据包,通常首先广播,然后是 IP 多播,最后是 TCP 数据包。
  • B 或 C 正在处理回调。例如,如果 C 在其通道上收到处理用 T + 1 秒的远程方法调用,此时 C 将不会处理任何其他消息,包括心跳。因此,B 将不会收到心跳确认,并将怀疑 C。