22.2. 使用 JGroups 进行集群通信


22.2.1. 关于 JGroups

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

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

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

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

您可以使用预配置的堆栈,或者自行定义以满足您的系统特定要求。

注意

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

22.2.2. 将 Default JGroups Channel 切换到 Use TCP

默认情况下,集群节点使用 UDP 协议进行通信。默认的 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。使用以下管理 CLI 命令,将 ee 频道切换为使用预配置的 tcp 堆栈。

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

此默认 tcp 堆栈使用 MPING 协议,该协议使用 IP 多播来发现初始集群成员资格。有关为替代成员资格发现协议配置堆栈,请参阅以下部分:

  • 使用 TCPPING 协议定义静态集群成员资格列表。
  • 使用 TCPGOSSIP 协议使用外部 gossip 路由器来发现集群的成员。

22.2.3. 配置 TCPPING

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

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

    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
    # Set the properties for the TCPPING protocol
    /subsystem=jgroups/stack=tcpping/protocol=TCPPING:write-attribute(name=properties,value={initial_hosts="HOST_A[7600],HOST_B[7600]",port_range=0,timeout=3000})
    /subsystem=jgroups/stack=tcpping/protocol=MERGE3:add
    /subsystem=jgroups/stack=tcpping/protocol=FD_SOCK:add(socket-binding=jgroups-tcp-fd)
    /subsystem=jgroups/stack=tcpping/protocol=FD: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=FRAG2:add
    # Set tcpping as the stack for the ee channel
    /subsystem=jgroups/channel=ee:write-attribute(name=stack,value=tcpping)
    run-batch
    reload

    请注意,定义的协议顺序非常重要。

  2. 修改您的环境的脚本。

    • 如果您在受管域中运行,则必须在带有 /profile=PROFILE_NAME/subsystem=jgroups 命令前指定要更新的配置集。
    • 根据您的环境调整 TCPPING 属性(可选):

      • initial_hosts :使用语法 HOST[PORT] 的逗号分隔列表,这些主机被视为已知,并可用于查找初始成员资格。
      • port_range :如果需要,您可以分配一个端口范围。如果您分配了端口范围 2,并且主机的初始端口为 7600,则 TCPPING 将尝试联系端口 7600-7602 上的主机。端口范围适用于 initial_hosts 中指定的每个地址。
      • Timeout :集群成员的超时值(以毫秒为单位)。
  3. 通过将脚本文件传递到管理 CLI,运行脚本。

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

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

22.2.4. 配置 TCPGOSSIP

此流程创建一个新的 JGroups 堆栈,它使用 TCPGOSSIP 协议来使用外部 gossip 路由器发现集群的成员。提供了一个基础脚本,它会创建一个 tcpgossip 堆栈,并将默认 ee 频道设置为使用此新堆栈。此脚本中的管理 CLI 命令必须针对您的环境自定义,并将作为批处理进行处理。

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

    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
    # Set the properties for the TCPGOSSIP protocol
    /subsystem=jgroups/stack=tcpgossip/protocol=TCPGOSSIP:write-attribute(name=properties,value={initial_hosts="HOST_A[13001]"})
    /subsystem=jgroups/stack=tcpgossip/protocol=MERGE3:add
    /subsystem=jgroups/stack=tcpgossip/protocol=FD_SOCK:add(socket-binding=jgroups-tcp-fd)
    /subsystem=jgroups/stack=tcpgossip/protocol=FD: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=FRAG2:add
    # Set tcpgossip as the stack for the ee channel
    /subsystem=jgroups/channel=ee:write-attribute(name=stack,value=tcpgossip)
    run-batch
    reload

    请注意,定义的协议顺序非常重要。

  2. 修改您的环境的脚本。

    • 如果您在受管域中运行,则必须在带有 /profile=PROFILE_NAME/subsystem=jgroups 命令前指定要更新的配置集。
    • 为您的环境调整 TCPGOSSIP 属性(可选):

      • initial_hosts :使用语法 HOST[PORT] 的逗号分隔列表,这些主机被视为已知,并可用于查找初始成员资格。
      • reconnect_interval :断开连接的存根尝试重新连接到 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 群集成员可以找到其他群集成员。

22.2.5. 将 JGroups 绑定到网络接口

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

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

重要

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

22.2.6. 保护集群

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

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

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

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

<subsystem xmlns="urn:jboss:domain:jgroups:4.0">
  <stacks>
    <stack name="udp">
      <transport type="UDP" socket-binding="jgroups-udp"/>
      <protocol type="PING"/>
      <protocol type="MERGE3"/>
      <protocol type="FD_SOCK" socket-binding="jgroups-udp-fd"/>
      <protocol type="FD_ALL"/>
      <protocol type="VERIFY_SUSPECT"/>
      <protocol type="pbcast.NAKACK2"/>
      <protocol type="UNICAST3"/>
      <protocol type="pbcast.STABLE"/>
      <protocol type="AUTH">
        <property name="auth_class">org.jgroups.auth.MD5Token</property>
        <property name="auth_value">mytoken</property> <!-- Change this password -->
        <property name="token_hash">MD5</property>
      </protocol>
      <protocol type="pbcast.GMS"/>
      <protocol type="UFC"/>
      <protocol type="MFC"/>
      <protocol type="FRAG2"/>
    </stack>
  </stacks>
</subsystem>
配置加密

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

重要

您必须对 JBoss EAP 安装应用 Red Hat JBoss Enterprise Application Platform 7.0 更新 01 或较新的累积补丁,才能访问 SYM_ENCRYPTASYM_ENCRYPT 协议。

有关应用累积补丁的信息,请参阅 JBoss EAP 补丁和升级指南

使用 Symmetric Encryption

要使用 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. jgroups 子系统中配置 SYM_ENCRYPT 协议。

    在适用的服务器配置文件中,使用适当的属性设置添加 SYM_ENCRYPT 协议。SYM_ENCRYPT 协议应在 pbcast.NAKACK2 协议前立即配置。

    <subsystem xmlns="urn:jboss:domain:jgroups:4.0">
      <stacks>
        <stack name="udp">
          <transport type="UDP" socket-binding="jgroups-udp"/>
          <protocol type="PING"/>
          <protocol type="MERGE3"/>
          <protocol type="FD_SOCK" socket-binding="jgroups-udp-fd"/>
          <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="FRAG2"/>
        </stack>
      </stacks>
    </subsystem>
注意

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

使用 Asymmetric Encryption
  1. jgroups 子系统中配置 ASYM_ENCRYPT 协议。

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

    <subsystem xmlns="urn:jboss:domain:jgroups:4.0">
      <stacks>
        <stack name="udp">
          <transport type="UDP" socket-binding="jgroups-udp"/>
          <protocol type="PING"/>
          <protocol type="MERGE3"/>
          <protocol type="FD_SOCK" socket-binding="jgroups-udp-fd"/>
          <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="FRAG2"/>
        </stack>
      </stacks>
    </subsystem>
  2. jgroups 子系统中配置 AUTH 协议。

    ASYM_ENCRYPT 需要 AUTH。具体步骤请参阅 配置身份验证 部分。

22.2.7. 配置 JGroups 线程池

jgroups 子系统包含 默认的内部oobtimer 线程池。可以为任何 JGroups 堆栈配置这些池。

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

线程池名称keepalive-timemax-threadsmin-threadsqueue-length

default

60000L

300

20

100

internal

60000L

4

2

100

oob

60000L

300

20

0

timer

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 命令的示例,在 udp 堆栈 的默认 线程池中将 max-threads 值设置为 500

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

22.2.8. 配置 JGroups Send 和 Receive Buffers

解决缓冲大小警告

默认情况下,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)

以下是在 tcp 堆栈上将 recv_buf_size 属性设置为 20000000 的示例管理 CLI 命令。

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

也可以使用管理控制台配置 JGroups 子系统来配置 JGroups 缓冲区大小,具体操作为:从 Configuration 选项卡中导航到 JGroups 子系统,查看相关的堆栈,选择 Transport,然后选择 transport Properties 选项卡。

22.2.9. JGroups 故障排除

22.2.9.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
  • 如果机器有多个接口,请验证您是否使用正确的接口。
  • 请联系您的系统管理员,以确保多播适用于您选择的接口。

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

22.2.9.2. 在失败检测失败时导致 Missing Heartbeats

有时,故障检测(FD)可以怀疑群集成员,因为某些时间 T 尚未收到心跳确认,这由 timeoutmax_tries 定义。

对于节点 A、B、C 和 D 的一个集群示例,其中 A ping B, B ping C, C pings D, 和 D pings A, C 可满足以下任何原因:

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

学习

尝试、购买和销售

社区

关于红帽文档

通过我们的产品和服务,以及可以信赖的内容,帮助红帽用户创新并实现他们的目标。

让开源更具包容性

红帽致力于替换我们的代码、文档和 Web 属性中存在问题的语言。欲了解更多详情,请参阅红帽博客.

關於紅帽

我们提供强化的解决方案,使企业能够更轻松地跨平台和环境(从核心数据中心到网络边缘)工作。

© 2024 Red Hat, Inc.