配置 AMQ Broker

Red Hat AMQ 2021.Q3

用于 AMQ Broker 7.9

摘要

本指南描述了如何配置 AMQ 代理。

使开源包含更多

红帽承诺替换我们的代码、文档和网页属性中存在问题的语言。我们从这四个术语开始: master、slave、blacklist 和 whitelist。这些更改将在即将发行的几个发行本中逐渐实施。详情请查看 CTO Chris Wright 的信息

第 1 章 概述

AMQ 代理配置文件定义代理实例的重要设置。通过编辑代理的配置文件,您可以控制代理在您的环境中的工作方式。

1.1. AMQ Broker 配置文件和位置

代理的所有配置文件都存储在 <broker_instance_dir>/etc 中。您可以通过编辑这些配置文件中的设置来配置代理。

每个代理实例都使用以下配置文件:

broker.xml
主配置文件。您可以使用此文件配置代理的大多数方面,如网络连接、安全设置、消息地址等。
bootstrap.xml
AMQ Broker 用于启动代理实例的文件。您可以使用它来更改 broker.xml 的位置,配置 Web 服务器,并设置一些安全设置。
logging.properties
您可以使用此文件来设置代理实例的日志记录属性。
artemis.profile
您可以使用此文件设置代理实例运行时使用的环境变量。
login.config, artemis-users.properties, artemis-roles.properties
与安全相关的文件.您可以使用这些文件设置用户访问代理实例的身份验证。

1.2. 了解 default 代理配置

您可以通过编辑 broker.xml 配置文件来配置代理的大多数功能。该文件包含默认设置,足以启动和操作代理。但是,您可能需要更改一些默认设置,并添加新设置来为您的环境配置代理。

默认情况下,broker.xml 包含以下功能的默认设置:

  • 消息持久性
  • 接收器
  • 安全性
  • 消息地址

默认消息持久性设置

默认情况下,AMQ 代理持久性使用仅附加的文件日志,它由磁盘上的一组文件组成。日志保存消息、事务和其他信息。

<configuration ...>

   <core ...>

      ...

      <persistence-enabled>true</persistence-enabled>

      <!-- this could be ASYNCIO, MAPPED, NIO
           ASYNCIO: Linux Libaio
           MAPPED: mmap files
           NIO: Plain Java Files
       -->
      <journal-type>ASYNCIO</journal-type>

      <paging-directory>data/paging</paging-directory>

      <bindings-directory>data/bindings</bindings-directory>

      <journal-directory>data/journal</journal-directory>

      <large-messages-directory>data/large-messages</large-messages-directory>

      <journal-datasync>true</journal-datasync>

      <journal-min-files>2</journal-min-files>

      <journal-pool-files>10</journal-pool-files>

      <journal-file-size>10M</journal-file-size>

      <!--
       This value was determined through a calculation.
       Your system could perform 8.62 writes per millisecond
       on the current journal configuration.
       That translates as a sync write every 115999 nanoseconds.

       Note: If you specify 0 the system will perform writes directly to the disk.
             We recommend this to be 0 if you are using journalType=MAPPED and journal-datasync=false.
      -->
      <journal-buffer-timeout>115999</journal-buffer-timeout>

      <!--
        When using ASYNCIO, this will determine the writing queue depth for libaio.
       -->
      <journal-max-io>4096</journal-max-io>

      <!-- how often we are looking for how many bytes are being used on the disk in ms -->
      <disk-scan-period>5000</disk-scan-period>

      <!-- once the disk hits this limit the system will block, or close the connection in certain protocols
           that won't support flow control. -->
      <max-disk-usage>90</max-disk-usage>

      <!-- should the broker detect dead locks and other issues -->
      <critical-analyzer>true</critical-analyzer>

      <critical-analyzer-timeout>120000</critical-analyzer-timeout>

      <critical-analyzer-check-period>60000</critical-analyzer-check-period>

      <critical-analyzer-policy>HALT</critical-analyzer-policy>

      ...

  </core>

</configuration>

默认接收器设置

代理通过使用接收器 配置 元素来侦听传入客户端连接,以定义客户端可用于进行连接的端口和协议。默认情况下,AMQ Broker 包括每个支持的消息传递协议接收器,如下所示。

<configuration ...>

   <core ...>

      ...

      <acceptors>

        <!-- Acceptor for every supported protocol -->
        <acceptor name="artemis">tcp://0.0.0.0:61616?tcpSendBufferSize=1048576;tcpReceiveBufferSize=1048576;protocols=CORE,AMQP,STOMP,HORNETQ,MQTT,OPENWIRE;useEpoll=true;amqpCredits=1000;amqpLowCredits=300</acceptor>

        <!-- AMQP Acceptor. Listens on default AMQP port for AMQP traffic -->
        <acceptor name="amqp">tcp://0.0.0.0:5672?tcpSendBufferSize=1048576;tcpReceiveBufferSize=1048576;protocols=AMQP;useEpoll=true;amqpCredits=1000;amqpLowCredits=300</acceptor>

        <!-- STOMP Acceptor -->
        <acceptor name="stomp">tcp://0.0.0.0:61613?tcpSendBufferSize=1048576;tcpReceiveBufferSize=1048576;protocols=STOMP;useEpoll=true</acceptor>

        <!-- HornetQ Compatibility Acceptor. Enables HornetQ Core and STOMP for legacy HornetQ clients. -->
        <acceptor name="hornetq">tcp://0.0.0.0:5445?anycastPrefix=jms.queue.;multicastPrefix=jms.topic.;protocols=HORNETQ,STOMP;useEpoll=true</acceptor>

        <!-- MQTT Acceptor -->
        <acceptor name="mqtt">tcp://0.0.0.0:1883?tcpSendBufferSize=1048576;tcpReceiveBufferSize=1048576;protocols=MQTT;useEpoll=true</acceptor>

      </acceptors>

      ...

  </core>

</configuration>

默认安全设置

AMQ Broker 包含灵活的基于角色的安全模型,用于根据队列将安全性应用到队列中。默认配置使用通配符将 amq 角色应用到所有地址(由数字符号 # 表示)。

<configuration ...>

   <core ...>

      ...

      <security-settings>
         <security-setting match="#">
            <permission type="createNonDurableQueue" roles="amq"/>
            <permission type="deleteNonDurableQueue" roles="amq"/>
            <permission type="createDurableQueue" roles="amq"/>
            <permission type="deleteDurableQueue" roles="amq"/>
            <permission type="createAddress" roles="amq"/>
            <permission type="deleteAddress" roles="amq"/>
            <permission type="consume" roles="amq"/>
            <permission type="browse" roles="amq"/>
            <permission type="send" roles="amq"/>
            <!-- we need this otherwise ./artemis data imp wouldn't work -->
            <permission type="manage" roles="amq"/>
         </security-setting>
      </security-settings>

      ...

  </core>

</configuration>

默认消息地址设置

AMQ Broker 包含一个默认地址,用于建立一组要应用到任何创建的队列或主题的默认配置设置。

另外,默认配置定义了两个队列:DLQ (Dead Letter Queue)处理到达无已知目的地的消息,Expiry Queue 包含在其过期时间已过期的消息,因此不应路由到其原始目的地。

<configuration ...>

   <core ...>

      ...

      <address-settings>
         ...
         <!--default for catch all-->
         <address-setting match="#">
            <dead-letter-address>DLQ</dead-letter-address>
            <expiry-address>ExpiryQueue</expiry-address>
            <redelivery-delay>0</redelivery-delay>
            <!-- with -1 only the global-max-size is in use for limiting -->
            <max-size-bytes>-1</max-size-bytes>
            <message-counter-history-day-limit>10</message-counter-history-day-limit>
            <address-full-policy>PAGE</address-full-policy>
            <auto-create-queues>true</auto-create-queues>
            <auto-create-addresses>true</auto-create-addresses>
            <auto-create-jms-queues>true</auto-create-jms-queues>
            <auto-create-jms-topics>true</auto-create-jms-topics>
         </address-setting>
      </address-settings>

      <addresses>
         <address name="DLQ">
            <anycast>
               <queue name="DLQ" />
            </anycast>
         </address>
         <address name="ExpiryQueue">
            <anycast>
               <queue name="ExpiryQueue" />
            </anycast>
         </address>
      </addresses>

   </core>

</configuration>

1.3. 重新加载配置更新

默认情况下,代理每 5000 毫秒检查配置文件中的更改。如果代理检测到配置文件的"最后修改"时间戳中的更改,代理会决定配置更改发生。在这种情况下,代理会重新加载配置文件以激活更改。

当代理重新载入 broker.xml 配置文件时,它会重新载入以下模块:

  • 地址设置和队列

    重新载入配置文件时,地址设置决定了如何处理从 配置文件中删除的地址和队列。您可以使用 config-delete-addresses 和 config- delete-queues 属性设置此项。如需更多信息,请参阅 附录 B, 地址设置配置元素

  • 安全设置

    可以重新载入现有接收器上的 SSL/TLS 密钥存储和信任存储来建立新证书,而不会对现有客户端造成任何影响。连接的客户端,甚至具有较旧或不同证书的客户端也可以继续发送和接收消息。

  • 转变

    配置重新加载将部署 添加的任何新转变。但是,在重启代理前,从配置中移除或更改 <divert> 元素中的子元素不会生效。

以下流程演示了如何更改代理检查对 broker.xml 配置文件的更改间隔。

流程

  1. 打开 <broker_instance_dir>/etc/broker.xml 配置文件。
  2. <core> 元素中添加 <configuration-file-refresh-period> 元素并设置刷新周期(以毫秒为单位)。

    本例将配置刷新周期设置为 60000 毫秒:

    <configuration>
        <core>
            ...
            <configuration-file-refresh-period>60000</configuration-file-refresh-period>
            ...
        </core>
    </configuration>

如果出于某种原因无法访问配置文件,则可以使用管理 API 或控制台强制重新加载配置文件。可以使用 ActiveMQServerControl 上的管理操作 reloadConfigurationFile()( 使用 ObjectName org.apache.activemq.artemis:broker="BROKER_NAME" 或资源 名称服务器)重新加载配置文件。

其它资源

  • 了解如何使用管理 API,请参阅在管理 AMQ Broker 中使用 Management API

1.4. 模块化代理配置文件

如果您有多个共享通用配置设置的代理,您可以在单独的文件中定义通用配置,然后将这些文件包含在每个代理的 broker.xml 配置文件中。

您可以在代理之间共享的最常见配置设置包括:

  • 地址
  • 地址设置
  • 安全设置

流程

  1. 为您要共享的每个 broker.xml 部分创建单独的 XML 文件。

    每个 XML 文件只能包含来自 broker.xml 的一个部分(例如,地址或地址设置,但不能同时设置)。顶级元素还必须定义元素命名空间(xmlns="urn:activemq:core")

    本例显示了 my-security-settings.xml 中定义的安全设置配置:

    my-security-settings.xml

    <security-settings xmlns="urn:activemq:core">
       <security-setting match="a1">
          <permission type="createNonDurableQueue" roles="a1.1"/>
       </security-setting>
       <security-setting match="a2">
          <permission type="deleteNonDurableQueue" roles="a2.1"/>
       </security-setting>
    </security-settings>

  2. 为每个应使用通用配置设置的代理打开 <broker_instance_dir> /etc/broker.xml 配置文件。
  3. 对于您打开的每个 broker.xml 文件,执行以下操作:

    1. broker.xml 开头的 <configuration> 元素 中,验证是否出现以下行:

      xmlns:xi="http://www.w3.org/2001/XInclude"
    2. 为包含共享配置设置的每个 XML 文件添加 XML 包含。

      此示例包含 my-security-settings.xml 文件。

      broker.xml

      <configuration ...>
          <core ...>
              ...
              <xi:include href="/opt/my-broker-config/my-security-settings.xml"/>
              ...
          </core>
      </configuration>

    3. 如果需要,验证 broker.xml 以验证 XML 是否对架构有效。

      您可以使用任何 XML 验证器程序。这个示例使用 xmllint 针对 artemis-server .xsl 模式验证 broker. xml。

      $ xmllint --noout --xinclude --schema /opt/redhat/amq-broker/amq-broker-7.2.0/schema/artemis-server.xsd /var/opt/amq-broker/mybroker/etc/broker.xml
      /var/opt/amq-broker/mybroker/etc/broker.xml validates

其它资源

1.4.1. 重新加载模块配置文件

当代理定期检查配置更改时(根据 configuration-file-refresh-period指定的频率),它 不会自动 检测通过 xi:include 对在 broker.xml 配置文件中包含的配置文件进行的更改。例如,如果 broker.xml 包含 my-address-settings.xml,并且您对 my-address-settings.xml 进行配置更改,代理不会自动检测 my-address-settings.xml 中的 更改并重新加载配置。

强制 重新加载 broker.xml 配置文件以及其中包含的任何修改的配置文件,您必须确保 broker.xml 配置文件的"最后修改"时间戳已更改。您可以使用标准 Linux touch 命令更新 broker.xml 最后修改的时间戳,而不进行任何其他更改。例如:

$ touch -m <broker_instance_dir>/etc/broker.xml

或者,您可以使用管理 API 来强制重新加载代理。可以使用 ActiveMQServerControl 上的管理操作 reloadConfigurationFile()( 使用 ObjectName org.apache.activemq.artemis:broker="BROKER_NAME" 或资源 名称服务器)重新加载配置文件。

其它资源

  • 了解如何使用管理 API,请参阅在管理 AMQ Broker 中使用 Management API

1.5. 文档惯例

本文档对 sudo 命令、文件路径和可替换值使用以下惯例:

sudo 命令

在本文档中,sudo 用于任何需要 root 特权的命令。使用 sudo 时,您应始终谨慎操作,因为任何更改都可能会影响整个系统。

有关使用 sudo 的更多信息,请参阅 sudo 命令

关于在此文档中使用文件路径

在这个文档中,所有文件路径都对 Linux、UNIX 和类似操作系统(例如 /home/...)有效。如果您使用的是 Microsoft Windows,则应使用等效的 Microsoft Windows 路径(例如,C:\Users\...)。

可替换值

本文档有时会使用可替换值,您必须将这些值替换为特定于环境的值。可替换的值为小写,用方括号(<>)括起,样式则使用斜体和 单空间 字体。用下划线(_)分隔多个词语。

例如,在以下命令中,将 <install_dir> 替换为您自己的目录名称。

$ <install_dir>/bin/artemis create mybroker

第 2 章 在网络连接中配置接收器和连接器

AMQ Broker 中使用两种类型的连接:网络连接和虚拟机 内连接。当双方位于不同的虚拟机中时,无论是位于同一服务器还是物理远程,都使用网络连接。当客户端(应用程序或服务器)驻留在与代理相同的虚拟机上时,将使用虚拟机内连接。

网络连接使用 Netty。Netty 是一个高性能、低级网络库,能够以几种不同的方式配置网络连接;使用 Java IO 或 NIO、TCP 套接字、SSL/TLS 或通过 HTTP 或 HTTPS 进行隧道。Netty 还允许单个端口用于所有消息传递协议。代理将自动检测正在使用的协议,并将传入消息定向到适当的处理程序以进行进一步处理。

网络连接的 URI 决定其类型。例如,在 URI 中指定 vm 会创建一个 in-VM 连接:

<acceptor name="in-vm-example">vm://0</acceptor>

或者,在 URI 中指定 tcp 可创建网络连接。例如:

<acceptor name="network-example">tcp://localhost:61617</acceptor>

下面的部分描述了网络连接和虚拟机内连接所需的两个重要配置元素: 接收器连接器。这些部分介绍如何为 TCP、HTTP 和 SSL/TLS 网络连接以及虚拟机中的连接配置接收器和连接器。

2.1. 关于接收器

接收器 定义如何与代理建立连接。每个接收器定义客户端可用于进行连接的端口和协议。下方显示了一个简单的接收器配置。

<acceptors>
   <acceptor name="example-acceptor">tcp://localhost:61617</acceptor>
</acceptors>

您在代理配置中定义的每个接收器 元素 包含在单个 接收器 元素中。您可以为代理定义的接收器数量没有上限。默认情况下,AMQ Broker 包括每个支持的消息传递协议接收器,如下所示:

<configuration ...>
   <core ...>
      ...
      <acceptors>
        ...
        <!-- Acceptor for every supported protocol -->
        <acceptor name="artemis">tcp://0.0.0.0:61616?tcpSendBufferSize=1048576;tcpReceiveBufferSize=1048576;protocols=CORE,AMQP,STOMP,HORNETQ,MQTT,OPENWIRE;useEpoll=true;amqpCredits=1000;amqpLowCredits=300</acceptor>

        <!-- AMQP Acceptor. Listens on default AMQP port for AMQP traffic -->
        <acceptor name="amqp">tcp://0.0.0.0:5672?tcpSendBufferSize=1048576;tcpReceiveBufferSize=1048576;protocols=AMQP;useEpoll=true;amqpCredits=1000;amqpLowCredits=300</acceptor>

        <!-- STOMP Acceptor -->
        <acceptor name="stomp">tcp://0.0.0.0:61613?tcpSendBufferSize=1048576;tcpReceiveBufferSize=1048576;protocols=STOMP;useEpoll=true</acceptor>

        <!-- HornetQ Compatibility Acceptor. Enables HornetQ Core and STOMP for legacy HornetQ clients. -->
        <acceptor name="hornetq">tcp://0.0.0.0:5445?anycastPrefix=jms.queue.;multicastPrefix=jms.topic.;protocols=HORNETQ,STOMP;useEpoll=true</acceptor>

        <!-- MQTT Acceptor -->
        <acceptor name="mqtt">tcp://0.0.0.0:1883?tcpSendBufferSize=1048576;tcpReceiveBufferSize=1048576;protocols=MQTT;useEpoll=true</acceptor>
      </acceptors>
      ...
  </core>
</configuration>

2.2. 配置接收器

以下示例演示了如何配置接收器。

流程

  1. 打开 <broker_instance_dir>/etc/broker.xml 配置文件。
  2. acceptors 元素中,添加新的 接收器 元素。指定代理上的协议和端口。例如:

    <acceptors>
       <acceptor name="example-acceptor">tcp://localhost:61617</acceptor>
    </acceptors>

    前面的示例定义了 TCP 协议的接收器。代理在端口 61617 上侦听使用 TCP 的客户端连接。

  3. 将键值对附加到为接收器定义的 URI。使用分号(;)来分隔多个键值对。例如:

    <acceptor name="example-acceptor">tcp://localhost:61617?sslEnabled=true;key-store-path=</path/to/key_store></acceptor>

    配置现在定义使用 TLS/SSL 的接收器,并定义所需密钥存储的路径。

其它资源

2.3. 关于连接器

虽然接收器定义了代理如何 接受 连接,但客户端则使用连接器来定义如何 连接到 代理。

当代理本身充当客户端时,在代理上配置连接器。例如:

  • 代理桥接到另一个代理时
  • 代理参与集群中的时

下方显示了一个简单的连接器配置。

<connectors>
   <connector name="example-connector">tcp://localhost:61617</connector>
</connectors>

2.4. 配置连接器

以下示例演示了如何配置连接器。

流程

  1. 打开 <broker_instance_dir>/etc/broker.xml 配置文件。
  2. 连接器 元素中,添加新的 连接器 元素。指定代理上的协议和端口。例如:

    <connectors>
       <connector name="example-connector">tcp://localhost:61617</connector>
    </connectors>

    前面的示例为 TCP 协议定义了一个连接器。客户端可以使用连接器配置,通过 TCP 协议连接端口 61617 上的代理。代理本身也可以将此连接器用于传出连接。

  3. 将键值对附加到为连接器定义的 URI。使用分号(;)来分隔多个键值对。例如:

    <connector name="example-connector">tcp://localhost:61616?tcpNoDelay=true</connector>

    配置现在定义一个连接器,它将 tcpNoDelay 属性的值设置为 true。将此属性的值设为 true 可关闭 Nagle 的连接算法。Nagle 的算法是一种用于通过延迟传输小数据包并将其整合到大型数据包来提高 TCP 连接效率的算法。

其它资源

2.5. 配置 TCP 连接

AMQ 代理使用 Netty 提供基本、未加密、基于 TCP 的连接,这些连接可以配置为使用阻止 Java IO 或更新的非阻塞 Java NIO。Java NIO 是更好的可扩展性,具有多个并发连接。但是,当您不必担心支持数千个并发连接时,使用旧的 IO 有时会比 NIO 提供更好的延迟。

如果您在不受信任的网络连接中运行连接,您应该知道 TCP 网络连接是未加密的。如果安全性是优先级,您可能希望考虑使用 SSL 或 HTTPS 配置来加密通过此连接发送的消息。详情请查看 第 5.1 节 “保护连接”

使用 TCP 连接时,所有连接都由客户端发起。代理不会启动与客户端的任何连接。这非常适用于强制从一个方向启动连接的防火墙策略。

对于 TCP 连接,主机和连接器 URI 的端口定义用于连接的地址。

以下示例演示了如何配置 TCP 连接。

先决条件

流程

  1. 打开 <broker_instance_dir>/etc/broker.xml 配置文件。
  2. 添加新的接收器或修改现有接收器。在连接 URI 中,指定 tcp 作为 协议。在代理中包含 IP 地址或主机名以及端口。例如:

    <acceptors>
      <acceptor name="tcp-acceptor">tcp://10.10.10.1:61617</acceptor>
      ...
    </acceptors>

    根据前面的示例,代理接受来自通过 IP 地址 10.10.10.1 连接端口 61617 的客户端的 TCP 通信。

  3. (可选)您可以采用类似的方式配置连接器。例如:

    <connectors>
      <connector name="tcp-connector">tcp://10.10.10.2:61617</connector>
      ...
    </connectors>

    在与指定的 IP 和端口 10.10.10.2:61617 进行 TCP 连接时,客户端甚至代理本身也会引用连接器。

其它资源

2.6. 配置 HTTP 连接

HTTP 连接通过 HTTP 协议隧道传输数据包,在防火墙仅允许 HTTP 流量的情况下很有用。AMQ Broker 自动检测是否使用了 HTTP,因此为 HTTP 配置网络连接与为 TCP 配置连接相同。

先决条件

流程

  1. 打开 <broker_instance_dir>/etc/broker.xml 配置文件。
  2. 添加新的接收器或修改现有接收器。在连接 URI 中,指定 tcp 作为 协议。在代理中包含 IP 地址或主机名以及端口。例如:

    <acceptors>
      <acceptor name="http-acceptor">tcp://10.10.10.1:80</acceptor>
      ...
    </acceptors>

    根据前面的示例,代理接受来自通过 IP 地址 10.10.10.1 连接端口 80 的客户端的 HTTP 通信。代理自动检测 HTTP 协议正在使用中,并与客户端进行相应通信。

  3. (可选)您可以采用类似的方式配置连接器。例如:

    <connectors>
      <connector name="http-connector">tcp://10.10.10.2:80</connector>
      ...
    </connectors>

    使用上例中所示的连接器,代理在端口 80 上通过 IP 地址 10.10.10.2 创建出站 HTTP 连接。

其它资源

  • HTTP 连接使用与 TCP 相同的配置参数,但也有一些自己的配置参数。有关 HTTP 连接所有可用配置选项的详情,请参考 附录 A, 接收器和连接器配置参数
  • 有关如何使用 HTTP 的完整工作示例,请查看位于代理安装的 <install_dir>/examples/features/standard/ 目录中的 http-transport 示例。

2.7. 配置安全网络连接

您可以使用 TLS/SSL 保护网络连接。如需更多信息,请参阅 第 5.1 节 “保护连接”

2.8. 配置虚拟机内连接

当多个代理共存于同一虚拟机(例如,作为高可用性(HA)配置的一部分)时,您可以使用虚拟机内连接。虚拟机内连接也供在与代理相同的 JVM 中运行的本地客户端使用。

先决条件

流程

  1. 打开 <broker_instance_dir>/etc/broker.xml 配置文件。
  2. 添加新的接收器或修改现有接收器。在连接 URI 中,将 vm 指定为协议。例如:

    <acceptors>
      <acceptor name="in-vm-acceptor">vm://0</acceptor>
      ...
    </acceptors>

    根据上例中的接收器,代理接受来自 ID 为 0 的代理的连接。其他代理必须在同一虚拟机上运行。

  3. (可选)您可以采用类似的方式配置连接器。例如:

    <connectors>
      <connector name="in-vm-connector">vm://0</connector>
      ...
    </connectors>

    上例中的连接器定义了客户端如何建立与 ID 为 0 的代理中的虚拟机内连接,该代理在与客户端相同的虚拟机上运行。客户端可以是应用程序或其他代理。

第 3 章 在网络连接中配置消息传递协议

AMQ Broker 具有可插拔协议架构,以便您可以轻松地为网络连接启用一个或多个协议。

代理支持以下协议:

注意

除上述协议外,代理还支持自己的原生协议,称为"Core"。此协议的过去版本称为"HornetQ",供红帽 JBoss 企业应用平台使用。

3.1. 配置网络连接以使用消息传递协议

您必须将协议与网络连接关联,然后才能使用它。(请参阅 在网络 连接中配置接收器和连接器,以了解有关如何创建和配置网络连接的更多信息。) 文件 <broker_instance_dir>/etc/broker.xml 中的默认配置包括多个已定义的连接。为方便起见,AMQ Broker 包括每个支持的协议的接收器,以及支持所有协议的默认接收器。

默认接收器概述

下面显示了在 broker.xml 配置文件中默认包括的接收器。

<configuration>
  <core>
    ...
    <acceptors>

      <!-- All-protocols acceptor -->
      <acceptor name="artemis">tcp://0.0.0.0:61616?tcpSendBufferSize=1048576;tcpReceiveBufferSize=1048576;protocols=CORE,AMQP,STOMP,HORNETQ,MQTT,OPENWIRE;useEpoll=true;amqpCredits=1000;amqpLowCredits=300</acceptor>

      <!-- AMQP Acceptor. Listens on default AMQP port for AMQP traffic -->
      <acceptor name="amqp">tcp://0.0.0.0:5672?tcpSendBufferSize=1048576;tcpReceiveBufferSize=1048576;protocols=AMQP;useEpoll=true;amqpCredits=1000;amqpLowCredits=300</acceptor>

      <!-- STOMP Acceptor -->
      <acceptor name="stomp">tcp://0.0.0.0:61613?tcpSendBufferSize=1048576;tcpReceiveBufferSize=1048576;protocols=STOMP;useEpoll=true</acceptor>

      <!-- HornetQ Compatibility Acceptor. Enables HornetQ Core and STOMP for legacy HornetQ clients. -->
      <acceptor name="hornetq">tcp://0.0.0.0:5445?anycastPrefix=jms.queue.;multicastPrefix=jms.topic.;protocols=HORNETQ,STOMP;useEpoll=true</acceptor>

      <!-- MQTT Acceptor -->
      <acceptor name="mqtt">tcp://0.0.0.0:1883?tcpSendBufferSize=1048576;tcpReceiveBufferSize=1048576;protocols=MQTT;useEpoll=true</acceptor>

    </acceptors>
    ...
  </core>
</configuration>

在给定网络冲突中启用 协议 的唯一要求是将 protocol 参数添加到接收器的 URI 中。参数的值必须是以逗号分隔的协议名称列表。如果 URI 中省略了 protocol 参数,则启用所有协议。

例如,要使用 AMQP 协议在端口 3232 上接收消息创建接收器,请按照以下步骤执行:

  1. 打开 <broker_instance_dir>/etc/broker.xml 配置文件。
  2. <acceptors> 部分 中添加以下行:
<acceptor name="ampq">tcp://0.0.0.0:3232?protocols=AMQP</acceptor>

默认接收器中的其他参数

在最小接收器配置中,您要将协议指定为连接 URI 的一部分。但是,broker.xml 配置文件中的 默认接收器配置了一些额外的参数。下表详细介绍了为默认接收器配置的额外参数。

接收器(s)参数Description

all-protocols acceptor

AMQP

STOMP

tcpSendBufferSize

以字节为单位的 TCP 发送缓冲区大小.默认值为 32768

tcpReceiveBufferSize

TCP 接收缓冲区的大小(以字节为单位)默认值为 32768

TCP 缓冲区大小应该根据网络的带宽和延迟来调优。

在摘要中,TCP 发送/接收缓冲区大小计算为:

buffer_size = bandwidth * RTT.

其中带宽以每秒字节为单位,而网络往返时间(RTT)则以秒为单位。RTT 可使用 ping 实用程序轻松测量。

对于快速网络,您可能希望增加默认的缓冲区大小。

all-protocols acceptor

AMQP

STOMP

HornetQ

MQTT

useEpoll

如果使用支持 System(Linux)的系统(Linux),请使用 Netty epoll。Netty 原生传输比 NIO 传输提供更好的性能。这个选项的默认值为 true。如果将 选项设置为 false,则使用 NIO。

all-protocols acceptor

AMQP

amqpCredits

AMQP 制作者可以发送的最大消息数,无论消息总大小如何。默认值为 1000

要了解更多有关如何使用贡献来阻止 AMQP 消息的信息,请参阅 第 7.3.2 节 “阻塞 AMQP 制作者”

all-protocols acceptor

AMQP

amqpLowCredits

代理制造生产者信用的门槛较低。默认值为 300。当生产者达到这个阈值时,代理会向生产者发送足够的学分来恢复 amqpCredits 值。

要了解更多有关如何使用贡献来阻止 AMQP 消息的信息,请参阅 第 7.3.2 节 “阻塞 AMQP 制作者”

HornetQ 兼容性接收器

anycastPrefix

客户端在连接到使用 anycast 和多播的地址时用来指定 路由类型的前缀。默认值为 jms.queue

有关配置前缀以使客户端在连接到地址时指定路由类型的更多信息,请参阅 第 4.6 节 “将路由类型添加到接收器配置”

multicastPrefix

客户端在连接到使用 anycast 和多 的地址时用来指定 播路由类型的前缀。默认值为 jms.topic

有关配置前缀以使客户端在连接到地址时指定路由类型的更多信息,请参阅 第 4.6 节 “将路由类型添加到接收器配置”

其它资源

3.2. 将 AMQP 与网络连接一起使用

代理支持 AMQP 1.0 规范。AMQP 链接是用于源和目标(即客户端和代理)之间消息的单向协议。

流程

  1. 打开 <broker_instance_dir>/etc/broker.xml 配置文件。
  2. 通过包含值 AMQP 作为 URI 一部分的 protocol 参数来添加或配置接收器 接收 AMQP 客户端,如下例所示:
<acceptors>
  <acceptor name="amqp-acceptor">tcp://localhost:5672?protocols=AMQP</acceptor>
  ...
</acceptors>

在前面的示例中,代理接受端口 5672 上的 AMQP 1.0 客户端,这是默认的 AMQP 端口。

AMQP 链接有两个端点,即发送方和接收器。当发送者传输消息时,代理会将其转换为内部格式,以便可以转发到代理上的目的地。接收器连接到代理的目的地,并在消息发送前将消息重新转换为 AMQP。

如果 AMQP 链接是动态的,则会创建一个临时队列,并将远程源或远程目标地址设置为临时队列的名称。如果链接不是动态的,则将远程目标或源的地址用于队列。如果远程目标或源不存在,则会发送异常。

链接目标也可以是协调者,用于将底层会话作为事务处理,或者回滚或提交。

注意

AMQP 允许在每个会话使用多个事务,amqp:multi-txns-per-sn,但当前版本的 AMQ Broker 仅支持每个会话的单个事务。

注意

AMQP 中的分布式事务(XA)详情在规格的 1.0 版本中不提供。如果您的环境需要支持分布式事务,建议您使用 AMQ 核心协议 JMS。

有关协议及其功能的更多信息,请参阅 AMQP 1.0 规范。

3.2.2. 配置 AMQP 安全性

代理支持 AMQP SASL 身份验证。有关如何在代理上配置基于 SASL 的身份验证 的更多信息,请参阅安全性。

3.3. 在网络连接中使用 MQTT

代理支持 MQTT v3.1.1(以及较旧的 v3.1 代码消息格式)。MQTT 是服务器的轻量级客户端,发布/订阅消息传递协议。MQTT 减少了消息传递开销和网络流量,以及客户端的代码占用。因此,MQTT 非常适合传感器和传感器等受限设备,并且正在迅速成为物联网(IoT)实际上的标准通信协议。

流程

  1. 打开 <broker_instance_dir>/etc/broker.xml 配置文件。
  2. 添加启用了 MQTT 协议的接收器。例如:
<acceptors>
  <acceptor name="mqtt">tcp://localhost:1883?protocols=MQTT</acceptor>
  ...
</acceptors>

MQTT 随附一些有用的功能,包括:

服务质量
每条消息都可以定义与之关联的服务质量。代理将尝试以最高服务质量级别向订阅者发送消息。
保留的消息
可以针对特定地址保留消息。该地址的新订阅者会在任何其他消息之前接收最后保留的消息,即使保留的消息是在客户端连接之前发送的。
通配符订阅
MQTT 地址具有层次结构,类似于文件系统的层次结构。客户端能够订阅特定主题或层次结构的整个分支。
将消息
客户端可以将"will message"设置为其连接数据包的一部分。如果客户端正常断开连接,代理会将 will 消息发布到指定的地址。其他订阅者将收到该邮件,并可以相应做出反应。

有关 MQTT 协议的最佳信息来源是在规范中。MQTT v3.1.1 规范可以从 OASIS 网站 下载。

3.4. 将 OpenWire 与网络连接搭配使用

代理支持 OpenWire 协议,允许 JMS 客户端直接与代理通信。使用这个协议与旧版本的 AMQ Broker 进行通信。

目前 AMQ Broker 支持仅使用标准 JMS API 的 OpenWire 客户端。

流程

  1. 打开 <broker_instance_dir>/etc/broker.xml 配置文件。
  2. 添加或修改 接收器,使其包含 作为 protocol 参数一部分的 OPENWIRE,如下例所示:

    <acceptors>
      <acceptor name="openwire-acceptor">tcp://localhost:61616?protocols=OPENWIRE</acceptor>
      ...
    </acceptors>

在前面的示例中,代理将侦听端口 61616 传入的 OpenWire 命令。

如需了解更多详细信息,请参阅 <install_dir>/examples/protocols/openwire 下的示例。

3.5. 在网络连接中使用 STOMP

STOMP 是一种文本导向的线路协议,允许 STOMP 客户端与 STOMP 代理通信。代理支持 STOMP 1.0、1.1 和 1.2。STOMP 客户端可用于多种语言和平台,成为互操作性选择的好选择。

流程

  1. 打开 <broker_instance_dir>/etc/broker.xml 配置文件。
  2. 配置现有的 接收器或 创建新接收器,并包含值为 STOMP 的 protocol 参数,如下所示:
<acceptors>
  <acceptor name="stomp-acceptor">tcp://localhost:61613?protocols=STOMP</acceptor>
  ...
</acceptors>

在前面的示例中,代理接受端口 61613 上的 STOMP 连接,这是默认值。

有关如何使用 STOMP 配置代理 的示例,请参阅 <install_dir> /examples/protocols 中的 stomp 示例。

3.5.1. STOMP 限制

使用 STOMP 时,会有以下限制:

  1. 代理目前不支持虚拟主机,这意味着 CONNECT中的主机 标头被忽略。
  2. 消息确认不事务。ACK 帧不能是事务的一部分,如果设置了 事务 标头,它将被忽略。

3.5.2. 为 STOMP 消息提供 ID

在通过 JMS 使用者或 QueueBrowser 接收 STOMP 消息时,消息不包含任何 JMS 属性,如 JMSMessageID。但是,您可以使用代理参数设置每个传入 STOMP 消息的消息 ID。

流程

  1. 打开 <broker_instance_dir>/etc/broker.xml 配置文件。
  2. 将用于 STOMP 连接的接收器的 stomp EnableMessageId 参数设置为 true,如下例所示:
<acceptors>
  <acceptor name="stomp-acceptor">tcp://localhost:61613?protocols=STOMP;stompEnableMessageId=true</acceptor>
  ...
</acceptors>

通过使用 stomp EnableMessageId 参数,使用此接收器发送的每一 stomp 消息都会添加额外的属性。属性键是 amq-message-id,其值是前缀为 STOMP 的内部消息 ID 的 String 表示,如下例所示:

amq-message-id : STOMP12345

如果没有在配置中指定 stomp EnableMessageId,则默认值为 false

3.5.3. 将连接时间设置为 live

STOMP 客户端必须在关闭连接前发送 DISCONNECT 框架。这允许代理关闭任何服务器端资源,如会话和使用者。但是,如果 STOMP 客户端退出而不发送 DISCONNECT 帧,或者出现故障,代理将无法立即知道客户端是否仍然处于活动状态。因此,STOMP 连接被配置为将"生存时间"(TTL)为 1 分钟。表示代理如果闲置了一分钟以上,则会停止与 STOMP 客户端的连接。

流程

  1. 打开 <broker_instance_dir>/etc/broker.xml 配置文件。
  2. connectionTTL 参数添加到 用于 STOMP 连接的接收器 URI 中,如下例所示:
<acceptors>
  <acceptor name="stomp-acceptor">tcp://localhost:61613?protocols=STOMP;connectionTTL=20000</acceptor>
  ...
</acceptors>

在前面的示例中,使用 stomp -acceptor 的任何 stomp 连接将其 TTL 设置为 20 秒。

注意

STOMP 协议版本 1.0 不包含任何心跳帧。因此,用户负责确保数据在连接ttl 中发送,或者代理将假设客户已死机并清理服务器端资源。对于版本 1.1,您可以使用心跳来维护 stomp 连接的生命周期。

将代理默认时间覆盖为 live

如前文所述,STOMP 连接的默认 TTL 为一分钟。您可以通过在代理配置中添加 connection-ttl-override 属性来覆盖这个值。

流程

  1. 打开 <broker_instance_dir>/etc/broker.xml 配置文件。
  2. 添加 connection-ttl-override 属性,并为新默认值提供毫秒的值。它属于 <core> 小节,如下所示。
<configuration ...>
  ...
  <core ...>
    ...
    <connection-ttl-override>30000</connection-ttl-override>
    ...
  </core>
<configuration>

在上例中,STOMP 连接的默认 Time to Live(TTL)设置为 30 秒, 30000 毫秒。

3.5.4. 从 JMS 发送和使用 STOMP 消息

STOMP 主要是一个文本导向型协议。为了更加轻松地与 JMS 进行互操作,STOMP 实施将检查是否存在 内容长度 标头,以确定如何将 STOMP 消息映射到 JMS。

如果您希望 STOMP 信息映射到 …​message should…​.

JMS TextMessage

不包含 内容长度 标头。

JMS BytesMessage

包含 content-length 标头。

将 JMS 消息映射到 STOMP 时也适用相同的逻辑。STOMP 客户端可以确认存在 内容长度 标头,以确定邮件正文(字符串或字节)的类型。

如需有关消息标头的更多信息,请参阅 STOMP 规范。

3.5.5. 将 STOMP 目的地映射到 AMQ 代理地址和队列

在发送消息和订阅时,STOMP 客户端通常包含 目的地 标头。目的地名称是字符串值,映射到代理上的目的地。在 AMQ Broker 中,这些目的地映射到 地址队列。有关目的地帧的更多信息,请参阅 STOMP 规格。

以发送以下消息的 STOMP 客户端为例(包含标题和正文):

SEND
destination:/my/stomp/queue

hello queue a
^@

在这种情况下,代理会将消息转发到与地址 /my/stomp/queue 关联的任何队列。

例如,当 STOMP 客户端发送消息(通过使用 SEND 帧)时,指定的目的地映射到地址。

当客户端发送 SUBS CRIBE 或 UNSUBSCRIBE 帧时,它的工作方式相同,但在本例中,AMQ Broker 将 目的地 映射到队列。

SUBSCRIBE
destination: /other/stomp/queue
ack: client

^@

在前面的示例中,代理会将 目的地 映射到队列 /other/stomp/queue

将 STOMP 目的地映射到 JMS 目的地

JMS 目的地也映射到代理地址和队列。如果要使用 STOMP 向 JMS 目的地发送信息,STOMP 目的地必须遵循相同的约定:

  • 通过在队列名称 by jms.queue 前发送或订阅 JMS Queue。例如,要向 JMS Queue 的顺序发送消息,STOMP 客户端必须发送帧:

    SEND
    destination:jms.queue.orders
    hello queue orders
    ^@
  • 通过在主题名称 by jms.topic 前发送或订阅 JMS 主题。例如,要订阅 JMS Topic,STOMP 客户端必须发送类似如下的帧:

    SUBSCRIBE
    destination:jms.topic.stocks
    ^@

第 4 章 配置地址和队列

4.1. 地址、队列和路由类型

在 AMQ Broker 中,寻址模型包含三个主要概念: 地址队列路由类型

地址 代表消息传递端点。在配置中,为典型的地址指定唯一的名称、一个或多个队列以及路由类型。

队列 与地址关联.每个地址可以有多个队列。传入消息与地址匹配后,该消息将发送到一个或多个队列,具体取决于配置的路由类型。队列可以被配置为自动创建和删除队列。您还可以将地址(及其关联的队列)配置为 持久。持久队列中的消息可以在崩溃或代理重启后存活,只要队列中的消息也是持久的。相比之下,不可耐用队列中的消息不会在崩溃或代理重启后存活,即使消息本身是持久的。

路由类型 决定了如何将消息发送到与地址关联的队列。在 AMQ Broker 中,您可以使用两种不同的路由类型配置地址,如表中所示。

如果您希望您的消息路由到…​使用这个路由类型…​

匹配地址中的单个队列,以点对点的方式

anycast

匹配地址中的每个队列,采用发布订阅的方式

multicast

注意

个地址必须至少有一个定义的路由类型。

每个地址 可以 定义多个路由类型,但不建议这样做。

如果地址 同时 定义了路由类型,并且客户端没有显示首选,代理会默认使用 多播 路由类型。

其它资源

4.1.1. 地址和队列命名要求

配置地址和队列时请注意以下要求:

  • 为确保客户端可以连接到队列,无论客户端使用哪个线路协议,您的地址和队列名称 不应 包括以下字符:

    & :: , ? >

  • 数字符号(#)和星号(*)字符为通配符表达式保留,不应在地址和队列名称中使用。如需更多信息,请参阅 第 4.2.1 节 “AMQ Broker 通配符语法”
  • 地址和队列名称不应包含空格。
  • 要分隔地址或队列名称中的词语,请使用配置的分隔符字符。默认分隔符字符为句点(.)。如需更多信息,请参阅 第 4.2.1 节 “AMQ Broker 通配符语法”

4.2. 将地址设置应用到一组地址

在 AMQ Broker 中,您可以使用通配符表达式来表示匹配的地址名称,将 address-setting 元素中指定的配置应用到 一组 地址。

以下小节描述了如何使用通配符表达式。

4.2.1. AMQ Broker 通配符语法

AMQ Broker 使用特定的语法在地址设置中表示通配符。通配符也可以用于安全设置,也可以在创建使用者时使用。

  • 通配符表达式包含以句点(.)分隔的词语。
  • 数字符号(#)和星号(*)字符也有特殊含义,可以代替词语,如下所示:

    • 数字符号字符表示"匹配零个或多个单词的任意序列"。在表达式的末尾使用此选项。
    • 星号字符表示"匹配单个词语"。在表达式中的任意位置使用它。

匹配不按字符执行,而是在每个分隔符边界上执行。例如,配置为在其名称中与 my 的队列匹配的 address-setting 元素与名为 myqueue 的队列 不匹配

当多个 address-setting 元素匹配某个地址时,代理将配置最不特定的匹配项作为基准。字面表达式比通配符更为具体的,而星号(*)比数字符号(#)更具体。例如,my .destinationmy.* 都与地址 my.destination 匹配。在这种情况下,代理首先应用 my.* 下找到的配置,因为通配符表达式不如字面上的特定。接下来,代理会覆盖 my.destination address 设置元素的配置,它会覆盖所有通过 my.* 共享的配置。例如,根据以下配置,与 my.destination 关联的队列 将 max-delivery-attempts 设置为 3,并且 last-value-queue 设置为 false

<address-setting match="my.*">
    <max-delivery-attempts>3</max-delivery-attempts>
    <last-value-queue>true</last-value-queue>
</address-setting>
<address-setting match="my.destination">
    <last-value-queue>false</last-value-queue>
</address-setting>

下表中的示例说明了如何使用通配符匹配一组地址。

示例Description

#

broker.xml 中使用的默认 address-setting。匹配每个地址.您可以继续应用这一概括性,也可以根据需要为每个地址或地址组添加新 address-setting

news.europe.#

匹配 news.europenews.europe.sportnews.europe.politics.fr,但不会出现 news.usaeurope

news.*

匹配 news.europenews.usa,但不匹配 news.europe.sport

news.*.sport

匹配 news.europe.sportnews.usa.sport,但不匹配 news.europe.fr.sport

4.2.2. 配置代理通配符语法

以下步骤演示了如何自定义用于通配符地址的语法。

流程

  1. 打开 <broker_instance_dir>/etc/broker.xml 配置文件。
  2. 在配置中添加 <wildcard-addresses> 部分,如下例所示。

    <configuration>
      <core>
        ...
        <wildcard-addresses> //
          <enabled>true</enabled> //
          <delimiter>,</delimiter> //
          <any-words>@</any-words> //
          <single-word>$</single-word>
        </wildcard-addresses>
        ...
      </core>
    </configuration>
    enabled
    当设置为 true 时,指示代理使用您的自定义设置。
    delimiter
    提供要用作 分隔符 的自定义字符,而非默认的 字符,即:
    any-words
    作为 any-words 的值提供的字符表示 'match of zero or more word',并将替换默认值 #。在表达式末尾使用此字符。
    single-word
    作为 单词语 值提供的字符用于表示"匹配单个单词"并替换默认值 *。在表达式中的任意位置使用此字符。

4.3. 为点对点消息传递配置地址

点对点消息传递是一种常见场景,即生产者发送的消息只有一个消费者。例如,AMQP 和 JMS 消息制作者和使用者可以利用点对点消息传递队列。为确保与地址关联的队列以点对点的方式接收消息,您可以在代理配置中为给定 地址 元素定义 anycast 路由类型。

使用 anycast 在地址上收到消息时,代理会查找与该地址关联的队列,并将消息路由到其中。然后,消费者可能会请求使用来自该队列的消息。如果多个消费者连接到同一队列,消息将在消费者之间均匀分布,只要消费者能够同样地处理它们。

下图显示了点对点消息传递的示例。

指向消息传递

4.3.1. 配置基本点对点消息传递

以下步骤演示了如何为点对点消息传递配置单一队列的地址。

流程

  1. 打开 <broker_instance_dir>/etc/broker.xml 配置文件。
  2. anycast 配置元素包装在所选的 队列 元素周围 确保 地址队列 元素的 name 属性的值相同。例如:

    <configuration ...>
      <core ...>
        ...
        <address name="my.anycast.destination">
          <anycast>
            <queue name="my.anycast.destination"/>
          </anycast>
        </address>
      </core>
    </configuration>

4.3.2. 为多个队列配置点对点消息传递

您可以在使用 任播 路由类型的地址上定义多个队列。代理在所有关联的队列中平均分发发送到 任播 地址的消息。通过指定 完全限定队列名称 (FQQN),您可以将客户端连接到特定队列。如果多个消费者连接到同一队列,代理会在消费者之间均匀分发消息。

下图显示了使用两个队列的点对点消息传递示例:

指向使用多个队列的消息传递

以下步骤演示了如何为具有多个队列的地址配置点对点消息传递。

流程

  1. 打开 <broker_instance_dir>/etc/broker.xml 配置文件。
  2. anycast 配置元素周围的 address 元素包装到 address 元素中。例如:

    <configuration ...>
      <core ...>
        ...
        <address name="my.anycast.destination">
          <anycast>
            <queue name="q1"/>
            <queue name="q2"/>
          </anycast>
        </address>
      </core>
    </configuration>

如果您的配置(如 所示)在集群中的多个代理之间镜像,集群可以以对生产者和消费者不透明的方式对点对点消息传递进行负载平衡。确切的行为取决于如何为集群配置消息负载平衡策略。

其它资源

4.4. 配置用于发布与订阅消息传递的地址

在发布订阅场景中,消息发送到订阅某个地址的每个消费者。JMS 主题和 MQTT 订阅是发布与订阅消息传递的两个示例。为确保与地址关联的队列以发布与订阅的方式接收消息,您可以在代理配置中为给定 地址 元素定义 多播 路由类型。

当在具有 多播 路由类型的地址上收到消息时,代理会将消息副本路由到与该地址关联的每个队列。为减少复制开销,每个队列仅发送对消息的 引用,而不是完整副本。

下图显示了发布-订阅消息传递的示例:

发布订阅消息传递

以下步骤演示了如何配置用于发布与订阅消息传递的地址。

流程

  1. 打开 <broker_instance_dir>/etc/broker.xml 配置文件。
  2. 向地址添加空 多播 配置元素。

    <configuration ...>
      <core ...>
        ...
        <address name="my.multicast.destination">
          <multicast/>
        </address>
      </core>
    </configuration>
  3. (可选)向地址添加一个或多个 队列 元素,并在它们周围嵌套 多播 元素。这一步通常不需要,因为代理会自动为每个客户端请求的订阅创建一个队列。

    <configuration ...>
      <core ...>
        ...
        <address name="my.multicast.destination">
          <multicast>
            <queue name="client123.my.multicast.destination"/>
            <queue name="client456.my.multicast.destination"/>
          </multicast>
        </address>
      </core>
    </configuration>

4.5. 为点对点和发布订阅消息传递配置地址

您还可以使用点对 和发布订阅语义配置地址。

通常不 建议配置使用点对点和发布订阅语义的地址。但是,当您想要名为 Order 的 JMS 队列 JMS 主题也称为 Order 时,它 很有用 不同的路由类型使地址似乎与客户端连接不同。在这种情形中,JMS 队列制作者发送的消息使用 anycast 路由类型。JMS 主题制作者发送的消息使用 多播 路由类型。当 JMS 主题消费者连接到代理时,它将附加到其自身的订阅队列。但是,JMS 队列使用者附加到 anycast 队列。

下图显示了一起使用的点对点和发布订阅消息传递的示例。

指向点并发布订阅消息传递

以下步骤演示了如何为点对点和发布订阅消息传递配置地址。

注意

这种情况下的行为取决于所使用的协议。对 JMS 而言,主题和队列制作者和使用者之间存在明显区别,这使得逻辑非常简单。AMQP 等其他协议不做出这种区分。通过 AMQP 发送的消息由 任何广播和 多播 以及消费者默认路由到 anycast。如需更多信息,请参阅 第 3 章 在网络连接中配置消息传递协议

流程

  1. 打开 <broker_instance_dir>/etc/broker.xml 配置文件。
  2. anycast 配置元素周围的 address 元素包装到 address 元素中。例如:

    <configuration ...>
      <core ...>
        ...
        <address name="orders">
          <anycast>
            <queue name="orders"/>
          </anycast>
        </address>
      </core>
    </configuration>
  3. 向地址添加空 多播 配置元素。

    <configuration ...>
      <core ...>
        ...
        <address name="orders">
          <anycast>
            <queue name="orders"/>
          </anycast>
          <multicast/>
        </address>
      </core>
    </configuration>
    注意

    通常,代理会根据需要创建订阅队列,因此不需要列出 多播 元素中的特定队列元素。

4.6. 将路由类型添加到接收器配置

通常,如果消息由同时使用 anycast 和多 的地址接收,则一个 任播队列将 接收消息和所有 多播 队列。但是,客户端可以在连接到地址时指定一个特殊的前缀,以指定是使用 任播 还是 多播 进行连接。前缀是使用代理配置中接收器 URL 中的 anycast Prefix 和多播Prefix 参数指定的自定义值。

以下流程演示了如何为给定接收器配置前缀。

流程

  1. 打开 <broker_instance_dir>/etc/broker.xml 配置文件。
  2. 对于给定接收器,若要配置 任播 前缀,请将 anycastPrefix 添加到配置的 URL。设置自定义值。例如:

    <configuration ...>
      <core ...>
        ...
          <acceptors>
             <!-- Acceptor for every supported protocol -->
             <acceptor name="artemis">tcp://0.0.0.0:61616?protocols=AMQP;anycastPrefix=anycast://</acceptor>
          </acceptors>
        ...
      </core>
    </configuration>

    根据上述配置,接收器配置为使用 anycast:// 作为 anycast:// 前缀。如果客户端只需要将消息发送到 anycast 队列之一,客户端代码可以指定 any cast://<my.destination>/

  3. 对于给定接收器,若要配置 多播 前缀,请将 多播Prefix 添加到配置的 URL。设置自定义值。例如:

    <configuration ...>
      <core ...>
        ...
          <acceptors>
             <!-- Acceptor for every supported protocol -->
             <acceptor name="artemis">tcp://0.0.0.0:61616?protocols=AMQP;multicastPrefix=multicast://</acceptor>
          </acceptors>
        ...
      </core>
    </configuration>

    根据上述配置,接收器配置为使用 多播:// 作为多 前缀。如果客户端只需要发送到 多播 队列 的消息,客户端代码可以指定多播://<my.destination>/

4.7. 配置订阅队列

在大多数情况下,不需要手动创建订阅队列,因为当客户端第一次请求订阅某个地址时协议管理器会自动创建订阅队列。如需更多信息,请参阅 第 4.8.3 节 “协议管理器和地址”。对于持久订阅,生成的队列名称通常是客户端 ID 和地址的串联。

以下小节演示了在需要时如何手动创建订阅队列。

4.7.1. 配置持久订阅队列

当队列配置为持久订阅时,代理会保存任何不活跃的订阅的信息,并在用户重新连接时将其传送给订阅者。因此,确保客户端在订阅后接收发送到队列的每个消息。

流程

  1. 打开 <broker_instance_dir>/etc/broker.xml 配置文件。
  2. 持久 配置元素添加到所选队列。将值设为 true

    <configuration ...>
      <core ...>
        ...
        <address name="my.durable.address">
          <multicast>
            <queue name="q1">
              <durable>true</durable>
            </queue>
          </multicast>
        </address>
      </core>
    </configuration>
    注意

    由于队列默认为持久,因此在创建 持久 队列时,包括持久元素并将值设置为 true 并非严格要求。但是,明确包含该元素可让您稍后将队列的行为(如有必要)更改为不可持久性。

4.7.2. 配置非共享持久订阅队列

可以配置代理以防止多个使用者在任意时间连接到队列。因此,以这种方式配置队列的订阅被视为"非共享"。

流程

  1. 打开 <broker_instance_dir>/etc/broker.xml 配置文件。
  2. 持久 配置元素添加到每个所选队列。将值设为 true

    <configuration ...>
      <core ...>
        ...
        <address name="my.non.shared.durable.address">
          <multicast>
            <queue name="orders1">
              <durable>true</durable>
            </queue>
            <queue name="orders2">
              <durable>true</durable>
            </queue>
          </multicast>
        </address>
      </core>
    </configuration>
    注意

    由于队列默认为持久,因此在创建 持久 队列时,包括持久元素并将值设置为 true 并非严格要求。但是,明确包含该元素可让您稍后将队列的行为(如有必要)更改为不可持久性。

  3. max-consumers 属性添加到每个所选队列。将值设为 1

    <configuration ...>
      <core ...>
        ...
        <address name="my.non.shared.durable.address">
          <multicast>
            <queue name="orders1" max-consumers="1">
              <durable>true</durable>
            </queue>
            <queue name="orders2" max-consumers="1">
              <durable>true</durable>
            </queue>
          </multicast>
        </address>
      </core>
    </configuration>

4.7.3. 配置不可持久性的订阅队列

不可更改的订阅通常由相关协议管理器管理,它会创建和删除临时队列。

但是,如果您想要手动创建类似于不可持久性订阅队列的队列,您可以在队列中使用 purge-on-no-consumers 属性。当 purge-on-no-consumers 设为 true 时,队列不会开始接收消息,直到消费者连接为止。此外,当最后一个消费者与队列断开连接时,队列会被 清除 (即,其消息会被删除)。在新使用者连接到队列之前,队列不会再收到任何其他消息。

流程

  1. 打开 <broker_instance_dir>/etc/broker.xml 配置文件。
  2. purge-on-no-consumers 属性添加到每个所选队列。将值设为 true

    <configuration ...>
      <core ...>
        ...
        <address name="my.non.durable.address">
            <multicast>
                <queue name="orders1" purge-on-no-consumers="true"/>
            </multicast>
        </address>
      </core>
    </configuration>

4.8. 自动创建和删除地址和队列

您可以将代理配置为自动创建地址和队列,并在它们不再使用后将其删除。这样,您不必在客户端连接前预配置每个地址。

4.8.1. 自动创建和删除队列的配置选项

下表列出了配置 address-setting 元素以自动创建和删除队列和地址时可用的配置元素:

如果您希望 address-setting 到 …​添加此配置…​

当客户端向或尝试使用映射到且不存在的地址的队列的消息时,创建地址。

auto-create-addresses

客户端发送消息或尝试使用来自队列的消息时创建队列。

auto-create-queues

删除自动创建的地址(当其不再具有任何队列时)。

auto-delete-addresses

当队列有 0 个使用者和 0 消息时,删除自动创建的队列。

auto-delete-queues

如果客户端没有指定,请使用特定的路由类型。

default-address-routing-type

4.8.2. 配置自动创建和删除地址和队列

以下步骤演示了如何配置自动创建和删除地址和队列。

流程

  1. 打开 <broker_instance_dir>/etc/broker.xml 配置文件。
  2. 配置 address-setting 以自动创建和删除。以下示例使用了上表中提及的所有配置元素。

    <configuration ...>
     <core ...>
      ...
      <address-settings>
        <address-setting match="activemq.#">
          <auto-create-addresses>true</auto-create-addresses>
          <auto-delete-addresses>true</auto-delete-addresses>
          <auto-create-queues>true</auto-create-queues>
          <auto-delete-queues>true</auto-delete-queues>
          <default-address-routing-type>ANYCAST</default-address-routing-type>
        </address-setting>
      </address-settings>
      ...
     </core>
    </configuration>
    address-setting
    address-setting 元素的配置应用到任何与通配符地址 activemq.# 匹配的地址或队列。
    auto-create-addresses
    当客户端请求连接到尚不存在的地址时,代理会创建该地址。
    auto-delete-addresses
    当不再关联任何队列时,将自动创建的地址被删除。
    auto-create-queues
    当客户端请求连接到尚不存在的队列时,代理会创建队列。
    auto-delete-queues
    当队列不再有任何使用者或消息时,将自动创建队列被删除。
    default-address-routing-type
    如果客户端在连接时没有指定路由类型,代理在将信息传送到地址时使用 ANYCAST。默认值为 MULTICAST

其它资源

4.8.3. 协议管理器和地址

称为 协议管理器 的组件将协议特定的概念映射到 AMQ Broker 地址模型中使用的概念;队列和路由类型。在某些情况下,协议管理器可能会在代理上自动创建队列。

例如,当客户端发送带有地址 /house/room1/lights 和 /house/room2/lights MQTT 订阅包时,MQTT 协议管理器了解这两个地址需要 多播 语义。因此,协议管理器首先要确保为这两个地址启用 多播。如果没有,它会尝试动态创建它们。如果成功,协议管理器将为客户端请求的每个订阅创建特殊订阅队列。

每个协议的行为稍有不同。下表描述了当请求订阅各种 队列 类型的框架时通常会发生什么。

如果队列是这个类型…​协议管理器的典型操作是 to…​

持久订阅队列

查找合适的地址并确保启用了 多播 语义。然后,它会创建一个特殊的订阅队列,并将客户端 ID 和地址作为其名称和 多播 作为其路由类型。

特殊名称允许协议管理器快速识别客户端在以后断开连接和重新连接时所需的客户端订阅队列。

当客户端取消订阅时,队列被删除。

临时订阅队列

查找合适的地址并确保启用了 多播 语义。然后,它会在此地址下创建一个带有 多播 路由类型的随机(读取 UUID)名称的队列。

客户端断开连接后,队列被删除。

点到点队列

查找适当的地址并确保启用了 任播 路由类型。如果是,则它旨在查找名称与地址相同的队列。如果不存在,它将查找可用的第一个队列。它不存在,然后它会自动创建队列(启用自动创建)。队列使用者绑定到此队列。

如果队列自动创建,则在没有消费者且其中没有消息时会自动删除队列。

4.9. 指定完全限定队列名称

在内部,代理会将客户端对地址的请求映射到特定队列。代理代表要向其发送消息的队列或从哪个队列接收消息的客户端决定。但是,更高级的用例可能要求客户端直接指定队列名称。在这些情况下,客户端可以使用 完全限定的队列名称( FQQN)。FQQN 包含地址名称和队列名称,用 :: 分隔

以下步骤演示了如何在连接到具有多个队列的地址时指定 FQQN。

先决条件

  • 您有一个地址配置了两个或多个队列,如下例所示。

    <configuration ...>
      <core ...>
        ...
        <addresses>
           <address name="my.address">
              <anycast>
                 <queue name="q1" />
                 <queue name="q2" />
              </anycast>
           </address>
        </addresses>
      </core>
    </configuration>

流程

  • 在客户端代码中,在从代理请求连接时,同时使用地址名称和队列名称。使用两个冒号 :: 来分隔名称。例如:

    String FQQN = "my.address::q1";
    Queue q1 session.createQueue(FQQN);
    MessageConsumer consumer = session.createConsumer(q1);

4.10. 配置分片队列

跨队列处理消息的一种常见模式是使用 队列分片。这意味着您定义一个充当单一逻辑队列的 任播 地址,但受到许多底层物理队列的支持。

流程

  1. 打开 <broker_instance_dir>/etc/broker.xml 配置文件。
  2. 添加 address 元素并设置 name 属性。例如:

    <configuration ...>
      <core ...>
        ...
        <addresses>
           <address name="my.sharded.address"></address>
        </addresses>
      </core>
    </configuration>
  3. 添加 anycast 路由类型,并包含所需的分片队列数。在以下示例中,队列 q1、q 2q3 添加为 任播 目的地。

    <configuration ...>
      <core ...>
        ...
        <addresses>
           <address name="my.sharded.address">
              <anycast>
                 <queue name="q1" />
                 <queue name="q2" />
                 <queue name="q3" />
              </anycast>
           </address>
        </addresses>
    </core>
    </configuration>

根据上述配置,发送到 my.sharded.address 的消息在 q1、q2 和 q 3 之间均匀分布。当使用完全限定队列名称(FQQN)时,客户端可以直接连接到特定的物理队列。并且仅接收发送到该特定队列的消息。

要将特定消息绑定到特定队列,客户端可以为每个消息指定消息组。broker 将消息分组到同一队列,一个消费者对其进行全部处理。

其它资源

4.11. 配置最后一个值队列

最后一个值队列是队列 类型,当将具有相同值键值的更新消息放入队列中时,该队列将丢弃消息。通过此行为,最后一个值队列仅保留同一键消息的最后一个值。

最后一个值队列的简单用例是监控股票价格,其中只有特定股票的最新价值值得关注。

注意

如果没有配置的最后值键的消息发送到最后一个值队列,代理会将此消息作为"正常"消息处理。当具有配置值键的新消息到达时,不会从队列清除此类消息。

您可以单独配置最后一个值队列,或者配置与一组地址关联的所有队列。

以下步骤演示了如何通过以下方式配置最后的值队列:

4.11.1. 单独配置最后一个值队列

以下步骤演示了分别配置最后的值队列。

  1. 打开 <broker_instance_dir>/etc/broker.xml 配置文件。
  2. 对于给定队列,添加 last-value-key 键并指定自定义值。例如:

    <address name="my.address">
        <multicast>
            <queue name="prices1" last-value-key="stock_ticker"/>
        </multicast>
    </address>
  3. 或者,您可以配置最后一个值队列,该队列使用默认的最后一个值键名称 _AMQ_LVQ_NAME。为此,请将 最后值键 添加到给定队列中。将值设为 true。例如:

    <address name="my.address">
        <multicast>
            <queue name="prices1" last-value="true"/>
        </multicast>
    </address>

4.11.2. 为地址配置最后一个值队列

以下步骤演示了为地址或地址 配置最后一个值队列。

  1. 打开 <broker_instance_dir>/etc/broker.xml 配置文件。
  2. address-setting 元素中,为匹配地址添加 default-last-value-key。指定自定义值。例如:

    <address-setting match="lastValue">
       <default-last-value-key>stock_ticker</default-last-value-key>
    </address-setting>

    根据上述配置,与 lastValue 地址关联的所有队列都使用最后一个值键 stock_ticker。默认情况下,default -last-value-key 的值不会被设置。

  3. 要为 一组 地址配置最后一个值队列,您可以指定一个地址通配符。例如:

    <address-setting match="lastValue.*">
       <default-last-value-key>stock_ticker</default-last-value-key>
    </address-setting>
  4. 或者,您可以将与地址 关联的所有队列配置为使用默认的最后一个值键名称 _AMQ_LVQ_NAME。为此,可添加 default-last-value-queue,而不是 default-last-value-key。将值设为 true。例如:

    <address-setting match="lastValue">
       <default-last-value-queue>true</default-last-value-queue>
    </address-setting>

其它资源

4.11.3. 最后值队列行为示例

此示例显示了最后一个值队列的行为。

broker.xml 配置文件中,假设您添加了类似如下的配置:

<address name="my.address">
    <multicast>
        <queue name="prices1" last-value-key="stock_ticker"/>
    </multicast>
</address>

上述配置创建一个名为 price 1 的队列,其最后一个值键为 stock_ticker

现在,假设客户端发送两条消息。每一消息对属性 stock_ticker 具有相同的 ATN 值。每条消息对名为 stock_ price 的属性具有不同的值。每条消息都发送到同一队列 price 1

TextMessage message = session.createTextMessage("First message with last value property set");
message.setStringProperty("stock_ticker", "ATN");
message.setStringProperty("stock_price", "36.83");
producer.send(message);
TextMessage message = session.createTextMessage("Second message with last value property set");
message.setStringProperty("stock_ticker", "ATN");
message.setStringProperty("stock_price", "37.02");
producer.send(message);

当对 stock_ticker last value 键(本例中为 ATN)具有相同值的两个消息到达 price 1 队列 时,只有最新的消息保留在队列中,其中第一条消息将被清除。在命令行中,您可以输入以下行来验证此行为:

TextMessage messageReceived = (TextMessage)messageConsumer.receive(5000);
System.out.format("Received message: %s\n", messageReceived.getText());

在本示例中,您看到的输出是第二条消息,因为两条消息对最后一个值键都使用相同的值,而且第一个消息之后的队列中收到第二条消息。

4.11.4. 为最后一个值队列强制使用非破坏性

当消费者连接到队列时,通常的行为是发送到该消费者的消息只能被消费者获取。当消费者确认接收消息时,代理会从队列中删除消息。

作为正常消耗的替代方案,您可以将队列配置为强制实施 非破坏性 消耗。在这种情况下,当队列向消费者发送消息时,其他消费者仍然可以收到该消息。此外,即使消费者已经使用过该消息,该消息也会保留在队列中。当您实施这种非破坏性消耗行为时,消费者被称为队列 浏览器

强制使用非破坏性是最后一个值队列的实用配置,因为它可确保队列始终保存特定最后值键的最新值。

以下步骤演示了如何为最后一个值队列强制实施非破坏性消耗。

先决条件

流程

  1. 打开 <broker_instance_dir>/etc/broker.xml 配置文件。
  2. 如果您之前将队列单独配置为最后一个值队列,请添加 非破坏性 密钥。将值设为 true。例如:

    <address name="my.address">
       <multicast>
          <queue name="orders1" last-value-key="stock_ticker" non-destructive="true" />
       </multicast>
    </address>
  3. 如果您之前为最后一个值队列配置了地址或 一组 地址,请添加 默认值非破坏性 密钥。将值设为 true。例如:

    <address-setting match="lastValue">
       <default-last-value-key>stock_ticker </default-last-value-key>
       <default-non-destructive>true</default-non-destructive>
    </address-setting>
    注意

    默认情况下,default -non-destructive 的值为 false

4.12. 将过期的消息移到到期地址

对于最后一个值队列以外的队列,如果您只有一个非破坏性消费者,代理永远不会从队列中删除消息,从而导致队列大小随着时间增大。为防止这种队列大小不受约束的增长,您可以配置消息过期的时间并指定代理向其移动过期消息的地址。

4.12.1. 配置消息过期

以下流程演示了如何配置消息到期。

流程

  1. 打开 <broker_instance_dir>/etc/broker.xml 配置文件。
  2. core 元素中,设置 message-expiry-scan-period,以指定代理扫描过期消息的频率。

    <configuration ...>
       <core ...>
          ...
          <message-expiry-scan-period>1000</message-expiry-scan-period>
          ...

    根据上述配置,代理每隔 1000 毫秒扫描过期的消息队列。

  3. 在匹配地址的 address-setting 元素 ,指定到期地址。另外,设置消息过期时间。例如:

    <configuration ...>
       <core ...>
          ...
          <address-settings>
             ...
             <address-setting match="stocks">
                ...
                <expiry-address>ExpiryAddress</expiry-address>
                <expiry-delay>10</expiry-delay>
                ...
             </address-setting>
             ...
          <address-settings>
    <configuration ...>
    expiry-address
    匹配地址的到期地址。在前面的示例中,代理会向名为 ExpiryAddress 到期地址发送过期的消息。
    expiry-delay

    代理应用到 使用默认 过期时间的消息,以毫秒为单位。默认情况下,消息的过期时间为 0,即它们不会过期。对于过期时间大于默认的消息,expiration -delay 无效。

    例如,假设您将地址上的 expiration-delay 设置为 10,如上例中所示。如果默认过期时间为 0 的消息在此地址到达队列,代理会将消息的过期时间从 0 更改为 10。但是,如果另一条消息使用过期时间 20 到达,则其过期时间保持不变。如果将 expiration-delay 设置为 -1,则此功能被禁用。默认情况下,expiry-delay 设置为 -1

  4. 另外,您可以指定最小和最大 到期延迟值,而不是为 expiration-delay 指定值。例如:

    <configuration ...>
       <core ...>
          ...
          <address-settings>
             ...
             <address-setting match="stocks">
                ...
                <expiry-address>ExpiryAddress</expiry-address>
                <min-expiry-delay>10</min-expiry-delay>
                <max-expiry-delay>100</max-expiry-delay>
                ...
             </address-setting>
             ...
          <address-settings>
    <configuration ...>
    min-expiry-delay
    代理应用到消息的最短过期时间,以毫秒为单位。
    max-expiry-delay

    代理应用到消息的最大过期时间,以毫秒为单位。

    代理应用 min-expiry-delay 和 max- expiry-delay 的值,如下所示:

    • 对于默认过期时间为 0 的消息,代理会将过期时间设置为 max-expiry-delay 的指定值。如果您还没有为 max-expiry-delay 指定值,代理会将过期时间设置为 min-expiry-delay 的指定值。如果您没有为 min-expiry-delay 指定值,代理不会更改消息的过期时间。
    • 对于过期时间超过 max-expiry-delay 的消息,代理会将过期时间设置为 max-expiry-delay 的指定值。
    • 对于过期时间低于 min-expiry-delay 的消息,代理会将过期时间设置为 min-expiry-delay 的指定值。
    • 对于在 min-expiry-delay 和 max-expiry-delay 之间带有 expiration 的消息, 代理不会更改消息的过期时间。
    • 如果您为 expiry-delay 指定一个值(即默认值 -1以外的值),这将覆盖您为 min-expiry-delay 和 max-expir y-delay 指定的任何值。
    • min-expiry-delay 和 max- expiry-delay 的默认值都是 -1 (即禁用)。
  5. 在 配置文件的 address 元素中,配置之前为 expiration -address 指定 的地址。在此地址上定义队列.例如:

    <addresses>
        ...
        <address name="ExpiryAddress">
            <anycast>
                <queue name="ExpiryQueue"/>
            </anycast>
        </address>
        ...
    </addresses>

    以上示例配置将到期队列 ExpiryQueue 与到期地址 ExpiryAddress 关联。

4.12.2. 自动创建到期资源

常见用例是根据其原始地址隔离过期消息。例如,您可以选择将过期的消息路由到名为 EXP.stocks 到期队列。同样,您可能将过期的消息从名为 Order 的地址路由 名为 EXP.orders 的到期队列。

借助这种路由模式,可以轻松跟踪、检查和管理过期的消息。不过,这样的模式很难在主要使用自动创建地址和队列的环境中实施。在这种类型的环境中,管理员不需要额外的工作来手动创建地址和队列来存放过期的消息。

作为解决方案,您可以将代理配置为自动创建资源(即强制和队列),以处理给定地址或 一组 地址的过期消息。以下步骤演示了一个示例。

先决条件

流程

  1. 打开 <broker_instance_dir>/etc/broker.xml 配置文件。
  2. 找到您之前添加到配置文件中的 <address-setting> 元素,以定义匹配地址或地址 集的 到期地址。例如:

    <configuration ...>
    
       <core ...>
          ...
          <address-settings>
             ...
             <address-setting match="stocks">
                ...
                <expiry-address>ExpiryAddress</expiry-address>
                ...
             </address-setting>
             ...
          <address-settings>
    <configuration ...>
  3. <address-setting> 元素中,添加指示代理自动创建到期资源(即地址和队列)以及如何命名这些资源的配置项目。例如:

    <configuration ...>
       <core ...>
          ...
          <address-settings>
             ...
             <address-setting match="stocks">
                ...
                <expiry-address>ExpiryAddress</expiry-address>
                <auto-create-expiry-resources>true</auto-create-expiry-resources>
                <expiry-queue-prefix>EXP.</expiry-queue-prefix>
                <expiry-queue-suffix></expiry-queue-suffix>
                ...
             </address-setting>
             ...
          <address-settings>
    <configuration ...>
    auto-create-expiry-resources

    指定代理是否自动创建一个到期地址和队列来接收过期的消息。默认值为 false

    如果参数值设为 true,代理会自动创建一个 <address> 元素来定义到期地址和关联的到期队列。auto-created <address> 元素的 name 值与为 <expiry-address> 指定的名称值匹配。

    自动创建的到期队列具有 多播 路由类型。默认情况下,代理会命名到期队列以匹配最初发送已过期消息的地址,例如:

    代理还为使用 _AMQ_ORIG_ADDRESS 属性的到期队列定义过滤器。此过滤器确保到期队列仅接收发送到对应原始地址的消息。

    expiry-queue-prefix

    代理应用到自动创建的到期队列的名称的前缀。默认值为 EXP。

    当您定义前缀值或保留默认值时,到期队列的名称是前缀和原始地址的串联,如 EXP.stocks

    expiry-queue-suffix
    代理应用到自动创建的到期队列的名称的后缀。未定义默认值(即代理不应用后缀)。

您可以使用自身队列名称(例如,使用 AMQ 代理核心协议 JMS 客户端)或使用完全限定队列名称(例如,使用其他 JMS 客户端)直接访问到期队列队列。

注意

由于会自动创建到期地址和队列,因此与删除自动创建的地址和队列相关的任何地址设置也适用于这些到期资源。

其它资源

4.13. 将未传送的消息移到死信地址

如果向客户端发送消息失败,您可能不希望代理不断尝试传递消息。为防止无限发送尝试,您可以定义一个 死信地址 以及一个或多个关联 死信队列。在尝试了指定次数后,代理会从原始队列中删除未传送的消息,并将消息发送到配置的死信地址。之后,系统管理员可以使用死信队列中未传送的消息来检查消息。

如果您没有为给定队列配置死信地址,代理会在指定传输尝试次数后从队列中永久删除未传送的消息。

从死信队列中消耗的未传送信息具有以下属性:

_AMQ_ORIG_ADDRESS
指定邮件原始地址的字符串属性
_AMQ_ORIG_QUEUE
指定消息原始队列的字符串属性

4.13.1. 配置死信地址

以下步骤演示了如何配置死信地址和关联的死信队列。

流程

  1. 打开 <broker_instance_dir>/etc/broker.xml 配置文件。
  2. 在与您的队列名称匹配的 <address-setting> 元素 中,为死信地址名称和最大发送尝试数设置值。例如:

    <configuration ...>
       <core ...>
          ...
          <address-settings>
             ...
             <address-setting match="exampleQueue">
                <dead-letter-address>DLA</dead-letter-address>
                <max-delivery-attempts>3</max-delivery-attempts>
             </address-setting>
          ...
          <address-settings>
    <configuration ...>
    匹配
    代理在此 address-setting 部分中应用的配置的地址。您可以为 <address-setting> 元素的 match 属性指定一个通配符表达式。如果要将 <address-setting> 元素中配置的死信设置与匹配的地址 关联,可以使用通配符表达式。
    dead-letter-address
    死信地址的名称。在本例中,代理将未传送的消息从队列 exampleQueue 移动到死信地址 DLA
    max-delivery-attempts
    代理在将未传送消息移至配置的死信地址前尝试的最大发送次数。在这个示例中,代理会在传送尝试失败后将未传送的消息移到死信地址。默认值为 10。如果您希望代理进行无限数量的重新传送尝试,请将值指定为 -1
  3. address 部分中,为死信 地址 DLA 添加 address 元素。若要将死信队列与死信地址关联,请为 队列 指定名称值。例如:

    <configuration ...>
       <core ...>
          ...
          <addresses>
             <address name="DLA">
                <anycast>
                   <queue name="DLQ" />
                </anycast>
             </address>
          ...
          </addresses>
       </core>
    </configuration>

在上述配置中,您将一个名为 DLQ 的死信队列与死信地址 DLA 关联。

其它资源

4.13.2. 自动创建死信队列

常见用例是根据其原始地址隔离未传送的消息。例如,您可以选择将不传送的消息从名为 的文件地址路由到名为 DLA.stocks 的死 信队列,该队列关联死信队列 DLQ.stocks。同样,您可以将名为 order 的地址中的未传送消息路由 名为 DLA.orders 的死信地址。

借助这种路由模式,可以轻松跟踪、检查和管理未交付的消息。不过,这样的模式很难在主要使用自动创建地址和队列的环境中实施。这种类型的环境的系统管理员可能不希望进行额外的工作,手动创建地址和队列来保存未传送的消息。

作为解决方案,您可以将代理配置为自动创建组和队列以处理未交付的消息,如下方所示。

先决条件

流程

  1. 打开 <broker_instance_dir>/etc/broker.xml 配置文件。
  2. 找到您之前添加的 <address-setting> 元素,以定义匹配队列或一组队列的死信地址。例如:

    <configuration ...>
       <core ...>
          ...
          <address-settings>
             ...
             <address-setting match="exampleQueue">
                <dead-letter-address>DLA</dead-letter-address>
                <max-delivery-attempts>3</max-delivery-attempts>
             </address-setting>
          ...
          <address-settings>
    <configuration ...>
  3. <address-setting> 元素中,添加指示代理自动创建死信资源(即地址和队列)以及如何命名这些资源的配置项目。例如:

    <configuration ...>
       <core ...>
          ...
          <address-settings>
             ...
             <address-setting match="exampleQueue">
                <dead-letter-address>DLA</dead-letter-address>
                <max-delivery-attempts>3</max-delivery-attempts>
                <auto-create-dead-letter-resources>true</auto-create-dead-letter-resources>
                <dead-letter-queue-prefix>DLQ.</dead-letter-queue-prefix>
                <dead-letter-queue-suffix></dead-letter-queue-suffix>
             </address-setting>
          ...
          <address-settings>
    <configuration ...>
    auto-create-dead-letter-resources

    指定代理是否自动创建一个死信地址和队列来接收未传送的信息。默认值为 false

    如果 auto-create-dead-letter-resources 被设置为 true,代理会自动创建一个 <address> 元素来定义死信地址和关联的死信队列。自动创建的 <address> 元素的名称与您为 <dead-letter-address> 指定的名称值匹配。

    代理在自动创建的 <address> 元素中定义的 死信队列具有 多播 路由类型。默认情况下,代理会命名死信队列,以匹配未传送消息的原始地址,例如:cr ue

    代理还为使用 _AMQ_ORIG_ADDRESS 属性的死信队列定义过滤器。此过滤器确保死信队列仅接收发送到对应原始地址的消息。

    dead-letter-queue-prefix

    代理应用到自动创建的死信队列名称的前缀。默认值为 DLQ。

    当您定义前缀值或保留默认值时,死信队列的名称是前缀和原始地址的串联,如 DLQ.stocks

    dead-letter-queue-suffix
    代理应用到自动创建的死信队列的后缀。未定义默认值(即代理不应用后缀)。

4.14. 已过期或未传送的 AMQP 消息的注解和属性

在代理将过期或未交付的 AMQP 消息移至您配置的过期或死信队列之前,代理会将注释和属性应用到消息。客户端可以根据这些属性或注释创建过滤器,从到期或死信队列中选择要使用的特定消息。

注意

代理应用的属性是 内部 属性,这些属性不向客户端公开以供常规使用,但 可以由 过滤器中的客户端指定。

下表显示了代理应用到已过期或未传送的 AMQP 消息的注解和内部属性。

注解名称内部属性名称Description

x-opt-ORIG-MESSAGE-ID

_AMQ_ORIG_MESSAGE_ID

原始消息 ID,在消息移到到期或死信队列之前。

x-opt-ACTUAL-EXPIRY

_AMQ_ACTUAL_EXPIRY

消息到期时间,指定为自上次 epoch 启动以来的毫秒数。

x-opt-ORIG-QUEUE

_AMQ_ORIG_QUEUE

已过期或未传送消息的原始队列名称。

x-opt-ORIG-ADDRESS

_AMQ_ORIG_ADDRESS

已过期或未传送消息的原始地址名称。

其它资源

4.15. 禁用队列

如果您在代理配置中手动定义队列,则默认启用队列。

但是,在某些情况下,您可能想要定义一个队列,以便客户端可以订阅该队列,但没有准备好将队列用于消息路由。或者,您可能想要停止消息流到队列,但仍保持客户端绑定到队列。在这些情况下,您可以禁用队列。

以下示例演示了如何禁用您在代理配置中定义的队列。

先决条件

流程

  1. 打开 <broker_instance_dir>/etc/broker.xml 配置文件。
  2. 对于之前定义的队列,添加 enabled 属性。若要禁用队列,可将此属性的值设为 false。例如:

    <addresses>
       <address name="orders">
          <multicast>
             <queue name="orders" enabled="false"/>
          </multicast>
       </address>
    </addresses>

    enabled 属性的默认值为 true。当您将值设置为 false 时,到队列的消息路由将被禁用。

注意

如果您禁用了一个地址上的所有队列,则发送到该地址 的所有 消息将被静默丢弃。

4.16. 限制与队列连接的消费者数量

使用 max-consumers 属性限制与特定队列连接的使用者数量。通过将 max-consumers 标志设置为 1,创建独占消费者。默认值为 -1,它会设置无限数量的消费者。

以下步骤演示了如何为可以连接到队列的用户数量设置限制。

流程

  1. 打开 <broker_instance_dir>/etc/broker.xml 配置文件。
  2. 对于给定队列,添加 max-consumers 键并设置值。

    <configuration ...>
      <core ...>
        ...
        <addresses>
           <address name="foo">
              <anycast>
                 <queue name="q3" max-consumers="20"/>
              </anycast>
           </address>
        </addresses>
      </core>
    </configuration>

    根据上述配置,只有 20 名消费者可以同时连接到队列 q3

  3. 要创建专用消费者,请将 max-consumers 设置为 1

    <configuration ...>
      <core ...>
        ...
        <address name="foo">
          <anycast>
            <queue name="q3" max-consumers="1"/>
          </anycast>
        </address>
      </core>
    </configuration>
  4. 要允许无限数量的消费者,请将 max-consumers 设置为 -1

    <configuration ...>
      <core ...>
        ...
        <address name="foo">
          <anycast>
             <queue name="q3" max-consumers="-1"/>
          </anycast>
        </address>
      </core>
    </configuration>

4.17. 配置专用队列

专用队列是特殊的队列,一次将所有消息路由到一个消费者。当您希望所有消息都由同一使用者序列处理时,此配置很有用。如果队列中有多个消费者,则只有一个消费者会接收消息。如果消费者断开与队列的连接,则会选择另一个消费者。

4.17.1. 单独配置专用队列

以下步骤演示了如何将给定队列单独配置为独占队列。

流程

  1. 打开 <broker_instance_dir>/etc/broker.xml 配置文件。
  2. 对于给定队列,添加 专用 密钥。将值设为 true

    <configuration ...>
      <core ...>
        ...
        <address name="my.address">
          <multicast>
            <queue name="orders1" exclusive="true"/>
          </multicast>
        </address>
      </core>
    </configuration>

4.17.2. 为地址配置独占队列

以下步骤演示了如何配置地址或 一组 地址,以便所有关联的队列都具有排他性。

  1. 打开 <broker_instance_dir>/etc/broker.xml 配置文件。
  2. address-setting 元素中,为匹配地址添加 default-exclusive-queue 键。将值设为 true

    <address-setting match="myAddress">
        <default-exclusive-queue>true</default-exclusive-queue>
    </address-setting>

    根据上述配置,与 myAddress 地址关联的所有队列都是专用的。默认情况下,default-exclusive -queue 的值为 false

  3. 要为 一组 地址配置独占队列,您可以指定一个地址通配符。例如:

    <address-setting match="myAddress.*">
        <default-exclusive-queue>true</default-exclusive-queue>
    </address-setting>

其它资源

4.18. 将特定地址设置应用到临时队列

例如,在使用 JMS 时,代理 会通过分配一个通用唯一标识符(UUID)作为地址名称和队列名称来创建临时 队列。

默认的 <address-setting match="#"> 将配置的地址设置应用到 所有 队列,包括临时队列。如果只想将特定的地址设置应用到临时队列,您可以选择指定 临时队列-命名空间,如下所述。然后,您可以指定与命名空间匹配的地址设置,代理将这些设置应用到所有临时队列。

当创建临时队列并存在临时队列命名空间时,代理会将 temporary -queue-namespace 值和配置的分隔符(default .)前缀到地址名称。它使用它来引用匹配的地址设置。

流程

  1. 打开 <broker_instance_dir>/etc/broker.xml 配置文件。
  2. 添加 ephemeral -queue-namespace 值。例如:

    <temporary-queue-namespace>temp-example</temporary-queue-namespace>
  3. 添加具有 匹配 值的 address-setting 元素,对应于临时队列命名空间。例如:

    <address-settings>
       <address-setting match="temp-example.#">
          <enable-metrics>false</enable-metrics>
       </address-setting>
    </address-settings>

    这个示例禁用了代理创建的所有临时队列的指标。

    注意

    指定临时队列命名空间不会影响临时队列。例如,命名空间不会更改临时队列的名称。命名空间用于引用临时队列。

其它资源

4.19. 配置环队列

通常,AMQ 代理中的队列使用先进(FIFO)语义。这意味着代理将消息添加到队列的尾部,并将它们从头中删除。环队列是一种特殊类型的队列,存放指定的固定消息数。代理会在新消息到达时删除队列头的消息,但队列已保存指定数量的邮件,以此维护固定队列大小。

例如,一个环队列配置了大小为 3,制作者按顺序发送消息 ABCD。消息 C 到达队列后,队列中的消息数已达到配置的环大小。此时消息 A 处于 队列的头部,而消息 C 位于 尾部。当消息 D 到达队列时,代理会将消息添加到队列的尾部。要维护固定队列大小,代理会在队列头删除消息(即消息 A)。消息 B 现在处于队列的头部。

4.19.1. 配置环队列

以下步骤演示了如何配置环队列。

流程

  1. 打开 <broker_instance_dir>/etc/broker.xml 配置文件。
  2. 要在匹配地址上为未设置明确环大小的所有队列定义默认环大小,请在 address-setting 元素中指定 default-ring- size 的值。例如:

    <address-settings>
       <address-setting match="ring.#">
          <default-ring-size>3</default-ring-size>
       </address-setting>
    </address-settings>

    default-ring-size 参数对于定义自动创建的队列的默认大小特别有用。default-ring-size 的默认值为 -1 (即无大小限制)。

  3. 若要在特定队列上定义环大小,请将 ring-size 键添加到 队列 元素中。指定一个值。例如:

    <addresses>
       <address name="myRing">
          <anycast>
             <queue name="myRing" ring-size="5" />
          </anycast>
       </address>
    </addresses>
注意

您可以在代理运行时更新 ring-size 值。代理会动态应用更新。如果新的 ring-size 值小于之前的值,代理不会立即从队列头中删除消息来强制实施新大小。发送到队列的新消息仍会强制删除较旧的消息,但队列的大小不会达到新的、减小的大小,除非通过客户端正常使用的消息而自动执行此操作。

4.19.2. 环队列故障排除

本节介绍环队列的行为与其配置不同的情况。

in-delivery 消息和回滚

当消息正在传送到消费者时,消息处于"中间"状态,其中消息在技术上不再在队列中,但也尚未确认。消息一直处于传送中状态,直到被消费者确认。处于传送中状态的消息不能从环队列中删除。

因为代理无法删除传送中的消息,所以客户端可以发送比环大小配置更多的消息。例如,考虑这种情况:

  1. 制作者向配置了 ring-size="3" 的环队列发送三条消息。
  2. 所有消息都会立即分配给消费者。

    此时,Message Count= 3 和 delivery Count= 3

  3. 制作者向队列发送另一条消息。该消息随后被分配给消费者。

    现在,MessageCount = 4deliveryCount = 4。消息数 4 大于配置的环大小 3。但是,代理会坚持允许这种情况,因为它无法从队列中删除传输中消息。

  4. 现在,假设消费者未拒绝任何消息即可关闭。

    在这种情况下,四个未确认的消息将被取消到代理,并按使用它们的相反顺序添加到队列头。此操作在其配置的环大小上放置队列。由于环队列将队列末尾的消息优先于头条消息,因此队列会丢弃制作者发送的第一条消息,因为这是最近一次添加回队列头的消息。事务或核心会话回滚的方式相同。

如果您直接使用核心客户端,或者使用 AMQ 核心协议 JMS 客户端,您可以通过减少 consumerWindowSize 参数的值来最小化传输中的消息数量(默认为 1024 * 1024 字节)。

计划的消息

将计划的消息发送到队列时,该消息不会像普通消息一样立即添加到队列的尾部。相反,代理将计划的消息保存在中间缓冲区中,并根据消息的详细信息将消息调度到队列的头部。但是,调度的消息仍会反映在队列的消息计数中。与传送中消息一样,这种行为可使它似乎代理没有强制实施环队列大小。例如,考虑这种情况:

  1. 在 12:00 时,制作者将消息 A 发送到配置了 ring-size="3" 的环队列。该消息计划为 12:05。

    此时,Message Count= 1 和 schedule Count= 1

  2. 在 12:01 时,制作者将消息 B 发送到同一环队列。

    现在,MessageCount= 2scheduledCount= 1

  3. 在 12:02 时,制作者将消息 C 发送到同一环队列。

    现在,MessageCount= 3scheduledCount= 1

  4. 在 12:03 时,制作者将消息 D 发送到同一环队列。

    现在,MessageCount= 4scheduledCount= 1

    队列的消息数现在为 4,一个 大于 配置的环大小 3。但是,调度的消息尚不在队列中(即,它位于代理中并调度到队列中)。在预定的交付时间为 12:05 时,代理会将消息放在队列的头部。但是,由于环队列已达到其配置大小,计划的消息 A 将立即被删除。

页面信息

与传输中调度的消息和消息类似,分页消息不计入代理强制执行的环队列大小,因为消息实际上是在地址级别上分页的,而不是队列级别。分页消息在队列上不是在技术上进行的,尽管它反映在队列的 messageCount 值中。

建议您不要将分页用于具有环队列的地址。相反,请确保整个地址可适合内存。或者,将 address-full-policy 参数配置为 DROPBLOCKFAIL 的值。

其它资源

4.20. 配置追溯地址

将地址配置为 被动 可让您保留发送到该地址的消息,包括在没有绑定到该地址的队列时。稍后创建队列并将其绑定到地址时,代理会追溯地将消息分发到这些队列。如果地址 没有 配置为被动且尚未绑定队列,代理会丢弃发送到该地址的消息。

当您配置追溯地址时,代理会创建一个类型的内部实例,称为 环队列。环队列是一种特殊类型的队列,存放指定的固定消息数。队列达到指定大小后,到达队列的下一个消息将强制最旧的消息退出队列。当您配置追溯地址时,您可以间接指定内部环队列的大小。默认情况下,内部队列使用 多播 路由类型。

由被动地址使用的内部环队列通过管理 API 公开。您可以检查指标并执行其他常见管理操作,如清空队列。环形队列还有助于 地址的整体内存使用量,这会影响消息分页等行为。

以下步骤演示了如何将地址配置为追溯。

流程

  1. 打开 <broker_instance_dir>/etc/broker.xml 配置文件。
  2. address-setting 元素 中为 retroactive-message-count 参数指定一个值。您指定的值定义了您希望代理保留的消息数量。例如:

    <configuration>
      <core>
        ...
        <address-settings>
           <address-setting match="orders">
              <retroactive-message-count>100</retroactive-message-count>
           </address-setting>
        </address-settings>
    ...
      </core>
    </configuration>
    注意

    您可以在代理运行时更新 retroactive-message-count 的值,可在 broker.xml 配置文件或管理 API 中更新。但是,如果 降低 此参数的值,则需要额外的步骤,因为追溯地址是通过环队列实施的。个环队列 ( ring-size 参数减少)不会自动从队列中删除消息,从而实现新的 环大小 值。此行为是一种防止意外的消息丢失的保护。在这种情况下,您需要使用管理 API 来手动减少环队列中的消息数量。

其它资源

4.21. 为内部管理的地址和队列禁用公告消息

默认情况下,AMQ 代理会在 OpenWire 客户端连接到代理时创建有关地址和队列的公告信息。公告消息发送到由代理创建的内部管理地址。这些地址显示在与用户部署的地址和队列相同的显示器上的 AMQ 管理控制台中。虽然它们提供了有用的信息,但当代理管理大量目的地时,公告消息可能会导致不必要的结果。例如,消息可能会增加内存用量或紧张的连接资源。另外,在尝试显示为发送公告消息创建的所有地址时,AMQ 管理控制台可能会变得杂乱。要避免这种情况,您可以使用以下参数来配置代理上公告信息的行为。

supportAdvisory
将这个选项设置为 true 可启用创建公告信息或 false 来禁用它们。默认值为 true
suppressInternalManagementObjects
将此选项设置为 true 以将公告消息公开给管理服务,如 JMX 注册表和 AMQ 管理控制台,或 false 以不公开它们。默认值为 true

以下流程演示了如何在代理上禁用公告消息。

流程

  1. 打开 <broker_instance_dir>/etc/broker.xml 配置文件。
  2. 对于 OpenWire 连接器,将 supportAdvisoryblockedInternalManagementObjects 参数添加到配置的 URL。按照本节前面所述设置值。例如:

    <acceptor name="artemis">tcp://127.0.0.1:61616?protocols=CORE,AMQP,OPENWIRE;supportAdvisory=false;suppressInternalManagementObjects=false</acceptor>

4.22. 联合地址和队列

Federation 允许在代理之间传输消息,而无需代理位于一个通用集群中。代理可以是独立的,也可以是独立的集群中。此外,源和目标代理可以位于不同的管理域中,这意味着代理可能有不同的配置、用户和安全设置。代理甚至可能使用不同版本的 AMQ Broker。

例如,联合适合将信息从一个集群可靠发送到另一个集群。此传输可能跨越广域网(WAN)、云基础架构 区域或互联网。如果从源代理到目标代理的连接丢失(例如,因为网络失败),源代理会尝试重新建立连接,直到目标代理恢复在线。当目标代理恢复在线时,消息传输会恢复。

管理员可以使用地址和队列策略来管理联合。策略配置可以与特定地址或队列匹配,或者策略可以包含通配符表达式,将配置与地址或队列 匹配。因此,联合可以动态应用,因为队列或地址添加到匹配集合或从匹配集合中删除。策略可以 包含多个 表达式,包括和/或排除特定地址和队列。另外,多个策略可以应用到代理或代理集群。

在 AMQ Broker 中,两个主要的联合选项是 地址联合队列联合。以下小节中描述了这些选项。

注意

代理可以包含联合组件 仅本地组件的配置。也就是说,如果您在代理中配置联合,则不需要联合那个代理上的所有内容。

4.22.1. 关于地址联合

地址联合如同连接的代理之间的完整多播分布模式。例如,发送到 BrokerA 上地址的每个消息都会传送到那个代理上的每个队列。另外,每个信息都会传送到 BrokerB 以及那里附加的队列。

地址联合动态地将代理链接到远程代理中的地址。例如,如果本地代理希望从远程代理上的地址获取信息,则在远程地址上自动创建队列。然后,远程代理上的消息会被添加到此队列中。最后,消息会被复制到本地代理上的对应地址,就像它们最初直接发布到本地地址。

不需要重新配置远程代理来允许联合在其上创建地址。但是,本地代理 确实需要 被授予远程地址的权限。

4.22.2. 地址联合的通用拓扑

下面介绍了一些用于地址联合的常见拓扑结构。

对称拓扑

在对称拓扑中,制作者和使用者连接到每个代理。队列及其消费者可以接收由任一制作者发布的消息。对称拓扑的示例如下所示:

图 4.1. 对称拓扑中的地址联合

对称地址联合

为对称拓扑配置地址联合时,将 address 策略的 max-hops 属性的值设置为 1 非常重要。这样可确保 仅复制一次 消息,从而避免循环复制。如果此属性设为更大的值,使用者将收到同一消息的多个副本。

完整网格拓扑

完整的网格拓扑与对称设置类似。三个或多个代理相互对称联合,创建完整的网格。在这个设置中,制作者和消费者连接到每个代理。队列及其消费者可以接收任何制作者发布的消息。此拓扑的示例如下所示:

图 4.2. 完整网格拓扑中的地址联合

完整网格地址联合

与对称设置一样,在为完整网格拓扑配置地址联合时,必须将地址策略的 max-hops 属性的值设置为 1。这样可确保 仅复制一次 消息,从而避免循环复制。

Ring topology

在代理环中,每个联合地址仅上游到环中的另一个地址。此拓扑的示例如下所示:

图 4.3. ring 拓扑中的地址联合

Ring address federation

当您为环拓扑配置联合时,为了避免循环复制,必须将地址策略 的 max-hops 属性设置为 n-1,其中 n 是环中的节点数。例如,在上面显示的环拓扑中,max-hops 的 值设置为 5。这样可确保环中的每个地址都 准确看到消息一次

环形拓扑的一个优点在于,设置成本低廉,因为您需要进行的物理连接数量。但是,这种拓扑的缺点是,如果单个代理失败,整个环会失败。

Fan-out 拓扑

在 Fan-out 拓扑中,单个主地址由联合地址树链接到。任何发布到主地址的消息都可以被任何连接到树中的代理的消费者接收。该树可以配置为任何深度。也可以扩展树形,无需在树中重新配置现有代理。此拓扑的示例如下所示:

图 4.4. fan-out 拓扑中的地址联合

清空地址联合

当您为 fan-out 拓扑配置联合时,请确保将地址策略的 max-hops 属性设置为 n-1,其中 n 是树中的级别数。例如,在上面显示的 fan-out 拓扑中,max-hops 的值设置为 2。这样可确保树中的每个地址都 准确看到消息一次

4.22.3. 支持在地址联合配置中转换绑定

在配置地址联合时,您可以在地址策略配置中添加对转换绑定的支持。添加这个支持可让联合响应转换绑定以在远程代理上为给定地址创建联合消费者。

例如,假设地址策略中包含名为 test.federation.source 的地址,并且不包含名为 test.federation.target 的另一个地址。通常,在 test.federation.target 上创建队列时,这 不会导致 创建联合消费者,因为该地址不是地址策略的一部分。但是,如果您创建一个转换的绑定,如 test.federation.source 是源地址,test.federation.target 是转发地址,则会在转发地址上创建一个持久消费者。源地址仍然必须使用 多播 路由类型,但目标地址可以使用 多播任播

示例用例是将 JMS 主题(多播 地址)重定向到 JMS 队列(任播 地址)的转变。这将为不支持 JMS 2.0 和共享订阅的传统使用者实现消息负载平衡。

4.22.4. 为代理集群配置联合

以下部分中的示例显示了如何配置 独立 本地和远程代理之间的地址和队列联合。对于独立代理之间的联合,联合配置的名称以及任何地址和队列策略的名称必须在本地和远程代理之间唯一。

但是,如果您要为 集群中的 代理配置联合,则还需要额外的要求。对于集群代理,对于集群中的每个代理,联合配置的名称以及该配置中任何地址和队列策略的名称 必须相同

确保同一集群中的代理使用相同的联合配置、地址和队列策略名称以避免消息重复。例如,如果同一集群中的代理 有不同的 联合配置名称,这可能会导致为同一地址创建多个名称不同的转发队列,从而导致下游消费者出现消息重复。相比之下,如果同一集群中的代理使用相同的 联合 配置名称,这基本上会创建复制的群集转发队列,这些队列负载平衡到下游消费者。这可避免消息重复。

4.22.5. 配置上游地址联合

以下示例演示了如何在独立代理之间配置上游地址联合。在本例中,您可以从本地(即 下游)代理将联合配置为一些远程(即 上游)代理。

先决条件

流程

  1. 打开 <broker_instance_dir>/etc/broker.xml 配置文件。
  2. 添加一个包含 <federation> 元素的新 <federations > 元素。例如:

    <federations>
      <federation name="eu-north-1" user="federation_username" password="32a10275cf4ab4e9">
      </federation>
    </federations>
    name
    联合配置的名称。在这个示例中,名称对应于本地代理的名称。
    user
    用于连接到上游代理的共享用户名。
    password
    用于连接到上游代理的共享密码。
    注意

    如果远程代理的用户名和密码凭证不同,您可以在将这些代理添加到配置时为这些代理单独指定凭证。这个步骤稍后会对此进行说明。

  3. 在 federation 元素 中添加 <address-policy> 元素。例如:

    <federations>
        <federation name="eu-north-1" user="federation_username" password="32a10275cf4ab4e9">
    
            <address-policy name="news-address-federation" auto-delete="true" auto-delete-delay="300000" auto-delete-message-count="-1" enable-divert-bindings="false" max-hops="1" transformer-ref="news-transformer">
            </address-policy>
    
        </federation>
    </federations>
    name
    地址策略的名称。代理上配置的所有地址策略必须具有唯一的名称。
    auto-delete
    在地址联合期间,本地代理会在远程地址上动态创建持久队列。auto-delete 属性的值指定一旦本地代理断开连接并且也达到了 auto-delete- delay 和 auto-delete- message-count 属性的值,是否应删除 远程队列。如果要自动清理动态创建的队列,这个选项非常有用。如果您想在本地代理长时间断开连接时防止在本地代理上构建信息,则这个选项也非常有用。但是,如果您希望信息始终在断开连接时一直为本地代理排队,您可以把这个选项设置为 false,以避免本地代理上的信息丢失。
    auto-delete-delay
    本地代理断开连接后,此属性的值指定在动态创建的远程队列有资格自动删除前,以毫秒为单位。
    auto-delete-message-count
    断开本地代理后,此属性的值指定在该队列有资格自动删除前仍可在动态创建的远程队列中的最大消息数。
    enable-divert-bindings
    将此属性设置为 true 可根据需求侦听此绑定。如果存在带有与地址策略所包含地址匹配的地址转换的绑定,则任何与转义地址的转发地址匹配的队列绑定都将产生需求。默认值为 false
    max-hops
    消息在联合期间可以做出的最大跃点数。特定的拓扑需要此属性的特定值。要了解更多有关这些要求的信息,请参阅 第 4.22.2 节 “地址联合的通用拓扑”
    transformer-ref
    转换器配置的名称。如果要在联合消息传输过程中转换消息,您可以添加转换器配置。此流程稍后将介绍转换器配置。
  4. <address-policy> 元素中,添加 address-matching 模式,以从地址策略包含和排除地址匹配模式。例如:

    <federations>
        <federation name="eu-north-1" user="federation_username" password="32a10275cf4ab4e9">
    
            <address-policy name="news-address-federation" auto-delete="true" auto-delete-delay="300000" auto-delete-message-count="-1" enable-divert-bindings="false" max-hops="1" transformer-ref="news-transformer">
    
                <include address-match="queue.bbc.new" />
                <include address-match="queue.usatoday" />
                <include address-match="queue.news.#" />
    
                <exclude address-match="queue.news.sport.#" />
            </address-policy>
    
        </federation>
    </federations>
    Include
    此元素的 address-match 属性的值指定要包含在 address 策略中的地址。您可以指定一个精确的地址,如 queue. bbc.newqueue.usatoday。或者,您可以使用通配符表达式来指定匹配的地址 集合。在前面的示例中,地址策略还包含以字符串 queue.news 开头的 所有 地址名称。
    exclude
    此元素的 address-match 属性的值指定要从 address 策略中排除的地址。您可以指定确切的地址名称,或者使用通配符表达式来指定匹配的地址 集合。在上例中,address 策略排除以字符串 queue.news.sport 开头的 所有 地址名称。
  5. (可选)在联合 元素 中,添加一个转换 元素来引用自定义转换器实施。例如:

    <federations>
        <federation name="eu-north-1" user="federation_username" password="32a10275cf4ab4e9">
    
            <address-policy name="news-address-federation" auto-delete="true" auto-delete-delay="300000" auto-delete-message-count="-1" enable-divert-bindings="false" max-hops="1" transformer-ref="news-transformer">
    
                <include address-match="queue.bbc.new" />
                <include address-match="queue.usatoday" />
                <include address-match="queue.news.#" />
    
                <exclude address-match="queue.news.sport.#" />
            </address-policy>
    
            <transformer name="news-transformer">
                <class-name>org.foo.NewsTransformer</class-name>
                <property key="key1" value="value1"/>
                <property key="key2" value="value2"/>
            </transformer>
    
        </federation>
    </federations>
    name
    转换器配置的名称。这个名称在本地代理中必须是唯一的。这是您指定为地址策略 converter -ref 属性的值的名称。
    class-name

    实施 org.apache.activemq.artemis.core.server.transformer.Transformer 接口的用户定义的类的名称。

    转换器的 transformation () 方法通过消息调用,然后再传输消息。这可让您在联合之前转换邮件标题或正文。

    属性
    用于保存特定转换器配置的键值对。
  6. federation 元素中添加一个或多个 上游 元素。每个 上游 元素定义与远程代理的连接以及应用到该连接的策略。例如:

    <federations>
        <federation name="eu-north-1" user="federation_username" password="32a10275cf4ab4e9">
    
            <upstream name="eu-east-1">
                <static-connectors>
                    <connector-ref>eu-east-connector1</connector-ref>
                </static-connectors>
                <policy ref="news-address-federation"/>
            </upstream>
    
            <upstream name="eu-west-1" >
                <static-connectors>
                    <connector-ref>eu-west-connector1</connector-ref>
                </static-connectors>
                <policy ref="news-address-federation"/>
            </upstream>
    
            <address-policy name="news-address-federation" auto-delete="true" auto-delete-delay="300000" auto-delete-message-count="-1" enable-divert-bindings="false" max-hops="1" transformer-ref="news-transformer">
    
                <include address-match="queue.bbc.new" />
                <include address-match="queue.usatoday" />
                <include address-match="queue.news.#" />
    
                <exclude address-match="queue.news.sport.#" />
            </address-policy>
    
            <transformer name="news-transformer">
                <class-name>org.foo.NewsTransformer</class-name>
                <property key="key1" value="value1"/>
                <property key="key2" value="value2"/>
            </transformer>
    
        </federation>
    </federations>
    static-connectors
    包含一组 connector -ref 元素,这些元素引用在本地代理的 broker.xml 配置文件里其他位置定义的 连接器 元素。连接器定义用于传出连接的传输(TCP、SSL、HTTP 等)和服务器连接参数(主机、端口等)。此流程的下一步演示了如何添加 static-connectors 元素中引用的连接器。
    policy-ref
    应用于上游代理的下游代理上配置的地址策略的名称。

    您可以为 上游 元素指定的附加选项如下所述:

    name
    上游代理配置的名称。在本例中,名称与名为 eu-east-1 and eu-west-1 的上游代理对应。
    user
    创建与上游代理连接时使用的用户名。如果没有指定,则使用在联合 元素 配置中指定的共享用户名。
    password
    创建与上游代理连接时使用的密码。如果没有指定,则使用在联合 元素 配置中指定的共享密码。
    call-failover-timeout
    call-timeout 类似,但在故障切换尝试期间使用调用时。默认值为 -1,这意味着禁用了超时。
    call-timeout
    当联合连接传输阻止调用的数据包时,以毫秒为单位等待来自远程代理的回复。如果这一次到期,连接会引发异常。默认值为 30000
    check-period
    本地代理发送到远程代理以毫秒为单位的连续"keep-alive"消息之间的时间间隔,以检查联合连接的健康状态。如果联合连接健康,远程代理会响应每个 keep-alive 消息。如果连接不健康,则当下游代理无法从上游代理接收响应时,可以使用称为 断路器 的机制来阻止联合消费者。如需更多信息,请参阅 断路器-timeout 参数的说明。check-period 参数的默认值为 30000
    circuit-breaker-timeout
    下游和上游代理之间的单一连接可能很多联合队列和地址消费者共享。如果代理间的连接丢失,每个联合消费者可能会尝试同时重新连接。为避免这种情况,称为 断路 器的机制会阻止使用者。当指定的超时值 elapes 时,断路器重新尝试连接。如果成功,用户将不再受阻。否则,断路器将再次应用。
    connection-ttl
    如果联合连接停止从远程代理接收消息,则联合连接以毫秒为单位。默认值为 60000
    discovery-group-ref
    作为为与上游代理的连接定义静态连接器的替代方案,此元素可用于指定在 broker.xml 配置文件中已在其他位置配置的发现组。特别是,您要将现有发现组指定为此元素的 discovery-group-name 属性的值。有关发现组的详情请参考 第 14.1.5 节 “代理发现方法”
    ha
    指定是否为与上游代理的连接启用高可用性。如果此参数的值设为 true,本地代理可以连接到上游集群中的任何可用代理,并在实时上游代理关闭时自动切换到备份代理。默认值为 false
    initial-connect-attempts
    下游代理将连接上游代理的初始尝试次数。如果在没有建立连接的情况下达到这个值,上游代理会永久离线。下游代理不再将消息路由到上游代理。默认值为 -1,这意味着没有限制。
    max-retry-interval
    当与远程代理连接失败时,后续重新连接尝试之间最长的时间(毫秒)。默认值为 2000
    reconnect-attempts
    如果连接失败,下游代理将尝试重新连接到上游代理的次数。如果在没有重新建立连接的情况下达到这个值,上游代理会永久离线。下游代理不再将消息路由到上游代理。默认值为 -1,这意味着没有限制。
    retry-interval
    如果与远程代理的连接失败,则在后续重新连接尝试之间,以毫秒为单位。默认值为 500
    retry-interval-multiplier
    应用于 retry-interval 参数值的倍数。默认值为 1
    share-connection
    如果为同一代理同时配置了下游和上游连接,则共享相同的连接,只要下游和上游配置都将该参数的值设置为 true。默认值为 false
  7. 在本地代理中,将连接器添加到远程代理中。这些是您联合地址配置 的静态连接器元素 中引用的连接器。例如:

    <connectors>
       <connector name="eu-west-1-connector">tcp://localhost:61616</connector>
       <connector name="eu-east-1-connector">tcp://localhost:61617</connector>
    </connectors>

4.22.6. 配置下游地址联合

以下示例演示了如何为独立代理配置下游地址联合。

下游地址联合允许您在本地代理中添加一个或多个远程代理连接到本地代理的配置。这种方法的优势在于,您可以在单个代理中保留所有联合配置。例如,这可能是集线拓扑的有用方法。

注意

下游地址联合将颠倒联合连接与上游地址配置的方向。因此,当您将远程代理添加到配置时,这些代理被视为 下游 代理。下游代理使用配置中的连接信息来连接回本地代理,现在被视为上游。本例稍后将对此进行说明,当您为远程代理添加配置时。

先决条件

流程

  1. 在本地代理中,打开 <broker_instance_dir>/etc/broker.xml 配置文件。
  2. 添加一个包含 <federation> 元素的 <federations > 元素。例如:

    <federations>
        <federation name="eu-north-1" user="federation_username" password="32a10275cf4ab4e9">
        </federation>
    </federations>
  3. 添加地址策略配置。例如:

    <federations>
        ...
        <federation name="eu-north-1" user="federation_username" password="32a10275cf4ab4e9">
    
            <address-policy name="news-address-federation" max-hops="1" auto-delete="true" auto-delete-delay="300000" auto-delete-message-count="-1" transformer-ref="news-transformer">
    
                <include address-match="queue.bbc.new" />
                <include address-match="queue.usatoday" />
                <include address-match="queue.news.#" />
    
                <exclude address-match="queue.news.sport.#" />
            </address-policy>
    
        </federation>
      ...
    </federations>
  4. 如果要在传输前转换消息,请添加转换器配置。例如:

    <federations>
        ...
        <federation name="eu-north-1" user="federation_username" password="32a10275cf4ab4e9">
    
            <address-policy name="news-address-federation" max-hops="1" auto-delete="true" auto-delete-delay="300000" auto-delete-message-count="-1" transformer-ref="news-transformer">
    
                <include address-match="queue.bbc.new" />
                <include address-match="queue.usatoday" />
                <include address-match="queue.news.#" />
    
                <exclude address-match="queue.news.sport.#" />
            </address-policy>
    
            <transformer name="news-transformer">
                <class-name>org.foo.NewsTransformer</class-name>
                <property key="key1" value="value1"/>
                <property key="key2" value="value2"/>
            </transformer>
    
        </federation>
      ...
    </federations>
  5. 为每个远程代理添加 下游 元素。例如:

    <federations>
        ...
        <federation name="eu-north-1" user="federation_username" password="32a10275cf4ab4e9">
    
            <downstream name="eu-east-1">
                    <static-connectors>
                        <connector-ref>eu-east-connector1</connector-ref>
                    </static-connectors>
                    <transport-connector-ref>netty-connector</transport-connector-ref>
                    <policy ref="news-address-federation"/>
            </downstream>
    
            <downstream name="eu-west-1" >
                    <static-connectors>
                        <connector-ref>eu-west-connector1</connector-ref>
                    </static-connectors>
                    <transport-connector-ref>netty-connector</transport-connector-ref>
                    <policy ref="news-address-federation"/>
            </downstream>
    
            <address-policy name="news-address-federation" max-hops="1" auto-delete="true" auto-delete-delay="300000" auto-delete-message-count="-1" transformer-ref="news-transformer">
                <include address-match="queue.bbc.new" />
                <include address-match="queue.usatoday" />
                <include address-match="queue.news.#" />
    
                <exclude address-match="queue.news.sport.#" />
            </address-policy>
    
            <transformer name="news-transformer">
                <class-name>org.foo.NewsTransformer</class-name>
                <property key="key1" value="value1"/>
                <property key="key2" value="value2"/>
            </transformer>
    
        </federation>
      ...
    </federations>

    如前面的配置所示,远程代理现在被视为本地代理的下游。下游代理使用配置中的连接信息来回连接到本地(即 上游)代理。

  6. 在本地代理中,添加本地和远程代理使用的连接器和接收器来建立联合连接。例如:

    <connectors>
       <connector name="netty-connector">tcp://localhost:61616</connector>
       <connector name="eu-west-1-connector">tcp://localhost:61616</connector>
       <connector name="eu-east-1-connector">tcp://localhost:61617</connector>
    </connectors>
    
    <acceptors>
       <acceptor name="netty-acceptor">tcp://localhost:61616</acceptor>
    </acceptors>
    connector name="netty-connector"
    本地代理发送到远程代理的连接器配置。远程代理使用此配置返回本地代理。
    connector name="eu-west-1-connector", connector name="eu-east-1-connector"
    与远程代理的连接器.本地代理使用这些连接器连接到远程代理,并共享远程代理需要连接到本地代理的配置。
    acceptor name="netty-acceptor"
    本地代理上的接收器,对应于远程代理用来连接到本地代理的连接器。

4.22.7. 关于队列联合

队列联合提供了一种方式,可以与其他远程代理之间在本地代理上平衡单个队列的负载。

为了实现负载平衡,本地代理从远程队列检索消息,以满足本地消费者对消息的需求。下面是一个示例。

图 4.5. 对称队列联合

对称队列联合

远程队列不需要重新配置,它们不必位于同一代理或同一集群中。建立远程链接和联合队列所需的所有配置都位于本地代理中。

4.22.7.1. 队列联合的优点

下面是您可以选择配置队列联合的一些原因。

增加容量
队列联合可以创建一个"逻辑"队列,该队列分布到多个代理上。这个逻辑分布式队列的容量比单个代理上的单个队列高得多。在这个设置中,尽可能多的信息都从最初发布到的代理中消耗。仅当需要负载平衡时,系统才会在联合中移动信息。
部署多区域设置

在多区域设置中,您可能在一个区域或场馆中有一个消息制作者,并在另一个地区拥有消费者。但是,理想情况下,您应该将生产者和消费者连接在本地保留到给定区域。在这种情况下,您可以在生产者和消费者的每个区域部署代理,并使用队列联合在地区之间通过广域网(WAN)移动消息。下面是一个示例。

图 4.6. 多区域队列联合

multi region queue federation
在安全企业 LAN 和 DMZ 间进行通信

在网络安全性中,非专用 区域 (DMZ)是一个物理或逻辑子网,包含企业的外部服务并将其公开给不可信、通常更大的网络,如互联网。企业的局域网(LAN)中的其余部分仍与该外部网络隔离,位于防火墙后面。

在很多消息制作者在 DMZ 中以及安全企业 LAN 中的多个消费者的情况下,可能不适合让生产者连接到安全的企业 LAN 中的代理。在这种情况下,您可以在 DMZ 中部署代理,生产者可以发布消息。然后,企业 LAN 中的代理可以连接到 DMZ 中的代理,并使用联合队列从 DMZ 中的代理接收消息。

4.22.8. 配置上游队列联合

以下示例演示了如何为独立代理配置上游队列联合。在本例中,您可以从本地(即 下游)代理将联合配置为一些远程(即 上游)代理。

先决条件

流程

  1. 打开 <broker_instance_dir>/etc/broker.xml 配置文件。
  2. 在新的 <federations> 元素中,添加一个 <federation> 元素。例如:

    <federations>
      <federation name="eu-north-1" user="federation_username" password="32a10275cf4ab4e9">
      </federation>
    </federations>
    name
    联合配置的名称。在本例中,名称对应于下游代理的名称。
    user
    用于连接到上游代理的共享用户名。
    password
    用于连接到上游代理的共享密码。
    注意
    • 如果上游代理的用户名和密码凭证不同,您可以在将这些代理添加到配置时为这些代理单独指定凭证。这个步骤稍后会对此进行说明。
  3. 在 federation 元素 中添加 <queue-policy> 元素。指定 <queue-policy> 元素的属性值。例如:

    <federations>
        <federation name="eu-north-1" user="federation_username" password="32a10275cf4ab4e9">
    
            <queue-policy name="news-queue-federation" include-federated="true" priority-adjustment="-5" transformer-ref="news-transformer">
            </queue-policy>
    
        </federation>
    </federations>
    name
    队列策略的名称。代理上配置的所有队列策略都必须具有唯一的名称。
    include-federated

    当此属性的值设为 false 时,配置不会重新使已经有生动的消费者(即联合队列中的消费者)。这可避免在对称或闭环拓扑中,没有非动态使用者,并且系统中无无源地流动消息的情况。

    如果没有 闭环拓扑,您可以将此属性的值设置为 true。例如,假设您有一个由三个代理( BrokerA、Broker BBrokerC )组成的链,位于 BrokerA 的生产者和 BrokerC。在这种情况下,您需要 BrokerB 消费者更新为 BrokerA

    priority-adjustment
    当消费者连接到队列时,将在创建上游( 联合)消费者时使用其优先级。联合消费者的优先级通过 优先级调整属性的值调整。此属性的默认值为 -1,可确保在负载平衡期间本地使用者优先于联合消费者。但是,您可以根据需要更改优先级调整的值。
    transformer-ref
    转换器配置的名称。如果要在联合消息传输过程中转换消息,您可以添加转换器配置。此流程稍后将介绍转换器配置。
  4. <queue-policy> 元素中,添加 address-matching 模式,以从队列策略中包含和排除地址。例如:

    <federations>
        <federation name="eu-north-1" user="federation_username" password="32a10275cf4ab4e9">
    
            <queue-policy name="news-queue-federation" include-federated="true" priority-adjustment="-5" transformer-ref="news-transformer">
    
                <include queue-match="#" address-match="queue.bbc.new" />
                <include queue-match="#" address-match="queue.usatoday" />
                <include queue-match="#" address-match="queue.news.#" />
    
                <exclude queue-match="#.local" address-match="#" />
    
            </queue-policy>
    
        </federation>
    </federations>
    Include

    此元素的 address-match 属性的值指定要包含在队列策略中的地址。您可以指定一个精确的地址,如 queue. bbc.newqueue.usatoday。或者,您可以使用通配符表达式来指定匹配的地址 集合。在前面的示例中,队列策略还包含以字符串 queue.news 开头的 所有 地址名称。

    address-match 属性相结合,您可以使用 queue-match 属性在队列策略中包含这些地址上的特定队列。与 address-match 属性一样,您可以指定确切的队列名称,也可以使用通配符表达式来指定 一组 队列。在前面的示例中,数字符号(#)通配符字符表示每个地址或地址集合中 的所有 队列都包含在队列策略中。

    exclude
    此元素的 address-match 属性的值指定要从队列策略中排除的地址。您可以指定精确的地址或使用通配符表达式来指定匹配的地址 集合。在前面的示例中,编号符号(#)通配符字符表示将排除 与所有 地址 中的 queue-match 属性匹配 的任何 队列。在这种情况下,任何以 string .local 结尾的队列都将被排除。这表示特定队列保留为本地队列,而不是联合。
  5. 联合 元素中,添加一个转换 元素来引用自定义转换器实施。例如:

    <federations>
        <federation name="eu-north-1" user="federation_username" password="32a10275cf4ab4e9">
    
            <queue-policy name="news-queue-federation" include-federated="true" priority-adjustment="-5" transformer-ref="news-transformer">
    
                <include queue-match="#" address-match="queue.bbc.new" />
                <include queue-match="#" address-match="queue.usatoday" />
                <include queue-match="#" address-match="queue.news.#" />
    
                <exclude queue-match="#.local" address-match="#" />
    
            </queue-policy>
    
            <transformer name="news-transformer">
                <class-name>org.foo.NewsTransformer</class-name>
                <property key="key1" value="value1"/>
                <property key="key2" value="value2"/>
            </transformer>
    
        </federation>
    </federations>
    name
    转换器配置的名称。这个名称在相关的代理中必须是唯一的。您可以将此名称指定为 address 策略的 converter-ref 属性的值。
    class-name

    实施 org.apache.activemq.artemis.core.server.transformer.Transformer 接口的用户定义的类的名称。

    转换器的 transformation () 方法通过消息调用,然后再传输消息。这可让您在联合之前转换邮件标题或正文。

    属性
    用于保存特定转换器配置的键值对。
  6. federation 元素中添加一个或多个 上游 元素。每个 上游 元素定义上游代理连接以及应用到该连接的策略。例如:

    <federations>
        <federation name="eu-north-1" user="federation_username" password="32a10275cf4ab4e9">
    
            <upstream name="eu-east-1">
                <static-connectors>
                    <connector-ref>eu-east-connector1</connector-ref>
                </static-connectors>
                <policy ref="news-queue-federation"/>
            </upstream>
    
            <upstream name="eu-west-1" >
                <static-connectors>
                    <connector-ref>eu-west-connector1</connector-ref>
                </static-connectors>
                <policy ref="news-queue-federation"/>
            </upstream>
    
            <queue-policy name="news-queue-federation" include-federated="true" priority-adjustment="-5" transformer-ref="news-transformer">
    
                <include queue-match="#" address-match="queue.bbc.new" />
                <include queue-match="#" address-match="queue.usatoday" />
                <include queue-match="#" address-match="queue.news.#" />
    
                <exclude queue-match="#.local" address-match="#" />
    
            </queue-policy>
    
            <transformer name="news-transformer">
                <class-name>org.foo.NewsTransformer</class-name>
                <property key="key1" value="value1"/>
                <property key="key2" value="value2"/>
            </transformer>
    
        </federation>
    </federations>
    static-connectors
    包含一组 connector -ref 元素,这些元素引用在本地代理的 broker.xml 配置文件里其他位置定义的 连接器 元素。连接器定义用于传出连接的传输(TCP、SSL、HTTP 等)和服务器连接参数(主机、端口等)。此流程的以下步骤演示了如何添加由联合队列配置 的静态连接器元素 引用的连接器。
    policy-ref
    应用于上游代理的下游代理上配置的队列策略的名称。

    您可以为 上游 元素指定的附加选项如下所述:

    name
    上游代理配置的名称。在本例中,名称与名为 eu-east-1 and eu-west-1 的上游代理对应。
    user
    创建与上游代理连接时使用的用户名。如果没有指定,则使用在联合 元素 配置中指定的共享用户名。
    password
    创建与上游代理连接时使用的密码。如果没有指定,则使用在联合 元素 配置中指定的共享密码。
    call-failover-timeout
    call-timeout 类似,但在故障切换尝试期间使用调用时。默认值为 -1,这意味着禁用了超时。
    call-timeout
    当联合连接传输阻止调用的数据包时,以毫秒为单位等待来自远程代理的回复。如果这一次到期,连接会引发异常。默认值为 30000
    check-period
    本地代理发送到远程代理以毫秒为单位的连续"keep-alive"消息之间的时间间隔,以检查联合连接的健康状态。如果联合连接健康,远程代理会响应每个 keep-alive 消息。如果连接不健康,则当下游代理无法从上游代理接收响应时,可以使用称为 断路器 的机制来阻止联合消费者。如需更多信息,请参阅 断路器-timeout 参数的说明。check-period 参数的默认值为 30000
    circuit-breaker-timeout
    下游和上游代理之间的单一连接可能很多联合队列和地址消费者共享。如果代理间的连接丢失,每个联合消费者可能会尝试同时重新连接。为避免这种情况,称为 断路 器的机制会阻止使用者。当指定的超时值 elapes 时,断路器重新尝试连接。如果成功,用户将不再受阻。否则,断路器将再次应用。
    connection-ttl
    如果联合连接停止从远程代理接收消息,则联合连接以毫秒为单位。默认值为 60000
    discovery-group-ref
    作为为与上游代理的连接定义静态连接器的替代方案,此元素可用于指定在 broker.xml 配置文件中已在其他位置配置的发现组。特别是,您要将现有发现组指定为此元素的 discovery-group-name 属性的值。有关发现组的详情请参考 第 14.1.5 节 “代理发现方法”
    ha
    指定是否为与上游代理的连接启用高可用性。如果此参数的值设为 true,本地代理可以连接到上游集群中的任何可用代理,并在实时上游代理关闭时自动切换到备份代理。默认值为 false
    initial-connect-attempts
    下游代理将连接上游代理的初始尝试次数。如果在没有建立连接的情况下达到这个值,上游代理会永久离线。下游代理不再将消息路由到上游代理。默认值为 -1,这意味着没有限制。
    max-retry-interval
    当与远程代理连接失败时,后续重新连接尝试之间最长的时间(毫秒)。默认值为 2000
    reconnect-attempts
    如果连接失败,下游代理将尝试重新连接到上游代理的次数。如果在没有重新建立连接的情况下达到这个值,上游代理会永久离线。下游代理不再将消息路由到上游代理。默认值为 -1,这意味着没有限制。
    retry-interval
    如果与远程代理的连接失败,则在后续重新连接尝试之间,以毫秒为单位。默认值为 500
    retry-interval-multiplier
    应用于 retry-interval 参数值的倍数。默认值为 1
    share-connection
    如果为同一代理同时配置了下游和上游连接,则共享相同的连接,只要下游和上游配置都将该参数的值设置为 true。默认值为 false
  7. 在本地代理中,将连接器添加到远程代理中。这些是您联合地址配置 的静态连接器元素 中引用的连接器。例如:

    <connectors>
       <connector name="eu-west-1-connector">tcp://localhost:61616</connector>
       <connector name="eu-east-1-connector">tcp://localhost:61617</connector>
    </connectors>

4.22.9. 配置下游队列联合

以下示例演示了如何配置下游队列联合。

下游队列联合允许您在本地代理中添加一个或多个远程代理连接到本地代理的配置。这种方法的优势在于,您可以在单个代理中保留所有联合配置。例如,这可能是集线拓扑的有用方法。

注意

下游队列联合会颠倒联合连接与上游队列配置的方向。因此,当您将远程代理添加到配置时,这些代理被视为 下游 代理。下游代理使用配置中的连接信息来连接回本地代理,现在被视为上游。本例稍后将对此进行说明,当您为远程代理添加配置时。

先决条件

流程

  1. 打开 <broker_instance_dir>/etc/broker.xml 配置文件。
  2. 添加一个包含 <federation> 元素的 <federations > 元素。例如:

    <federations>
      <federation name="eu-north-1" user="federation_username" password="32a10275cf4ab4e9">
      </federation>
    </federations>
  3. 添加队列策略配置。例如:

    <federations>
        ...
        <federation name="eu-north-1" user="federation_username" password="32a10275cf4ab4e9">
    
            <queue-policy name="news-queue-federation" priority-adjustment="-5" include-federated="true" transformer-ref="new-transformer">
    
                <include queue-match="#" address-match="queue.bbc.new" />
                <include queue-match="#" address-match="queue.usatoday" />
                <include queue-match="#" address-match="queue.news.#" />
    
                <exclude queue-match="#.local" address-match="#" />
    
            </queue-policy>
    
        </federation>
      ...
    </federations>
  4. 如果要在传输前转换消息,请添加转换器配置。例如:

    <federations>
        ...
        <federation name="eu-north-1" user="federation_username" password="32a10275cf4ab4e9">
    
            <queue-policy name="news-queue-federation" priority-adjustment="-5" include-federated="true" transformer-ref="news-transformer">
    
                <include queue-match="#" address-match="queue.bbc.new" />
                <include queue-match="#" address-match="queue.usatoday" />
                <include queue-match="#" address-match="queue.news.#" />
    
                <exclude queue-match="#.local" address-match="#" />
    
            </queue-policy>
    
            <transformer name="news-transformer">
                <class-name>org.foo.NewsTransformer</class-name>
                <property key="key1" value="value1"/>
                <property key="key2" value="value2"/>
            </transformer>
    
        </federation>
      ...
    </federations>
  5. 为每个远程代理添加 下游 元素。例如:

    <federations>
        ...
        <federation name="eu-north-1" user="federation_username" password="32a10275cf4ab4e9">
    
            <downstream name="eu-east-1">
                <static-connectors>
                    <connector-ref>eu-east-connector1</connector-ref>
                </static-connectors>
                <transport-connector-ref>netty-connector</transport-connector-ref>
                <policy ref="news-address-federation"/>
            </downstream>
    
            <downstream name="eu-west-1" >
                <static-connectors>
                    <connector-ref>eu-west-connector1</connector-ref>
                </static-connectors>
                <transport-connector-ref>netty-connector</transport-connector-ref>
                <policy ref="news-address-federation"/>
            </downstream>
    
            <queue-policy name="news-queue-federation" priority-adjustment="-5" include-federated="true" transformer-ref="new-transformer">
    
                <include queue-match="#" address-match="queue.bbc.new" />
                <include queue-match="#" address-match="queue.usatoday" />
                <include queue-match="#" address-match="queue.news.#" />
    
                <exclude queue-match="#.local" address-match="#" />
    
            </queue-policy>
    
            <transformer name="news-transformer">
                <class-name>org.foo.NewsTransformer</class-name>
                <property key="key1" value="value1"/>
                <property key="key2" value="value2"/>
            </transformer>
    
        </federation>
      ...
    </federations>

    如前面的配置所示,远程代理现在被视为本地代理的下游。下游代理使用配置中的连接信息来回连接到本地(即 上游)代理。

  6. 在本地代理中,添加本地和远程代理使用的连接器和接收器来建立联合连接。例如:

    <connectors>
       <connector name="netty-connector">tcp://localhost:61616</connector>
       <connector name="eu-west-1-connector">tcp://localhost:61616</connector>
       <connector name="eu-east-1-connector">tcp://localhost:61617</connector>
    </connectors>
    
    <acceptors>
       <acceptor name="netty-acceptor">tcp://localhost:61616</acceptor>
    </acceptors>
    connector name="netty-connector"
    本地代理发送到远程代理的连接器配置。远程代理使用此配置返回本地代理。
    connector name="eu-west-1-connector" , connector name="eu-east-1-connector"
    与远程代理的连接器.本地代理使用这些连接器连接到远程代理,并共享远程代理需要连接到本地代理的配置。
    acceptor name="netty-acceptor"
    本地代理上的接收器,对应于远程代理用来连接到本地代理的连接器。

第 5 章 保护代理

5.1. 保护连接

当代理连接到消息传递客户端或代理连接到其他代理时,您可以使用传输层安全(TLS)保护这些连接。

您可以使用两种 TLS 配置:

  • 单向 TLS,其中仅代理提供证书。这是最常见的配置。
  • 双向(或 mutual)TLS,代理和客户端(或其他代理)都存在证书。

本节中的步骤演示了如何配置单向和双向 TLS。

5.1.1. 配置单向 TLS

以下步骤演示了如何为单向 TLS 配置给定接收器。

  1. 打开 <broker_instance_dir>/etc/broker.xml 配置文件。
  2. 对于给定接收器,添加 sslEnabled 键并将值设为 true。此外,添加 keyStorePathkeyStorePassword 密钥。设置与代理密钥存储对应的值。例如:

    <acceptor name="artemis">tcp://0.0.0.0:61616?sslEnabled=true;keyStorePath=../etc/broker.keystore;keyStorePassword=1234!</acceptor>

5.1.2. 配置双向 TLS

以下步骤演示了如何配置双向 TLS。

先决条件

流程

  1. 打开 <broker_instance_dir>/etc/broker.xml 配置文件。
  2. 对于您之前为单向 TLS 配置的接收器,添加 require ClientAuth 密钥。将值设为 true。例如:

    <acceptor name="artemis">tcp://0.0.0.0:61616?sslEnabled=true;keyStorePath=../etc/broker.keystore;keyStorePassword=1234!;needClientAuth=true</acceptor>
  3. 上一步中的配置假定客户端的证书由受信任的供应商签名。如果客户端的证书 没有 由可信供应商签名(例如,它是自签名的),那么代理需要将客户端的证书导入到信任存储中。在本例中,添加 trustStorePathtrustStorePassword 密钥。设置与代理信任存储对应的值。例如:

    <acceptor name="artemis">tcp://0.0.0.0:61616?sslEnabled=true;keyStorePath=../etc/broker.keystore;keyStorePassword=1234!;needClientAuth=true;trustStorePath=../etc/client.truststore;trustStorePassword=5678!</acceptor>
注意

AMQ 代理支持多个协议,每个协议和平台都有不同的方法来指定 TLS 参数。但是,在使用核心协议(桥接)的客户端时,TLS 参数在连接器 URL 上配置,类似于代理接收器上。

5.1.3. TLS 配置选项

下表显示了所有可用的 TLS 配置选项:

选项备注

sslEnabled

指定是否为连接启用 SSL。必须设为 true 以启用 TLS。默认值为 false

keyStorePath

当用于接收器时:包含代理证书的代理(无论是自签名还是由某一机构签名)上的 TLS 密钥存储路径。

在连接器中使用时:保存客户端证书的 TLS 密钥存储路径。只有在使用双向 TLS 时,这才与连接器相关。虽然您可以在代理中配置这个值,但它会被客户端下载和使用。如果客户端需要使用与代理上设置的不同路径,则可以使用标准的 javax.net.ssl.keyStore 系统属性或 AMQ 特定的 org.apache.activemq.ssl.keyStore 系统属性覆盖 broker 设置。如果客户端上的另一个组件已在使用标准 Java 系统属性,AMQ 特定的系统属性很有用。

keyStorePassword

当用于接收器时:代理上的密钥存储密码。

在连接器中使用时:客户端上密钥存储的密码。只有在使用双向 TLS 时,这才与连接器相关。虽然您可以在代理中配置这个值,但它会被客户端下载和使用。如果客户端需要使用与代理上设置的不同密码,那么它可以使用标准的 javax.net.ssl.keyStorePassword 系统属性或 AMQ 特定的 org.apache.activemq.ssl.keyStorePassword 系统属性覆盖 broker 设置。如果客户端上的另一个组件已在使用标准 Java 系统属性,AMQ 特定的系统属性很有用。

trustStorePath

当用于接收器时:代理上的 TLS 信任存储路径,该代理保存了代理信任的密钥。只有在您使用双向 TLS 时,这才与接收器相关。

在连接器中使用时:在保存客户端信任存储的客户端中 TLS 信任存储的路径。虽然您可以在代理中配置这个值,但它会被客户端下载和使用。如果客户端需要使用与服务器上设置的不同路径不同的路径,那么它可以使用标准的 javax.net.ssl.trustStore 系统属性或 AMQ 特定的 org.apache.activemq.ssl.trustStore 系统属性来覆盖服务器端设置。如果客户端上的另一个组件已在使用标准 Java 系统属性,AMQ 特定的系统属性很有用。

trustStorePassword

当用于接收器时:代理信任存储的密码。只有在您使用双向 TLS 时,这才与接收器相关。

在连接器中使用时:客户端上信任存储的密码。虽然您可以在代理中配置这个值,但它会被客户端下载和使用。如果客户端需要使用与代理上设置的不同密码,则可以使用标准的 javax.net.ssl.trustStorePassword 系统属性或 AMQ 特定的 org.apache.activemq.ssl.trustStorePassword 系统属性覆盖 broker 设置。如果客户端上的另一个组件已在使用标准 Java 系统属性,AMQ 特定的系统属性很有用。

enabledCipherSuites

无论是在接收器还是连接器上使用,都是用于 TLS 通信的密码套件的逗号分隔列表。默认值为 null,这意味着使用 JVM 的默认值。

enabledProtocols

无论是在接收器还是连接器上使用,这是用于 TLS 通信的协议的逗号分隔列表。默认值为 null,这意味着使用 JVM 的默认值。

needClientAuth

此属性仅适用于接收器。它指示客户端连接到需要双向 TLS 的接收器。有效值为 true 或者 false。默认值为 false

5.2. 验证客户端

5.2.1. 客户端验证方法

要在代理中配置客户端身份验证,您可以使用以下方法:

基于用户名和密码的身份验证

使用以下选项之一直接验证用户凭证:

  • 针对存储在代理中的一组本地的属性文件检查凭证。您还可以配置允许有限访问代理的 客户机 帐户,并组合登录模块以支持更复杂的用例。
  • 配置 轻量级目录访问协议(LDAP )登录模块,以根据存储在中央 X.500 目录服务器中的用户数据检查客户端凭据。
基于证书的身份验证
配置双向 传输层安全 (TLS),要求代理和客户端提供用于相互身份验证的证书。管理员还必须配置定义批准的客户端用户和角色的属性文件。这些属性文件存储在代理中。
基于 Kerberos 的身份验证
配置代理以使用 简单身份验证和安全层(SASL)框架中的 GSSAPI 机制为客户端验证 Kerberos 安全 凭证。

下面的部分描述了如何配置基于用户和密码的身份验证。

其它资源

5.2.2. 根据属性文件配置用户和密码身份验证

AMQ Broker 支持灵活的基于角色的安全模型,以根据其地址将安全性应用到队列中。队列绑定到一对一(用于点对点消息)或多对一(用于发布-订阅消息传递)的地址。当消息发送到地址时,代理将查找与该地址绑定的一组队列,并将消息路由到该组队列。

当您需要基本用户和密码身份验证时,请使用 PropertiesLoginModule 定义它。此登录模块根据存储在代理本地的以下配置文件检查用户凭证:

artemis-users.properties
用于定义用户和相应密码
artemis-roles.properties
用于定义角色并将用户分配给这些角色
login.config
用于为用户和密码身份验证和虚拟客户机访问配置登录模块

artemis-users.properties 文件可以包含哈希密码,以提高安全性。

以下部分介绍如何配置:

5.2.2.1. 配置基本用户和密码身份验证

以下步骤演示了如何配置基本用户和密码身份验证。

流程

  1. 打开 <broker_instance_dir>/etc/login.config 配置文件。默认情况下,新 AMQ Broker 7.9 实例中的此文件包括以下行:

    activemq {
       org.apache.activemq.artemis.spi.core.security.jaas.PropertiesLoginModule sufficient
           debug=false
           reload=true
           org.apache.activemq.jaas.properties.user="artemis-users.properties"
           org.apache.activemq.jaas.properties.role="artemis-roles.properties";
             };
    activemq
    配置的别名.
    org.apache.activemq.artemis.spi.core.security.jaas.PropertiesLoginModule
    实施类。
    足够

    指定 PropertiesLoginModule 所需成功级别的标志。您可以设置的值有:

    • 必需 :需要登录模块才能成功。无论成功还是失败,身份验证仍会继续执行在给定别名下配置的登录模块列表。
    • 必需 :需要登录模块才能成功。失败会立即将控制权返回到应用。身份验证不会继续执行在给定别名下配置的登录模块列表。
    • 足够 :成功不需要登录模块。如果成功,控制将返回到应用,并且不会进一步继续身份验证。如果失败,身份验证尝试会结束在给定别名下配置的登录模块列表。
    • 可选 :成功不需要登录模块。无论成功还是失败,身份验证都会继续低于在给定别名下配置的登录模块列表。
    org.apache.activemq.jaas.properties.user
    指定为登录模块实施定义一组用户和密码的属性文件。
    org.apache.activemq.jaas.properties.role
    指定将用户映射到登录模块实施的已定义角色的属性文件。
  2. 打开 <broker_instance_dir>/etc/artemis-users.properties 配置文件。
  3. 添加用户并将密码分配给用户。例如:

    user1=secret
    user2=access
    user3=myPassword
  4. 打开 <broker_instance_dir>/etc/artemis-roles.properties 配置文件。
  5. 将角色名称分配给之前添加到 artemis-users.properties 文件中的用户。例如:

    admin=user1,user2
    developer=user3
  6. 打开 <broker_instance_dir>/etc/bootstrap.xml 配置文件。
  7. 如有必要,将您的安全域别名(在这个实例中为 activemq)添加到该文件中,如下所示:

    <jaas-security domain="activemq"/>

5.2.2.2. 配置客户机访问权限

对于没有登录凭证或凭证失败身份验证的用户,您可以使用 guest 帐户授予对代理的有限访问权限。

您可以使用命令行参数创建启用了客户机访问的代理实例;-- allow-anonymous (反向是 --require-login)。

以下步骤演示了如何配置 guest 访问。

先决条件

流程

  1. 打开之前为基本用户和密码身份验证配置的 <broker_instance_dir> /etc/login.config 配置文件。
  2. 在您之前添加的属性登录模块配置后,添加客户机登录模块配置。例如:

    activemq {
      org.apache.activemq.artemis.spi.core.security.jaas.PropertiesLoginModule sufficient
          debug=true
          org.apache.activemq.jaas.properties.user="artemis-users.properties"
          org.apache.activemq.jaas.properties.role="artemis-roles.properties";
    
      org.apache.activemq.artemis.spi.core.security.jaas.GuestLoginModule sufficient
          debug=true
          org.apache.activemq.jaas.guest.user="guest"
          org.apache.activemq.jaas.guest.role="restricted";
    };
    org.apache.activemq.artemis.spi.core.security.jaas.GuestLoginModule
    实施类。
    org.apache.activemq.jaas.guest.user
    分配给匿名用户的用户名。
    org.apache.activemq.jaas.guest.role
    分配给匿名用户的角色。

根据上述配置,如果用户提供凭证,则激活用户和密码身份验证模块。如果用户没有提供凭证,或者提供的凭证不正确,则激活客户机身份验证。

5.2.2.2.1. 客户机访问示例

以下示例显示了为用例配置 guest 访问,其中只有那些没有凭据的用户才会以 guest 身份登录。在本示例中,观察与前面的配置过程相比,登录模块的顺序已被撤销。此外,附加到属性登录模块的 标志也更改为 必需

activemq {
    org.apache.activemq.artemis.spi.core.security.jaas.GuestLoginModule sufficient
        debug=true
       credentialsInvalidate=true
       org.apache.activemq.jaas.guest.user="guest"
       org.apache.activemq.jaas.guest.role="guests";

    org.apache.activemq.artemis.spi.core.security.jaas.PropertiesLoginModule requisite
        debug=true
        org.apache.activemq.jaas.properties.user="artemis-users.properties"
        org.apache.activemq.jaas.properties.role="artemis-roles.properties";
};

根据上述配置,如果没有提供登录凭据,则激活客户机身份验证模块。

对于此用例,在 guest login 模块的配置中必须将 credentialsInvalidate 选项设置为 true

如果提供了凭据,属性登录模块会被激活。凭据必须是有效的。

其它资源

5.2.3. 配置基于证书的身份验证

Java 身份验证与授权服务 (JAAS)证书登录模块处理使用传输层安全(TLS)的客户端的身份验证和授权。该模块需要使用双向 传输层安全( TLS),并且客户端配置有自己的证书。身份验证在 TLS 握手期间执行,而不是直接由 JAAS 证书登录模块执行。

证书登录模块的角色为:

  • 限制可接受的用户集合。只有相关属性文件中明确列出的用户 区分名称 (DN)才有资格进行身份验证。
  • 将组列表与收到的用户身份关联。这可促进授权。
  • 要求存在传入客户端证书(默认情况下,TLS 层配置为将客户端证书的存在性视为可选)。

证书登录模块将证书 DN 的集合存储在一对无格式文本文件中。文件将用户名和组 ID 列表与各个 DN 相关联。

证书登录模块由 org.apache.activemq.artemis.spi.core.security.jaas.TextFileCertificateLoginModule 类实施。

5.2.3.1. 将代理配置为使用基于证书的身份验证

以下流程演示了如何配置代理以使用基于证书的身份验证。

先决条件

流程

  1. 从之前导入代理密钥存储的用户证书获取使用者可 辨识名称 (DN)。

    1. 将证书从密钥存储文件导出到临时文件。例如:

      keytool -export -file <file_name> -alias broker-localhost -keystore broker.ks -storepass <password>
    2. 打印导出的证书的内容:

      keytool -printcert -file <file_name>

      输出结果类似如下:

      Owner: CN=localhost, OU=broker, O=Unknown, L=Unknown, ST=Unknown, C=Unknown
      Issuer: CN=localhost, OU=broker, O=Unknown, L=Unknown, ST=Unknown, C=Unknown
      Serial number: 4537c82e
      Valid from: Thu Oct 19 19:47:10 BST 2006 until: Wed Jan 17 18:47:10 GMT 2007
      Certificate fingerprints:
               MD5:  3F:6C:0C:89:A8:80:29:CC:F5:2D:DA:5C:D7:3F:AB:37
               SHA1: F0:79:0D:04:38:5A:46:CE:86:E1:8A:20:1F:7B:AB:3A:46:E4:34:5C

      Owner 条目是主题 DN。用于输入主题 DN 的格式取决于您的平台。上面的字符串也可以表示为:

      Owner: `CN=localhost,\ OU=broker,\ O=Unknown,\ L=Unknown,\ ST=Unknown,\ C=Unknown`
  2. 配置基于证书的身份验证.

    1. 打开 <broker_instance_dir>/etc/login.config 配置文件。添加证书登录模块,并引用用户和角色属性文件。例如:

      activemq {
          org.apache.activemq.artemis.spi.core.security.jaas.TextFileCertificateLoginModule
              debug=true
              org.apache.activemq.jaas.textfiledn.user="artemis-users.properties"
              org.apache.activemq.jaas.textfiledn.role="artemis-roles.properties";
      };
      org.apache.activemq.artemis.spi.core.security.jaas.TextFileCertificateLoginModule
      实施类。
      org.apache.activemq.jaas.textfiledn.user
      指定为登录模块实施定义一组用户和密码的属性文件。
      org.apache.activemq.jaas.textfiledn.role
      指定将用户映射到登录模块实施的已定义角色的属性文件。
    2. 打开 <broker_instance_dir>/etc/artemis-users.properties 配置文件。用户及其对应的 DN 在此文件中定义。例如:

      system=CN=system,O=Progress,C=US
      user=CN=humble user,O=Progress,C=US
      guest=CN=anon,O=Progress,C=DE

      例如,根据上述配置,名为 system 的用户映射到 CN=system,O=Progress,C=US 主题 DN。

    3. 打开 <broker_instance_dir>/etc/artemis-roles.properties 配置文件。可用的角色和持有这些角色的用户在此文件中进行了定义。例如:

      admins=system
      users=system,user
      guests=guest

      在上述配置中,对于 users 角色,您可以以逗号分隔的列表列出多个用户。

    4. 确保 bootstrap.xml 中引用了您的安全域别名(在这个示例中是 activemq),如下所示:

      <jaas-security domain="activemq"/>

5.2.3.2. 为 AMQP 客户端配置基于证书的身份验证

使用 Simple Authentication and Security Layer( SASL)EXTERNAL 机制配置参数在连接到代理时配置您的 AQMP 客户端以进行基于证书的身份验证。

代理会以验证任何证书的方式验证 AMQP 客户端的传输层 ( TLS)/安全套接字层 (SSL)证书:

  1. 代理读取客户端的 TLS/SSL 证书,以从证书的主题获取身份。
  2. 证书主体通过证书登录模块映射到代理身份。然后,代理根据用户的角色授权用户。

以下流程演示了如何为 AMQP 客户端配置基于证书的身份验证。要让您的 AMQP 客户端使用基于证书的身份验证,您必须将配置参数添加到客户端用来连接到代理的 URI 中。

先决条件

流程

  1. 打开包含要编辑的 URI 的资源:

    amqps://localhost:5500
  2. 添加参数 sslEnabled=true 来为连接启用 TSL/SSL:

    amqps://localhost:5500?sslEnabled=true
  3. 添加与客户端信任存储和密钥存储相关的参数,以便使用代理进行 TSL/SSL 证书交换:

    amqps://localhost:5500?sslEnabled=true&trustStorePath=<trust_store_path>&trustStorePassword=<trust_store_password>&keyStorePath=<key_store_path>&keyStorePassword=<key_store_password>
  4. 添加参数 saslMechanisms=EXTERNAL,以请求代理使用其 TSL/SSL 证书中找到的身份验证客户端:

    amqps://localhost:5500?sslEnabled=true&trustStorePath=<trust_store_path>&trustStorePassword=<trust_store_password>&keyStorePath=<key_store_path>&keyStorePassword=<key_store_password>&saslMechanisms=EXTERNAL

其它资源

5.3. 授权客户端

5.3.1. 客户端授权方法

要授权客户端在代理上执行操作,如创建和删除地址和队列,以及发送和消耗信息,您可以使用以下方法:

基于用户和角色的授权
为经过身份验证的用户和角色配置代理安全设置。
配置 LDAP 以授权客户端
配置 轻量级目录访问协议(LDAP )登录模块,以处理身份验证和授权。LDAP 登录模块对照中央 X.500 目录服务器中存储的用户数据检查传入的凭据,并根据用户角色设置权限。
将 Kerberos 配置为授权客户端
配置 Java 身份验证与授权服务 (JAAS) Krb5LoginModule 登录模块,以将凭证传递给 PropertiesLoginModuleLDAPLoginModule 登录模块,该模块会将 Kerberos 身份验证的用户映射到 AMQ Broker 角色。

5.3.2. 配置基于用户和角色的授权

5.3.2.1. 设置权限

通过 broker.xml 配置文件中的 <security-setting> 元素针对队列(基于其地址)定义权限。您可以在配置文件的 <security- settings> 元素中定义多个 <security-setting > 实例。您可以指定完全地址匹配,也可以使用数字符号(#)和星号(*)通配符字符定义通配符匹配。

可以为与地址匹配的一组队列授予不同的权限。下表中显示了这些权限。

允许用户…​使用此参数…

创建地址

createAddress

删除地址

deleteAddress

在匹配地址下创建一个持久队列

createDurableQueue

删除匹配地址下的持久队列

deleteDurableQueue

在匹配地址下创建不可重复的队列

createNonDurableQueue

删除匹配地址下的不可重复队列

deleteNonDurableQueue

发送一条消息到匹配地址

send

使用绑定到匹配地址的队列中的消息

使用

通过将管理消息发送到管理地址来调用管理操作

管理

浏览绑定到匹配地址的队列

browse

对于每个权限,您可以指定一个被授予权限的角色列表。如果给定用户具有任何角色,则将被授予他们这一组地址的权限。

下面的部分显示了一些权限配置示例。

5.3.2.1.1. 为单个地址配置消息生产环境

以下流程演示了如何为单个地址配置消息生产权限。

流程

  1. 打开 <broker_instance_dir>/etc/broker.xml 配置文件。
  2. <security- settings> 元素中添加单个 <security-setting > 元素。对于 match 键,指定一个地址。例如:

    <security-settings>
        <security-setting match="my.destination">
            <permission type="send" roles="producer"/>
        </security-setting>
    </security-settings>

    根据上述配置,producer 角色的成员具有地址 my.destination发送 权限。

5.3.2.1.2. 为单个地址配置消息消耗

以下步骤演示了如何为单个地址配置消息使用权限。

流程

  1. 打开 <broker_instance_dir>/etc/broker.xml 配置文件。
  2. <security- settings> 元素中添加单个 <security-setting > 元素。对于 match 键,指定一个地址。例如:

    <security-settings>
        <security-setting match="my.destination">
            <permission type="consume" roles="consumer"/>
        </security-setting>
    </security-settings>

    根据上述配置,users 角色 的成员具有地址 my.destination 的消耗 权限

5.3.2.1.3. 在所有地址上配置完整访问权限

以下步骤演示了如何配置对所有地址和相关队列的完整访问权限。

流程

  1. 打开 <broker_instance_dir>/etc/broker.xml 配置文件。
  2. <security- settings> 元素中添加单个 <security-setting > 元素。对于 match 键,若要配置 对所有 地址的访问,请指定数字符号(#)通配符。例如:

    <security-settings>
        <security-setting match="#">
            <permission type="createDurableQueue" roles="guest"/>
            <permission type="deleteDurableQueue" roles="guest"/>
            <permission type="createNonDurableQueue" roles="guest"/>
            <permission type="deleteNonDurableQueue" roles="guest"/>
            <permission type="createAddress" roles="guest"/>
            <permission type="deleteAddress" roles="guest"/>
            <permission type="send" roles="guest"/>
            <permission type="browse" roles="guest"/>
            <permission type="consume" roles="guest"/>
            <permission type="manage" roles="guest"/>
        </security-setting>
    </security-settings>

    根据上述配置,将所有队列上的 guest 角色成员授予所有权限。这在将匿名身份验证配置为为每个用户分配 guest 角色的开发场景中非常有用。

其它资源

5.3.2.1.4. 配置多个安全设置

以下示例步骤演示了如何单独为匹配地址集配置多个安全设置。这与本节前面的示例相反,它演示了如何授予 对所有 地址 的完整 访问权限。

  1. 打开 <broker_instance_dir>/etc/broker.xml 配置文件。
  2. <security- settings> 元素中添加单个 <security-setting > 元素。对于 match 键, 包含数字符号(#)通配符字符,以将设置应用到匹配的地址集合。例如:

    <security-setting match="globalqueues.europe.#">
       <permission type="createDurableQueue" roles="admin"/>
       <permission type="deleteDurableQueue" roles="admin"/>
       <permission type="createNonDurableQueue" roles="admin, guest, europe-users"/>
       <permission type="deleteNonDurableQueue" roles="admin, guest, europe-users"/>
       <permission type="send" roles="admin, europe-users"/>
       <permission type="consume" roles="admin, europe-users"/>
    </security-setting>
    match=globalqueues.europe.#
    数字符号(#)通配符由代理解释为"任何词语序列"。词语用句点(.)分隔。在本例中,安全设置适用于以字符串 globalqueues.europe 开头的任何地址。
    permission type="createDurableQueue"
    只有具有 admin 角色的用户 才能创建或删除绑定到以字符串 globalqueues.europe 开头的地址的持久队列。
    permission type="createNonDurableQueue"
    任何具有 adminguesteurope-users 角色的用户 都可以创建或删除绑定到以字符串 globalqueues.europe 开头的地址的临时队列。
    permission type="send"
    任何具有 admineurope-users 角色的用户都可以发送消息到绑定至以字符串 globalqueues.europe 开头的地址的队列。
    permission type="consume"
    任何具有 admineurope-users 角色的用户 都可以使用绑定到以字符串 globalqueues.europe 开头的地址的队列中的消息。
  3. (可选)要将不同的安全设置应用到更严格的地址集合,请添加另一个 <security-setting> 元素。对于 match 键,请指定一个更具体的文本字符串。例如:

    <security-setting match="globalqueues.europe.orders.#">
       <permission type="send" roles="europe-users"/>
       <permission type="consume" roles="europe-users"/>
    </security-setting>

    在第二个 security-setting 元素中,全局queues.europe.orders.# 匹配比第一个 security-setting 元素中指定的 globalqueues.europe.# 匹配更为具体。对于匹配 globalqueues.europe.orders.# 的任何地址,权限 createDurableQueue,deleteDurableQueue,createNonDurableQueue,deleteNonDurableQueue 继承自 文件中的第一个 security-setting 元素。例如,对于地址 globalqueues.europe.orders.plastics,存在的唯一权限会为 europe-users 角色 发送 和使用

    因此,由于一个 security-setting 块中指定的权限不会被其他人继承,您只需不指定这些权限即可有效地拒绝更具体的 security-setting 块中的权限。

5.3.2.1.5. 使用用户配置队列

自动创建队列时,将为队列分配连接的客户端的用户名。此用户名作为元数据包含在队列中。该名称由 JMX 和 AMQ Broker 管理控制台公开。

以下流程演示了如何将用户名添加到您在代理配置中手动定义的队列中。

流程

  1. 打开 <broker_instance_dir>/etc/broker.xml 配置文件。
  2. 对于给定队列,添加 用户 密钥。分配一个值。例如:

    <address name="ExampleQueue">
        <anycast>
           <queue name="ExampleQueue" user="admin"/>
        </anycast>
    </address>

    根据上述配置,将 admin 用户分配到队列 ExampleQueue

注意
  • 在队列中配置用户不会更改该队列的任何安全语义,它仅用于该队列上的元数据。
  • 用户之间的映射和他们拥有的角色之间的映射由名为 安全管理器 的组件处理。安全管理器从存储在代理中的属性文件中读取用户凭证。默认情况下,AMQ Broker 使用 org.apache.activemq.artemis.spi.core.security.ActiveMQJAASSecurityManager 安全管理器。此默认安全管理器提供与 JAAS 和红帽 JBoss 企业应用平台(JBoss EAP)安全性的集成。

    要了解如何使用 自定义 安全管理器,请参阅 第 5.6.2 节 “指定自定义安全管理器”

5.3.2.2. 配置基于角色的访问控制

基于角色的访问控制 (RBAC)用于限制对 MBean 属性和方法的访问。RBAC 可让管理员根据角色为所有用户(如 Web 控制台、管理界面和核心消息等)授予正确的访问权限。

5.3.2.2.1. 配置基于角色的访问

以下示例步骤演示了如何将角色映射到特定 MBeans 及其属性和方法。

先决条件

流程

  1. 打开 <broker_instance_dir>/etc/management.xml 配置文件。
  2. 搜索 role-access 元素并编辑配置。例如:

    <role-access>
        <match domain="org.apache.activemq.artemis">
           <access method="list*" roles="view,update,amq"/>
           <access method="get*" roles="view,update,amq"/>
           <access method="is*" roles="view,update,amq"/>
           <access method="set*" roles="update,amq"/>
           <access method="*" roles="amq"/>
        </match>
    </role-access>
    • 在这种情况下,匹配将应用到域名为 org.apache.activemq.apache 的任何 MBean 属性。
    • 对匹配的 MBean 属性的 view更新或 amq 角色的访问由以下哪个 列表控制:*get*set*是*,以及您将角色添加到的 * 访问方法。method="*" (wildcard)语法用作指定配置中没有列出的所有其他方法的概括性方法。配置中的每种访问方法将转换为 MBean 方法调用。
    • 调用的 MBean 方法与配置中列出的方法匹配。例如,如果您调用了带 org.apache.activemq.artemis 域的 MBean 上名为 listMessages 的方法,代理会将访问权限重新匹配回 列表 方法配置中定义的角色。
    • 您还可以使用完整 MBean 方法名称来配置访问权限。例如:

      <access method="listMessages" roles="view,update,amq"/>
  3. 启动或重启代理。

    • Linux: <broker_instance_dir>/bin/artemis run
    • 在 Windows 上 :<broker_instance_dir>\bin\artemis-service.exe start

您还可以通过添加与 MBean 属性匹配的 key 属性来匹配域中的特定 MBean。

5.3.2.2.2. 基于角色的访问示例

本节演示了以下应用基于角色的访问控制的示例:

下例演示了如何使用 key 属性将 角色映射到指定域中的所有队列。

<match domain="org.apache.activemq.artemis" key="subcomponent=queues">
   <access method="list*" roles="view,update,amq"/>
   <access method="get*" roles="view,update,amq"/>
   <access method="is*" roles="view,update,amq"/>
   <access method="set*" roles="update,amq"/>
   <access method="*" roles="amq"/>
</match>

下例演示了如何使用 key 属性将 角色映射到特定指定队列。在本例中,指定队列为 exampleQueue

<match domain="org.apache.activemq.artemis" key="queue=exampleQueue">
   <access method="list*" roles="view,update,amq"/>
   <access method="get*" roles="view,update,amq"/>
   <access method="is*" roles="view,update,amq"/>
   <access method="set*" roles="update,amq"/>
   <access method="*" roles="amq"/>
</match>

下例演示了如何将角色映射到名称包含指定前缀的每个队列。在本例中,使用星号(*)通配符运算符匹配以前缀 example 开头的所有队列名称。

<match domain="org.apache.activemq.artemis" key="queue=example*">
   <access method="list*" roles="view,update,amq"/>
   <access method="get*" roles="view,update,amq"/>
   <access method="is*" roles="view,update,amq"/>
   <access method="set*" roles="update,amq"/>
   <access method="*" roles="amq"/>
</match>

您可能希望针对同一属性的不同组映射角色(例如,不同的队列集)。在这种情况下,您可以在配置文件中包含多个 匹配 元素。但是,同一域中可以有多个匹配项。

例如,考虑配置如下的两个 <match> 元素

<match domain="org.apache.activemq.artemis" key="queue=example*">

<match domain="org.apache.activemq.artemis" key="queue=example.sub*">

基于此配置,org.apache.activemq .artemis 域中名为 example.sub. queue 的队列与两个通配符键表达式都匹配。因此,代理需要一个优先级方案来确定映射到队列的角色集合、第一个 匹配 元素中指定的角色集合,或者第二个 匹配 元素中指定的角色。

当同一域中有多个匹配项时,代理在映射角色时使用以下优先级方案:

  • 完全匹配项优先于通配符匹配
  • 通配符匹配时间超过较短的通配符匹配

在本例中,由于较长的通配符表达式与 example. sub.queue 的队列名称匹配,所以代理会应用在第二个 <match> 元素中配置的角色映射。

注意

default-access 元素是每个不使用 role-access 或 whitelist 配置来处理的每个方法调用的 catch- all 元素。default-accessrole-access 元素具有同样的 匹配 元素语义。

5.3.2.2.3. 配置白名单元素

白名单 是一组不需要用户身份验证的预批准域或 MBean。您可以提供必须绕过身份验证的域列表或 MBeans 列表。例如,您可以使用白名单指定要运行 AMQ Broker 管理控制台的任何 MBean。

以下示例流程演示了如何配置 白名单 元素。

流程

  1. 打开 <broker_instance_dir>/etc/management.xml 配置文件。
  2. 搜索 白名单 元素并编辑配置:

    <whitelist>
       <entry domain="hawtio"/>
    </whitelist>

    在此示例中,任何带 hawtio 域的 MBean 都可在不通过身份验证的情况下进行访问。您还可以使用 <entry domain="hawtio" 键="type=*"/> 格式的 通配符条目来匹配 MBean 属性。

  3. 启动或重启代理。

    • Linux: <broker_instance_dir>/bin/artemis run
    • 在 Windows 上 :<broker_instance_dir>\bin\artemis-service.exe start

5.3.2.3. 设置资源限制

有时,设置特定用户可执行的操作限制(超出与授权和身份验证相关的普通安全设置)会很有帮助。

5.3.2.3.1. 配置连接和队列限制

以下示例步骤演示了如何限制用户可以创建的连接和队列数量。

  1. 打开 <broker_instance_dir>/etc/broker.xml 配置文件。
  2. 添加 resource-limit-settings 元素。指定 max-connectionsmax-queues 的值。例如:

    <resource-limit-settings>
       <resource-limit-setting match="myUser">
          <max-connections>5</max-connections>
          <max-queues>3</max-queues>
       </resource-limit-setting>
    </resource-limit-settings>
    max-connections
    定义匹配用户可以与代理进行的连接数量。默认值为 -1,这意味着没有限制。
    max-queues
    定义匹配用户可以创建的队列数量。默认值为 -1,这意味着没有限制。
注意

与您可以在代理配置的 address-setting 元素中指定的 match 字符串不同,您在 resource-limit-settings 中指定的 match 字符串 无法使用 通配符语法。相反,match 字符串定义将资源限制设置应用到的特定用户。

5.4. 使用 LDAP 进行身份验证和授权

LDAP 登录模块根据中央 X.500 目录服务器中存储的用户数据检查传入的凭据,从而启用身份验证和授权。它由 org.apache.activemq.artemis.spi.core.security.jaas.LDAPLoginModule 实施。

5.4.1. 配置 LDAP 以验证客户端

以下示例步骤演示了如何使用 LDAP 验证客户端。

流程

  1. 打开 <broker_instance_dir>/etc/broker.xml 配置文件。
  2. security-settings 元素内,添加 security-setting 元素来配置权限。例如:

    <security-settings>
        <security-setting match="#">
            <permission type="createDurableQueue" roles="user"/>
            <permission type="deleteDurableQueue" roles="user"/>
            <permission type="createNonDurableQueue" roles="user"/>
            <permission type="deleteNonDurableQueue" roles="user"/>
            <permission type="send" roles="user"/>
            <permission type="consume" roles="user"/>
        </security-setting>
    </security-settings>

    上述配置 将所有 队列的特定权限分配给 用户 角色的成员。

  3. 打开 <broker_instance_dir>/etc/login.config 文件。
  4. 根据您使用的目录服务,配置 LDAP 登录模块。

    1. 如果您使用 Microsoft Active Directory 目录服务,请添加类似此示例的配置:

      activemq {
        org.apache.activemq.artemis.spi.core.security.jaas.LDAPLoginModule required
           debug=true
           initialContextFactory=com.sun.jndi.ldap.LdapCtxFactory
           connectionURL="LDAP://localhost:389"
           connectionUsername="CN=Administrator,CN=Users,OU=System,DC=example,DC=com"
           connectionPassword=redhat.123
           connectionProtocol=s
           connectionTimeout="5000"
           authentication=simple
           userBase="dc=example,dc=com"
           userSearchMatching="(CN={0})"
           userSearchSubtree=true
           readTimeout="5000"
           roleBase="dc=example,dc=com"
           roleName=cn
           roleSearchMatching="(member={0})"
           roleSearchSubtree=true
           ;
      };
      注意

      如果您使用的是 Microsoft Active Directory,并且您需要为 connectionUsername 属性指定的值包含一个空格(如 OU=System Accounts),则必须将值括在一对双引号("")并使用反斜杠(\)来转义对中的每个双引号。例如, connectionUsername="CN=Administrator,CN=Users,OU=\"System Accounts\",DC=example,DC=com"。

    2. 如果使用 ApacheDS 目录服务,请添加类似以下示例的配置:

      activemq {
        org.apache.activemq.artemis.spi.core.security.jaas.LDAPLoginModule required
           debug=true
           initialContextFactory=com.sun.jndi.ldap.LdapCtxFactory
           connectionURL="ldap://localhost:10389"
           connectionUsername="uid=admin,ou=system"
           connectionPassword=secret
           connectionProtocol=s
           connectionTimeout=5000
           authentication=simple
           userBase="dc=example,dc=com"
           userSearchMatching="(uid={0})"
           userSearchSubtree=true
           userRoleName=
           readTimeout=5000
           roleBase="dc=example,dc=com"
           roleName=cn
           roleSearchMatching="(member={0})"
           roleSearchSubtree=true
           ;
      };
      debug
      打开调试(true)或 off(false)。默认值为 false
      initialContextFactory
      必须始终设置为 com.sun.jndi.ldap.LdapCtxFactory
      connectionURL
      使用 LDAP URL __<ldap://Host:Port> 的目录服务器的位置。您可以选择性地通过添加正斜杠 /,后面跟目录树中特定节点的 DN 来验证这个 URL。Apache DS 的默认端口为 10389,而 Microsoft AD 的默认值为 389
      connectionUsername
      打开与目录服务器连接的用户的可分辨名称(DN)。例如,uid=admin,ou=system。目录服务器通常需要客户端显示用户名/密码凭据才能打开连接。
      connectionPassword
      connectionUsername 中的 DN 匹配的密码。在目录服务器中,在 Directory Information Tree (DIT)中,密码通常作为 userPassword 属性存储在对应的目录条目中。
      connectionProtocol
      任何值都受支持,但实际上未使用。必须显式设置这个选项,因为它没有默认值。
      connectionTimeout

      指定代理可以花费的最长时间(毫秒)连接到目录服务器。如果代理无法在此时间内连接到该目录,它会中止连接尝试。如果为此属性指定零或以下值,则改为使用底层 TCP 协议的超时值。如果没有指定值,代理会无限期地等待建立连接,或者底层网络超时。

      当为连接请求连接池时,此属性指定代理在已达到最大池大小并且正在使用池中所有连接时等待连接的最长时间。如果您指定了零或以下值,代理会无限期等待连接可用。否则,代理会在达到最长等待时间时中止连接尝试。

      身份验证
      指定绑定到 LDAP 服务器时使用的身份验证方法。此参数可以设置为 simple (需要用户名和密码)或 none (允许匿名访问)。
      userBase
      选择 DIT 的特定子树以搜索用户条目。子树由 DN 指定,它指定子树的基节点。例如,通过将这个选项设置为 ou=User,ou=ActiveMQ,ou=system,搜索用户条目仅限于 ou=User,ou=ActiveMQ,ou=system node 下的子树。
      userSearchMatching
      指定 LDAP 搜索过滤器,应用到 userBase 选择的子树。如需更多信息,请参阅以下 第 5.4.1.1 节 “搜索匹配参数” 部分。
      userSearchSubtree
      指定用户条目的搜索深度,相对于 userBase 指定的节点。此选项是一个布尔值。指定值 false 表示搜索尝试匹配 userBase 节点的一个子条目(映射到 javax.naming.directory.SearchControls.ONELEVEL_SCOPE)。指定值 true 表示搜索会尝试匹配属于 userBase 节点 子树 的任何条目(映射到 javax.naming.directory.SearchControls.SUBTREE_SCOPE)。
      userRoleName
      用户条目的属性名称,其中包含用户的角色名称列表。角色名称由代理的授权插件解释为组名称。如果省略此选项,则不会从用户条目中提取角色名称。
      readTimeout
      指定代理可以等待从目录服务器接收到 LDAP 请求的最大时间(以毫秒为单位)。如果代理没有收到来自目录服务器的响应,代理会中止请求。如果您指定的值为零或以下值,或者您没有指定值,代理会无限期地等待从目录服务器响应到 LDAP 请求。
      roleBase
      如果角色数据存储直接存储在目录服务器中,则可以使用角色选项的组合(roleBase、roleBase、roleSearchMatching、roleSearchSubtreeroleName)作为指定 userRoleName 选项的替代选择(或补充)。此选项选择 DIT 的特定子树来搜索角色/组条目。子树由 DN 指定,它指定子树的基节点。例如,通过将此选项设置为 ou=Group,ou=ActiveMQ,ou=system,搜索 role/group 条目仅限于 ou=Group,ou=ActiveMQ,ou=system 节点下面的子树。
      roleName
      包含角色/组名称的角色条目的属性类型(如 C、O、OU 等)。如果省略此选项,则有效禁用角色搜索功能。
      roleSearchMatching
      指定 LDAP 搜索过滤器,应用到 roleBase 选择的子树。如需更多信息,请参阅以下 第 5.4.1.1 节 “搜索匹配参数” 部分。
      roleSearchSubtree

      指定角色条目的搜索深度,相对于 roleBase 指定的节点。如果设置为 false (默认值),则搜索将尝试匹配 roleBase 节点的子条目之一(映射到 javax.naming.directory.SearchControls.ONELEVEL_SCOPE)。如果为 true,它将尝试匹配属于 roleBase 节点子树的任何条目(映射到 javax.naming.directory.SearchControls.SUBTREE_SCOPE)。

      注意

      Apache DS 使用 DN 路径的 OID 部分。Microsoft Active Directory 使用 CN 部分。例如,您可以在 Apache DS 中使用 DN 路径,如 as oid=testuser,dc=example,dc=com,而您可能在 Microsoft Active Directory 中使用 DN 路径,如 cn=testuser,dc=example,dc=com

  5. 启动或重启代理(服务或进程)。

5.4.1.1. 搜索匹配参数

userSearchMatching

在传递到 LDAP 搜索操作之前,此配置参数中提供的字符串值受到字符串替换的影响,具体由 java.text.MessageFormat 类实施。

这意味着,特殊字符串 {0} 替换为用户名,如从传入的客户端凭证中提取时所示。替换后,字符串解释为 LDAP 搜索过滤器(语法由 IETF 标准 RFC 2254 定义)。

例如,如果将此选项设置为 (uid={0}),收到的用户名是 jdoe,则搜索过滤器会在字符串替换 后变成(uid=jdoe )。

如果生成的搜索过滤器应用到用户基础选择的子树 ou=User,ou=ActiveMQ,ou=system,它将与条目, uid=jdoe,ou=User,ou=ActiveMQ,ou=system 匹配。

roleSearchMatching

这的工作方式与 userSearchMatching 选项类似,但它支持两个替换字符串。

替换字符串 {0} 替换匹配的用户条目的完整 DN(即用户搜索的结果)。例如,对于用户 jdoe,替换的字符串可以是 uid=jdoe,ou=User,ou=ActiveMQ,ou=system.

替换字符串 {1} 替换收到的用户名。例如,jdoe

如果此选项设置为 (member=uid={1}),收到的用户名为 jdoe,则搜索过滤器会在字符串替换后(假设 ApacheDS 搜索过滤器语法 )后变为(member=uid=jdoe )。

如果生成的搜索过滤器应用到角色基础 ou=Group,ou=ActiveMQ,ou=system 所选的子树,它将匹配 member 属性等于 uid=jdoe 的所有角色条目( member 属性的值是 DN)。

必须始终设置这个选项,即使角色搜索被禁用,因为它没有默认值。如果使用 OpenLDAP,搜索过滤器的语法为 (member:=uid=jdoe)。

其它资源

5.4.2. 配置 LDAP 授权

LegacyLDAPSecuritySettingPlugin 安全设置插件读取之前由 LDAPAuthorizationMap 和 缓存LDAPAuthorizationMap 在 AMQ 6 中处理的安全信息,并将这些信息转换为对应的 AMQ 7 安全设置(如果可能)。

AMQ 6 和 AMQ 7 中的代理的安全实施与 AMQ 7 中的安全实施不完全匹配。因此,插件会在两个版本之间执行一些转换,以实现近乎相同的功能。

以下示例演示了如何配置插件。

流程

  1. 打开 <broker_instance_dir>/etc/broker.xml 配置文件。
  2. security-settings 元素内,添加 security-setting-plugin 元素。例如:

    <security-settings>
        <security-setting-plugin class-name="org.apache.activemq.artemis.core.server.impl.LegacyLDAPSecuritySettingPlugin">
            <setting name="initialContextFactory" value="com.sun.jndi.ldap.LdapCtxFactory"/>
            <setting name="connectionURL" value="ldap://localhost:1024"/>`ou=destinations,o=ActiveMQ,ou=system`
            <setting name="connectionUsername" value="uid=admin,ou=system"/>
            <setting name="connectionPassword" value="secret"/>
            <setting name="connectionProtocol" value="s"/>
            <setting name="authentication" value="simple"/>
        </security-setting-plugin>
    </security-settings>
    class-name
    其实施为 org.apache.activemq.artemis.core.server.impl.LegacyLDAPSecuritySettingPlugin
    initialContextFactory
    用于连接到 LDAP 的初始上下文工厂。必须始终设置为 com.sun.jndi.ldap.LdapCtxFactory (即默认值)。
    connectionURL
    使用 LDAP URL <ldap://Host:Port> 指定目录服务器的位置。您可以选择添加正斜杠 /,后面跟目录树中特定节点的可分辨名称(DN)来验证这个 URL。例如: ldap://ldapserver:10389/ou=system。默认值为 ldap://localhost:1024
    connectionUsername
    打开与目录服务器的连接的用户的 DN。例如,uid=admin,ou=system。目录服务器通常需要客户端显示用户名/密码凭据才能打开连接。
    connectionPassword
    connectionUsername 中的 DN 匹配的密码。在目录服务器中,在 Directory Information Tree (DIT)中,密码通常作为 userPassword 属性存储在对应的目录条目中。
    connectionProtocol
    当前未使用.以后,此选项可能允许您选择连接到目录服务器的安全套接字层(SSL)。必须显式设置这个选项,因为它没有默认值。
    身份验证

    指定绑定到 LDAP 服务器时使用的身份验证方法。这个参数的有效值为 simple (用户名和密码)或 none (匿名)。默认值为 simple

    注意

    不支持 简单的身份验证和安全层(SASL)身份验证。

以上配置示例中未显示的其他设置有:

destinationBase
指定子项为所有目标提供权限的节点的 DN。在这种情况下,DN 是一个字面值(即,不对属性值执行字符串替换)。例如,此属性的典型值为 ou=destinations,o=ActiveMQ,ou=system The defaults value is ou=destinations,o=ActiveMQ,ou=system
filter
指定 LDAP 搜索过滤器,用于查找任何目的地的权限。搜索过滤器会尝试匹配队列或主题节点的子项或子代之一。默认值为 (cn=*)
roleAttribute
指定与过滤器匹配的节点属性,该 过滤器 的值是角色的 DN。默认值为 uniqueMember
adminPermissionValue
指定与 admin 权限匹配的值。默认值为 admin
readPermissionValue
指定与 读取 权限匹配的值。默认值为 read
writePermissionValue
指定与 写入权限 匹配的值。默认值为 write
enableListener
指定是否启用自动接收 LDAP 服务器中进行的更新的监听程序,并实时更新代理的授权配置。默认值为 true
mapAdminToManage

指定是否将传统(即 AMQ 6) 管理 权限 映射到 AMQ 7 管理 权限。请参阅下表中的映射语义详情。默认值为 false

LDAP 中定义的队列或主题名称充当安全设置的"匹配",权限值从 AMQ 6 类型映射到 AMQ 7 类型,并且该角色按原样映射。由于 LDAP 中定义的队列或主题名称充当安全设置的匹配项,因此安全性设置可能无法如预期应用到 JMS 目的地。这是因为 AMQ 7 始终为 JMS 目的地添加前缀 "jms.queue." 或 "jms.topic."(根据需要)。

AMQ 6 的权限类型有三种 :读取写入管理员。ActiveMQ 网站描述了这些权限类型; 安全性.

AMQ 7 有以下权限类型:

  • createAddress
  • deleteAddress
  • createDurableQueue
  • deleteDurableQueue
  • createNonDurableQueue
  • deleteNonDurableQueue
  • send
  • 使用
  • 管理
  • browse

    下表显示了安全设置插件如何将 AMQ 6 权限类型映射到 AMQ 7 权限类型:

    AMQ 6 权限类型AMQ 7 权限类型

    读取

    使用、浏览

    write

    send

    admin

    createAddress, deleteAddress, createDurableQueue, deleteDurableQueue, createNonDurableQueue, deleteNonDurableQueue, manage(如果 mapAdminToManage 设为 true

    如下所述,在一些情况下,插件在 AMQ 6 和 AMQ 7 权限类型之间执行一些转换以实现等效:

    • 默认情况下,映射不包括 AMQ 7 管理 权限类型,因为 AMQ 6 中没有类似权限类型。但是,如果 mapAdminToManage 设为 true,则插件会将 AMQ 6 admin 权限映射到 AMQ 7 manage 权限。
    • AMQ 6 中的 admin 权限类型确定代理是否自动创建目的地(如果目标不存在),并且用户向其发送消息。如果用户有权向目的地发送消息,AMQ 7 会自动允许自动创建目的地。因此,默认情况下,插件会将旧 管理 权限映射到上面显示的 AMQ 7 权限。如果 mapAdminToManage 设为 true,该插件还会将 AMQ 6 admin 权限映射到 AMQ 7 manage 权限。
allowQueueAdminOnRead

是否要将传统的读取权限映射到 createDurableQueue、createNonDurableQueue 和 deleteDurableQueue 权限,以便 JMS 客户端能够创建持久且不可更改的订阅,而无需 admin 权限。AMQ 6 中允许这样做。默认值为 false。

下表显示了当 allowQueueAdminOnReadtrue 时,安全设置插件如何将 AMQ 6 权限类型映射到 AMQ 7 权限类型:

AMQ 6 权限类型AMQ 7 权限类型

读取

consume, browse, createDurableQueue, createNonDurableQueue, deleteDurableQueue

write

send

admin

createAddress, deleteAddress, deleteNonDurableQueue, manage(如果 mapAdminToManage 设置为 true

5.4.3. 在 login.config 文件中加密密码

由于组织经常与 LDAP 安全地存储数据,因此 login.config 文件可以包含代理与组织的 LDAP 服务器通信所需的配置。此配置文件通常包含用于登录 LDAP 服务器的密码,因此需要加密此密码。

先决条件

流程

以下流程演示了如何屏蔽 <broker_instance_dir>/etc/login.config 文件中的 connectionPassword 参数的值。

  1. 在命令提示符后,使用 掩码 程序加密密码:

    $ <broker_instance_dir>/bin/artemis mask <password>
    result: 3a34fd21b82bf2a822fa49a8d8fa115d
  2. 打开 <broker_instance_dir>/etc/login.config 文件。找到 connectionPassword 参数:

    connectionPassword = <password>
  3. 将纯文本密码替换为加密值:

    connectionPassword = 3a34fd21b82bf2a822fa49a8d8fa115d
  4. 使用标识符 "ENC()" 括起加密的值:

    connectionPassword = "ENC(3a34fd21b82bf2a822fa49a8d8fa115d)"

login.config 文件现在包含一个屏蔽的密码。因为密码用 "ENC()" 标识符打包,AMQ Broker 会在使用密码前对其进行解密。

其它资源

5.4.4. 映射外部角色

您可以将角色从外部身份验证提供商(如 LDAP)映射到代理内部使用的角色。

要映射外部角色,请在 broker.xml 配置文件 的 security-settings 元素中创建 role-mapping 条目。例如:

<security-settings>
...
    <role-mapping from="cn=admins,ou=Group,ou=ActiveMQ,ou=system" to="my-admin-role"/>
    <role-mapping from="cn=users,ou=Group,ou=ActiveMQ,ou=system" to="my-user-role"/>
</security-settings>
注意
  • 角色映射是可选的。这意味着用户将保留原始角色和新分配的角色。
  • 角色映射仅影响授权队列访问的角色,不提供启用 Web 控制台访问的方法。

5.5. 使用 Kerberos 进行身份验证和授权

使用 AMQP 协议发送和接收消息时,客户端可以通过 简单身份验证和安全层(SASL)框架中的 GSSAPI 机制发送 AMQ Broker 验证的 Kerberos 安全 凭证。Kerberos 凭据也可以用于授权,方法是将经过身份验证的用户映射到 LDAP 目录或基于文本的属性文件中配置的分配角色。

您可以使用 SASL 与 传输层安全( TLS)一起保护消息传递应用程序。SASL 提供用户身份验证,TLS 提供数据完整性。

重要

以下步骤演示了如何为身份验证和授权配置 Kerberos。

5.5.1. 配置网络连接以使用 Kerberos

AMQ 代理使用 简单身份验证和安全层(SASL)框架中的 GSSAPI 机制与 Kerberos 安全 凭证集成。要在 AMQ Broker 中使用 Kerberos,每个接受者验证或授权使用 Kerberos 凭证的客户端都必须配置为使用 GSSAPI 机制。

以下步骤演示了如何配置接收器以使用 Kerberos。

先决条件

  • 您必须部署和配置 Kerberos 基础架构,然后才能 AMQ Broker 验证和授权 Kerberos 凭证。

流程

  1. 停止代理。

    1. 在 Linux 中:

      <broker_instance_dir>/bin/artemis stop
    2. 在 Windows 中:

      <broker_instance_dir>\bin\artemis-service.exe stop
  2. 打开 <broker_instance_dir>/etc/broker.xml 配置文件。
  3. 将 name-value 对 saslMechanisms=GSSAPI 添加到接收器的 URL 的查询字符串

    <acceptor name="amqp">
      tcp://0.0.0.0:5672?protocols=AMQP;saslMechanisms=GSSAPI
    </acceptor>

    上述配置意味着接收器在验证 Kerberos 凭据时使用 GSSAPI 机制。

  4. (可选) 也支持 PLAINANONYMOUS SASL 机制。要指定多个机制,请使用逗号分隔列表。例如:

    <acceptor name="amqp">
      tcp://0.0.0.0:5672?protocols=AMQP;saslMechanisms=GSSAPI,PLAIN
    </acceptor>

    结果是一个同时使用 GSSAPIPLAIN SASL 机制的接收器。

  5. 启动代理。

    1. 在 Linux 中:

      <broker_instance_dir>/bin/artemis run
    2. 在 Windows 中:

      <broker_instance_dir>\bin\artemis-service.exe start

其它资源

5.5.2. 使用 Kerberos 凭证验证客户端

AMQ Broker 支持使用 简单身份验证和安全层(SASL)框架中的 GSSAPI 机制的 AMQP 连接的 Kerberos 身份验证

代理通过使用 Java 身份验证与授权服务 (JAAS)获取其 Kerberos 接收器凭证。Java 安装中包含的 JAAS 库打包为登录模块 Krb5LoginModule,用于验证 Kerberos 凭证。有关 Krb5LoginModule 的更多信息,请参阅来自您的 Java 厂商的文档。例如,Oracle 在其 Java 8 文档中 提供有关其 Krb5LoginModule 登录模块的信息。

先决条件

流程

  1. 停止代理。

    1. 在 Linux 中:

      <broker_instance_dir>/bin/artemis stop
    2. 在 Windows 中:

      <broker_instance_dir>\bin\artemis-service.exe stop
  2. 打开 <broker_instance_dir>/etc/login.config 配置文件。
  3. 添加名为 amqp-sasl-gssapi 的配置范围。以下示例显示了 JDK 的 Oracle 和 OpenJDK 版本中找到的 Krb5LoginModule 的配置。

    amqp-sasl-gssapi {
        com.sun.security.auth.module.Krb5LoginModule required
        isInitiator=false
        storeKey=true
        useKeyTab=true
        principal="amqp/my_broker_host@example.com"
        debug=true;
    };
    amqp-sasl-gssapi
    默认情况下,代理上的 GSSAPI 机制实施使用名为 amqp-sasl-gssapi 的 JAAS 配置范围来获取其 Kerberos 接收器凭证。
    Krb5LoginModule
    这个版本的 Krb5LoginModule 由 Oracle 和 OpenJDK 版本的 JDK 提供。通过参考来自 Java 供应商的文档,验证 Krb5LoginModule 的完全限定类名称及其可用选项。
    useKeyTab
    在验证主体时,Krb5LoginModule 配置为使用 Kerberos keytab。keytab 使用来自 Kerberos 环境的工具生成。有关生成 Kerberos keytab 的详细信息,请参阅供应商的文档。
    principal
    Principal 设置为 amqp/my_broker_host@example.com。这个值必须与您的 Kerberos 环境中创建的服务主体对应。有关创建服务主体的详情,请查看您供应商的文档。
  4. 启动代理。

    1. 在 Linux 中:

      <broker_instance_dir>/bin/artemis run
    2. 在 Windows 中:

      <broker_instance_dir>\bin\artemis-service.exe start

5.5.2.1. 使用替代配置范围

您可以通过将 saslLoginConfigScope 参数添加到 AMQP 接收器的 URL 来指定替代配置范围。在以下配置示例中,slLoginConfigScope 参数被赋予值 alternative-sasl-gssapi。结果是一个接收器,它使用名为 alternative-sasl-gssapi 的替代范围,它在 <broker_instance_dir>/etc/login.config 配置文件中声明。

<acceptor name="amqp">
tcp://0.0.0.0:5672?protocols=AMQP;saslMechanisms=GSSAPI,PLAIN;saslLoginConfigScope=alternative-sasl-gssapi`
</acceptor>

5.5.3. 使用 Kerberos 凭证授权客户端

AMQ Broker 包括 JAAS Krb5LoginModule 登录模块的实施,以便在映射角色时供其他安全模块使用。该模块将 Kerberos 身份验证的 Peer Principal 添加到主题的主体集中,作为 AMQ Broker UserPrincipal。然后可将凭证传递给 PropertiesLoginModuleLDAPLoginModule 模块,该模块将 Kerberos 验证的 Peer Principal 映射到 AMQ Broker 角色。

注意

Kerberos Peer Principal 不再是代理用户,仅作为角色成员。

先决条件

  • 您必须启用接收器的 GSSAPI 机制,然后才能使用 Kerberos 安全凭证授权 AMQP 连接。

流程

  1. 停止代理。

    1. 在 Linux 中:

      <broker_instance_dir>/bin/artemis stop
    2. 在 Windows 中:

      <broker_instance_dir>\bin\artemis-service.exe stop
  2. 打开 <broker_instance_dir>/etc/login.config 配置文件。
  3. 添加 AMQ Broker Krb5LoginModuleLDAPLoginModule 的配置。通过引用 LDAP 供应商的文档来验证配置选项。

    下面显示了一个配置示例:

    org.apache.activemq.artemis.spi.core.security.jaas.Krb5LoginModule required
        ;
    org.apache.activemq.artemis.spi.core.security.jaas.LDAPLoginModule optional
        initialContextFactory=com.sun.jndi.ldap.LdapCtxFactory
        connectionURL="ldap://localhost:1024"
        authentication=GSSAPI
        saslLoginConfigScope=broker-sasl-gssapi
        connectionProtocol=s
        userBase="ou=users,dc=example,dc=com"
        userSearchMatching="(krb5PrincipalName={0})"
        userSearchSubtree=true
        authenticateUser=false
        roleBase="ou=system"
        roleName=cn
        roleSearchMatching="(member={0})"
        roleSearchSubtree=false
        ;
    注意

    上例中显示的 Krb5LoginModule 版本与 AMQ Broker 一起分发,并将 Kerberos 身份转换为代理身份,供其他 AMQ 模块用于角色映射。

  4. 启动代理。

    1. 在 Linux 中:

      <broker_instance_dir>/bin/artemis run
    2. 在 Windows 中:

      <broker_instance_dir>\bin\artemis-service.exe start

其它资源

5.6. 指定安全管理器

代理使用名为 安全管理器 的组件来处理身份验证和授权。

AMQ Broker 包括两个安全管理器:

  • ActiveMQJAASSecurityManager 安全管理器.此安全经理提供与 JAAS 和红帽 JBoss 企业应用平台(JBoss EAP)安全性的集成。这是 AMQ Broker 使用 的默认 安全管理器。
  • ActiveMQBasicSecurityManager 安全管理器.这个基本安全管理器不支持 JAAS。相反,它支持通过用户名和密码凭据进行身份验证和授权。此安全管理器支持使用管理 API 添加、删除和更新用户。所有用户和角色数据都存储在代理绑定日志中。这意味着,对 live 代理所做的任何更改也适用于其备份代理。

作为包含的安全管理器的替代方案,系统管理员可能需要对代理安全性的实施进行更多控制。在这种情况下,也可以在代理配置中指定 自定义 安全管理器。自定义安全管理器是一个用户定义的类,它实施 org.apache.activemq.artemis.spi.core.security.ActiveMQSecurityManager5 接口。

以下子部分中的示例显示了如何配置代理使用:

  • 基本安全管理器,而不是默认的 JAAS 安全管理器
  • 自定义安全管理器

5.6.1. 使用基本安全管理器

除了默认的 ActiveMQJAASSecurityManager 安全管理器外,AMQ Broker 还包含 ActiveMQBasicSecurityManager 安全管理器。

当您使用基本安全管理器时,所有用户和角色数据存储在绑定日志中(如果您使用 JDBC 持久性,则为绑定 )。因此,如果您配置了 live-backup 代理组,则在 live 代理上执行的任何用户管理都会在故障转移时自动反映在备份代理中。这免除了单独管理 LDAP 服务器的需要,这也是实现此行为的替代方法。

在配置和使用基本安全管理器前,请注意以下几点:

  • 基本安全管理器不可插拔,与默认的 JAAS 安全管理器一样。
  • 基本安全管理器不支持 JAAS。相反,它只支持通过用户名和密码凭据进行身份验证和授权。
  • AMQ 管理控制台需要 JAAS.因此,如果您使用基本安全管理器并希望使用控制台,您还需要配置 login.config 配置文件以进行用户和密码身份验证。有关配置用户和密码身份验证的详情请参考 第 5.2.2.1 节 “配置基本用户和密码身份验证”
  • 在 AMQ Broker 中,用户管理由代理管理 API 提供。此管理包括添加、列出、更新和删除用户和角色的功能。您可以使用 JMX、管理消息、HTTP(使用 Jolokia 或 AMQ 管理控制台)和 AMQ Broker 命令行界面来执行这些功能。因为代理会直接存储这些数据,所以代理必须正在运行才能管理用户。无法手动修改绑定数据。
  • 任何通过 HTTP 的管理访问(例如,使用 Jolokia 或 AMQ 管理控制台)都由控制台 JAAS 登录模块处理。MBean 通过 JConsole 或其他远程 JMX 工具进行访问由基本安全经理处理。管理消息由基本安全管理器处理。

5.6.1.1. 配置基本安全管理器

以下流程演示了如何配置代理以使用基本安全管理器。

流程

  1. 打开 <broker-instance-dir>/etc/boostrap.xml 配置文件。
  2. security-manager 元素的 class-name 属性中,指定完整的 ActiveMQBasicSecurityManager 类名称。

    <broker xmlns="http://activemq.org/schema">
       ...
       <security-manager class-name="org.apache.activemq.artemis.spi.core.security.ActiveMQBasicSecurityManager">
       </security-manager>
       ...
    </broker>
  3. 由于您无法手动修改保存用户和角色数据的绑定数据,且代理必须正在运行才能管理用户,因此建议您在第一次引导时保护代理的安全。要做到这一点,请定义 bootstrap 用户,其凭证可用于添加其他用户。

    security-manager 元素中,添加 bootstrapUserbootstrapPasswordbootstrapRole 属性并指定值。例如:

    <broker xmlns="http://activemq.org/schema">
       ...
       <security-manager class-name="org.apache.activemq.artemis.spi.core.security.ActiveMQBasicSecurityManager">
            <property key="bootstrapUser" value="myUser"/>
            <property key="bootstrapPassword" value="myPass"/>
            <property key="bootstrapRole" value="myRole"/>
       </security-manager>
       ...
    </broker>
    bootstrapUser
    bootstrap 用户的名称。
    bootstrapPassword
    提升用户的 Passsword.您还可以指定加密的密码。
    bootstrapRole

    提升用户的角色.

    注意

    如果您在配置中为 bootstrap 用户定义了上述属性,则每次启动代理时都会设置这些凭证,不论您在代理运行时进行任何更改。

  4. 打开 <broker_instance_dir>/etc/broker.xml 配置文件。
  5. broker.xml 配置文件中,找到 activemq.management# 地址匹配默认定义的 address-setting 元素。这些默认地址设置如下所示:

    <address-setting match="activemq.management#">
        <dead-letter-address>DLQ</dead-letter-address>
        <expiry-address>ExpiryQueue</expiry-address>
        <redelivery-delay>0</redelivery-delay>
        <!--...-->
        <max-size-bytes>-1</max-size-bytes>
        <message-counter-history-day-limit>10</message-counter-history-day-limit>
        <address-full-policy>PAGE</address-full-policy>
        <auto-create-queues>true</auto-create-queues>
        <auto-create-addresses>true</auto-create-addresses>
        <auto-create-jms-queues>true</auto-create-jms-queues>
        <auto-create-jms-topics>true</auto-create-jms-topics>
    </address-setting>
  6. 在之前在此流程中指定的 bootstrap 角色名称的 activemq.management# 地址匹配的地址设置中,添加以下所需的权限:

    • createNonDurableQueue
    • createAddress
    • 使用
    • 管理
    • send

    例如:

    <address-setting match="activemq.management#">
        ...
        <permission type="createNonDurableQueue" roles="myRole"/>
        <permission type="createAddress" roles="myRole"/>
        <permission type="consume" roles="myRole"/>
        <permission type="manage" roles="myRole"/>
        <permission type="send" roles="myRole"/>
    </address-setting>

其它资源

5.6.2. 指定自定义安全管理器

以下流程演示了如何在代理配置中指定自定义安全管理器。

流程

  1. 打开 <broker_instance_dir>/etc/boostrap.xml 配置文件。
  2. security-manager 元素中,为 class-name 属性指定类,该类是用户定义的 org.apache.activemq.artemis.spi.core.security.ActiveMQSecurityManager5 接口的实施。例如:

    <broker xmlns="http://activemq.org/schema">
       ...
       <security-manager class-name="com.foo.MySecurityManager">
          <property key="myKey1" value="myValue1"/>
          <property key="myKey2" value="myValue2"/>
       </security-manager>
       ...
    </broker>

5.6.3. 运行自定义安全管理器示例程序

AMQ Broker 包含一个示例程序,它演示了如何实施自定义安全管理器。在示例中,自定义安全管理器会记录身份验证和授权的详细信息,然后将详细信息传递到 ActiveMQJAASSecurityManager (即默认安全管理器)的实例。

以下流程演示了如何运行自定义安全管理器示例程序。

先决条件

  • 您的机器必须设置为运行 AMQ Broker 示例程序。如需更多信息,请参阅 运行 AMQ Broker 示例

流程

  1. 导航到包含自定义安全管理器示例的目录。

    $ cd <install_dir>/examples/features/standard/security-manager
  2. 运行示例。

    $ mvn verify
注意

如果您更喜欢在运行示例程序时手动创建和启动代理实例,请将上一步中的命令替换为 mvn -PnoServer 验证

其它资源

5.7. 禁用安全

默认启用 安全性。以下流程演示了如何禁用代理安全性。

流程

  1. 打开 <broker_instance_dir>/etc/broker.xml 配置文件。
  2. core 元素中,将 security-enabled 的 值设置为 false

    <security-enabled>false</security-enabled>
  3. 如有必要,请为 security-invalidation-interval 指定一个新值,以毫秒为单位。此属性的值指定代理定期使安全登录无效。默认值为 10000

5.8. 跟踪已验证用户的信息

要启用跟踪和记录消息的来源(例如,为了安全审核目的),您可以使用 _AMQ_VALIDATED_USER 消息键。

broker.xml 配置文件中,如果将 populate -validated-user 选项设为 true,代理将使用 _AMQ_VALIDATED_USER 键将验证的用户名称添加到消息中。对于 JMS 和 STOMP 客户端,此消息密钥映射到 JMSXUserID 密钥。

注意

代理无法将验证的用户名添加到 AMQP JMS 客户端生成的消息中。在客户端发送后修改 AMQP 消息的属性会违反 AMQP 协议。

对于基于其 SSL 证书进行身份验证的用户,代理填充的已验证用户名为证书可辨识名称(DN)映射的名称。

broker.xml 配置文件中,如果启用了 security-enabled 填充-validated-usertrue,代理会填充客户端提供的任何用户名(如果有)。auto -validated-user 选项默认为 false

您可以将代理配置为拒绝当客户端发送消息时未填充用户名(即 JMSXUserID 密钥)的消息。您可能会发现这个选项对 AMQP 客户端很有用,因为代理无法为这些客户端发送的消息填充经过验证的用户名本身。

要将代理配置为拒绝客户端未设置 JMSXUserID 的信息,请在 broker.xml 配置文件中添加以下配置:

<reject-empty-validated-user>true</reject-empty-validated-user>

默认情况下,reject-empty-validated-user 设置为 false

5.9. 加密配置文件中的密码

默认情况下,AMQ Broker 将所有密码都以纯文本形式存储在配置文件中。务必使用正确的权限保护所有配置文件,以防止未经授权的访问。您还可以加密或 屏蔽 纯文本密码,以防止不需要的查看器读取它们。

5.9.1. 关于加密的密码

加密或 屏蔽 的密码是纯文本密码的加密版本。加密版本由 AMQ Broker 提供的 掩码 命令行实用程序生成。有关 掩码 工具的更多信息,请参阅命令行帮助文档:

$ <broker_instance_dir>/bin/artemis help mask

要屏蔽密码,请将其纯文本值替换为加密密码。屏蔽的密码必须使用标识符 ENC() 括起,以便在需要实际值时解密。

在以下示例中,配置文件 <broker_instance_dir>/etc/bootstrap.xml 包含用于 keyStorePassword 和 trustStorePassword 参数的屏蔽密码。

<web bind="https://localhost:8443" path="web"
     keyStorePassword="ENC(-342e71445830a32f95220e791dd51e82)"
     trustStorePassword="ENC(32f94e9a68c45d89d962ee7dc68cb9d1)">
    <app url="activemq-branding" war="activemq-branding.war"/>
</web>

您可以将屏蔽的密码与以下配置文件搭配使用:

  • broker.xml
  • bootstrap.xml
  • management.xml
  • artemis-users.properties
  • login.config(用于 LDAPLoginModule

配置文件位于 <broker_instance_dir>/etc

注意

Artemis-users.properties 仅支持已散列化的屏蔽密码。在创建代理时创建用户时,arte mis-users.properties 默认包含散列化密码。默认 PropertiesLoginModule 不会解码 artemis-users.properties 文件中的密码,而是对输入进行哈希并比较两个哈希值以进行密码验证。将哈希密码更改为屏蔽的密码不允许访问 AMQ Broker 管理控制台。

broker.xmlbootstrap.xmlmanagement.xmllogin.config 支持被屏蔽但未哈希的密码。

5.9.2. 在配置文件中加密密码

以下示例演示了如何在 broker.xml 配置文件中屏蔽 cluster-password 的值。

流程

  1. 在命令提示符后,使用 掩码 程序加密密码:

    $ <broker_instance_dir>/bin/artemis mask <password>
    result: 3a34fd21b82bf2a822fa49a8d8fa115d
  2. 打开 <broker_instance_dir>/etc/broker.xml 配置文件,该文件包含您要屏蔽的纯文本密码:

    <cluster-password>
      <password>
    </cluster-password>
  3. 将纯文本密码替换为加密值:

    <cluster-password>
      3a34fd21b82bf2a822fa49a8d8fa115d
    </cluster-password>
  4. 使用标识符 ENC() 包装加密的值:

    <cluster-password>
      ENC(3a34fd21b82bf2a822fa49a8d8fa115d)
    </cluster-password>

配置文件现在包含加密的密码。由于密码用 ENC() 标识符打包,AMQ Broker 会在使用密码前对其进行解密。

其它资源

第 6 章 保留消息数据

AMQ Broker 有两个用于持久性存储(即 存储)消息数据的选项:

在日志中保留消息
这是默认选项。基于日志的持久性是一个高性能选项,可将消息写入文件系统上的日志中。
在数据库中保留消息
此选项使用 Java 数据库连接(JDBC )连接将消息永久保留到您选择的数据库。

另外,您还可以将代理配置为 保留任何消息数据。如需更多信息,请参阅 第 6.3 节 “禁用持久性”

代理使用不同的解决方案来持久保留消息日志之外的大型消息。如需更多信息,请参阅 第 8 章 处理大量消息

代理也可以配置为在低内存情况下将消息分页到磁盘。如需更多信息,请参阅 第 7.1 节 “配置消息分页”

注意

有关 AMQ Broker 支持哪些数据库和网络文件系统的当前信息,请参阅红帽客户门户网站 中的 Red Hat AMQ 7 支持的配置

6.1. 在日志中持久保留消息数据

代理日志是磁盘上的一组 仅附加 文件。每个文件都预先创建为固定大小,并在最初填充 padding。随着消息操作在代理上执行,记录会附加到日志的末尾。通过附加记录,代理可以最小化磁盘头移动和随机访问操作,这通常是磁盘上最慢的操作。当一个日志文件已满时,代理会新建一个。

日志文件大小可以配置,最大程度减少各个文件使用的磁盘柱面数量。然而,现代磁盘拓扑比较复杂,代理无法控制该文件所映射到的柱面。因此,日志文件大小难以精确控制。

代理使用的其他持久性相关功能有:

  • 垃圾收集 算法,用于确定特定日志文件是否仍在使用。如果不再使用日志文件,代理可以回收该文件以供重复使用。
  • 压缩算法,用于从日志中移除死空间并压缩数据。这会使日志使用磁盘上的文件更少。
  • 支持本地交易.
  • 在使用 JMS 客户端时支持扩展架构(XA)事务.

大多数日志都用 Java 编写。但是,会提取与实际文件系统的交互,以便您可以使用不同的可插拔实施。AMQ Broker 包括以下实现:

NIO
NIO(新 I/O)使用标准 Java NIO 与文件系统进行接口。这提供了极其良好的性能,并在具有 Java 6 或更高版本运行时的任何平台上运行。有关 Java NIO 的更多信息,请参阅 Java NIO
AIO

AIO(Aynshcronous I/O)使用精简原生打包程序与 Linux 异步 I/O 库(libaio)对话。使用 AIO 时,数据将重新调用代理到磁盘,从而避免完全显式同步。默认情况下,代理会尝试使用 AIO 日志,并在 AIO 不可用时返回使用 NIO。

AIO 的性能优于 Java NIO.要了解如何安装 libaio,请参阅 第 6.1.1 节 “安装 Linux 异步 I/O 库”

以下子部分中的步骤演示了如何为基于日志的持久性配置代理。

6.1.1. 安装 Linux 异步 I/O 库

红帽建议使用 AIO 日志(而不是 NIO)来提高持久性性能。

注意

AIO 日志 不能 与其他操作系统或早期版本的 Linux 内核一起使用。

要使用 AIO 日志,您必须安装 Linux 异步 I/O 库(libaio)。要安装 libaio,请使用 yum 命令,如下所示:

yum install libaio

6.1.2. 配置基于日志的持久性

以下流程描述了如何查看代理用于基于日志的持久性的默认配置。您可以根据需要使用此描述来调整配置。

  1. 打开 <broker_instance_dir>/etc/broker.xml 配置文件。

    默认情况下,代理配置为使用基于日志的持久性,如下所示。

    <configuration>
      <core>
        ...
        <persistence-enabled>true</persistence-enabled>
        <journal-type>ASYNCIO</journal-type>
        <bindings-directory>./data/bindings</bindings-directory>
        <journal-directory>./data/journal</journal-directory>
        <journal-datasync>true</journal-datasync>
        <journal-min-files>2</journal-min-files>
        <journal-pool-files>-1</journal-pool-files>
        <journal-device-block-size>4096</journal-device-block-size>
        <journal-file-size>10M</journal-file-size>
        <journal-buffer-timeout>12000</journal-buffer-timeout>
        <journal-max-io>4096</journal-max-io>
        ...
      </core>
    </configuration>
    启用持久性
    如果此参数的值设为 true,代理将使用基于文件的日志实现消息持久性。
    journal-type
    要使用的日志类型。如果设置为 ASYNCIO,代理首先会尝试使用 AIO。如果没有找到 AIO,代理将使用 NIO。
    bindings-directory
    绑定日志的文件系统位置。默认值为相对于 <broker_instance_dir> 目录。
    journal-directory
    消息日志的文件系统位置。默认值为相对于 <broker_instance_dir> 目录。
    journal-datasync
    如果此参数的值设为 true,代理将使用 fdatasync 功能确认磁盘写入。
    journal-min-files
    在代理启动时最初创建的日志文件数。
    journal-pool-files
    回收未使用的文件后要保留的文件数.默认值 -1 表示在清理过程中不会删除任何文件。
    journal-device-block-size
    存储设备上日志所使用的数据块的最大大小,以字节为单位。默认值为 4096 字节。
    journal-file-size
    指定日志目录中各个日志文件的最大大小,以字节为单位。达到此限制时,代理会启动新文件。此参数还支持字节表示法(如 K、M、G)或二进制等效(Ki、Mi、Gi)。如果您的配置中没有明确指定此参数,则默认值为 10485760 字节(10MiB)。
    journal-buffer-timeout
    指定代理刷新日志缓冲区的频率,以纳秒为单位。AIO 通常使用高于 NIO 的清空率,因此代理为 NIO 和 AIO 维护不同的默认值。如果您的配置中没有明确指定此参数,则 NIO 的默认值为 3333 纳秒(即每秒 300 倍)。AIO 的默认值为 50000 纳秒(即,每秒为 2000 倍)。
    journal-max-io

    任意时间上 IO 队列中的最大写入请求数。如果队列已满,代理会阻止进一步写入,直到可用空间为止。

    如果您使用 NIO,这个值应该始终为 1。如果您使用的是 AIO,且此参数未在配置中明确指定,则默认值为 500

  2. 根据上述描述,根据需要调整您的存储设备的持久性配置。

其它资源

6.1.3. 关于绑定日志

绑定日志用于存储与绑定相关的数据,如代理中部署的队列集合及其属性。它还存储 ID 序列计数器等数据。

绑定日志始终使用 NIO,因为与消息日志相比,它通常是较低的吞吐量。此日志中的文件前缀为 activemq-bindings。每个文件还具有扩展名 .bindings,默认大小为 1048576 字节。

要配置绑定日志,请在 <broker_instance_dir>/etc/broker.xml 配置文件 的核心 元素中包括以下参数。

bindings-directory
绑定日志的目录。默认值为 <broker_instance_dir>/data/bindings
create-bindings-dir
如果此参数的值设为 true,代理会在 bindings-directory 中指定的位置自动创建绑定目录(如果不存在)。默认值为 true

6.1.4. 关于 JMS 日志

JMS 日志存储与 JMS 相关的所有数据,包括 JMS 队列、主题和连接工厂,以及这些资源的任何 JNDI 绑定。通过管理 API 创建的任何 JMS 资源都将保留在此日志中,但通过配置文件配置的任何资源都不保留。代理 仅在 使用 JMS 时创建 JMS 日志。

JMS 日志中的文件前缀为 activemq-jms。每个文件的扩展名为 .jms,默认大小为 1048576 字节。

JMS 日志通过绑定日志共享其配置。

其它资源

6.1.5. 压缩日志文件

AMQ Broker 包含一个压缩算法,用于从日志中移除死空间并压缩数据,使其占用的磁盘空间较少。

以下子部分显示如何:

6.1.5.1. 配置日志文件压缩

代理使用以下条件来确定何时开始压缩:

  • 为日志创建的文件数。
  • 日志文件中的实时数据百分比。

达到这两个条件的配置值后,紧凑过程将解析日志并删除所有死记录。因此,日志包含的文件更少。

以下步骤演示了如何为日志文件压缩配置代理。

流程

  1. 打开 <broker_instance_dir>/etc/broker.xml 配置文件。
  2. core 元素中添加 journal-compact-min-filesjournal-compact-percentage 参数,并指定值。例如:

    <configuration>
      <core>
        ...
        <journal-compact-min-files>15</journal-compact-min-files>
        <journal-compact-percentage>25</journal-compact-percentage>
        ...
      </core>
    </configuration>
    journal-compact-min-files
    代理在开始压缩前必须创建的最少日志文件数量。默认值为 10。将值设为 0 可禁用紧凑。禁用压缩时您应该小心,因为日志的大小可能会无限期地增加。
    journal-compact-percentage
    日志文件中的实时数据百分比。如果将少于这个百分比视为实时数据(并且已达到 journal-compact-min-files 配置的值),则开始压缩。默认值为 30

6.1.5.2. 使用命令行界面运行紧凑

以下步骤演示了如何使用命令行界面(CLI)压缩日志文件。

流程

  1. 作为 <broker_instance_dir> 目录的所有者,停止代理。以下示例显示了用户 amq-broker

    su - amq-broker
    cd <broker_instance_dir>/bin
    $ ./artemis stop
  2. (可选)运行以下 CLI 命令以获取数据工具的完整参数列表:默认情况下,该工具使用 <broker_instance_dir>/etc/broker.xml 中找到的设置。

    $ ./artemis help data compact.
  3. 运行以下 CLI 命令以压缩数据:

    $ ./artemis data compact.
  4. 在工具成功压缩数据后,重启代理。

    $ ./artemis run

其它资源

6.1.6. 禁用磁盘写入缓存

大多数磁盘包含硬件写入缓存。写入缓存可以提高磁盘的可见性性能,因为稍后写入会写到磁盘中。默认情况下,许多系统都启用了磁盘写入缓存。这意味着即使在从操作系统进行同步之后,也无法保证数据已实际传输到磁盘。因此,如果发生故障,关键数据可能会丢失。

有些更昂贵的磁盘具有非易失性或受电池支持写入缓存,这些缓存不一定会在出现故障时丢失数据,但您应进行测试。如果您的磁盘没有这样的功能,您应该确保禁用写入缓存。请注意,禁用磁盘写入缓存可能会对性能造成负面影响。

以下步骤演示了如何在 Windows 上的 Linux 中禁用磁盘写入缓存。

流程

  1. 在 Linux 上,若要管理磁盘写入缓存设置,请使用 tools hdparm (用于 IDE 磁盘)或 sdparmsginfo (用于 SDSI/SATA 磁盘)。
  2. 在 Windows 上,要管理磁盘写入器缓存设置,请右键单击磁盘。选择 属性.

6.2. 在数据库中持久保留消息数据

当您在数据库中持久保留消息数据时,代理使用 Java 数据库连接(JDBC )连接将消息和绑定数据存储在数据库表中。表中的数据使用 AMQ Broker 日志编码进行编码。有关支持的数据库的详情,请查看红帽客户门户网站 中的 Red Hat AMQ 7 支持的配置

重要

管理员可以根据组织更广泛的 IT 基础架构的要求,选择将消息数据存储在数据库中。但是,使用数据库会对消息传递系统的性能造成负面影响。具体来说,通过 JDBC 将消息传递数据写入数据库表可为代理带来显著的性能开销。

6.2.1. 配置 JDBC 持久性

以下流程演示了如何配置代理以在数据库表中存储消息和绑定数据。

流程

  1. 将适当的 JDBC 客户端库添加到代理运行时。为此,请将相关 .jar 文件添加到 <broker_instance_dir>/lib 目录中。
  2. 打开 <broker_instance_dir>/etc/broker.xml 配置文件。
  3. core 元素中,添加一个 包含 数据库存储元素的 storage 元素。

    <configuration>
      <core>
        <store>
           <database-store>
           </database-store>
        </store>
      </core>
    </configuration>
  4. database-store 元素中,添加 JDBC 持久性的配置参数并指定值。例如:

    <configuration>
      <core>
        <store>
           <database-store>
              <jdbc-connection-url>jdbc:oracle:data/oracle/database-store;create=true</jdbc-connection-url>
              <jdbc-user>ENC(5493dd76567ee5ec269d11823973462f)</jdbc-user>
              <jdbc-password>ENC(56a0db3b71043054269d11823973462f)</jdbc-password>
              <bindings-table-name>BINDINGS_TABLE</bindings-table-name>
              <message-table-name>MESSAGE_TABLE</message-table-name>
              <large-message-table-name>LARGE_MESSAGES_TABLE</large-message-table-name>
              <page-store-table-name>PAGE_STORE_TABLE</page-store-table-name>
              <node-manager-store-table-name>NODE_MANAGER_TABLE</node-manager-store-table-name>
              <jdbc-driver-class-name>oracle.jdbc.driver.OracleDriver</jdbc-driver-class-name>
              <jdbc-network-timeout>10000</jdbc-network-timeout>
              <jdbc-lock-renew-period>2000</jdbc-lock-renew-period>
              <jdbc-lock-expiration>20000</jdbc-lock-expiration>
              <jdbc-journal-sync-period>5</jdbc-journal-sync-period>
           </database-store>
        </store>
      </core>
    </configuration>
    jdbc-connection-url
    数据库服务器的完整 JDBC 连接 URL。连接 URL 应当包含所有配置参数和数据库名称。
    jdbc-user
    您的数据库服务器的加密用户名。有关加密配置文件中使用的用户名和密码的详情请参考 第 5.9 节 “加密配置文件中的密码”
    jdbc-password
    加密您的数据库服务器密码。有关加密配置文件中使用的用户名和密码的详情请参考 第 5.9 节 “加密配置文件中的密码”
    bindings-table-name
    存储绑定数据的表的名称。指定表名称可让您在多个服务器之间共享一个数据库,而无需干扰。
    message-table-name
    存储消息数据的表的名称。指定此表名称可让您在多个服务器之间共享一个数据库,而无需干扰。
    large-message-table-name
    保留大量消息和相关数据的表名称。此外,如果客户端以区块形式流传输大型消息,块将存储在这个表中。指定此表名称可让您在多个服务器之间共享一个数据库,而无需干扰。
    page-store-table-name
    存储目录信息的表的名称。指定此表名称可让您在多个服务器之间共享一个数据库,而无需干扰。
    node-manager-store-table-name
    用于实时和备份代理的共享存储高可用性(HA)锁定及其他 HA 相关数据的表名称。指定此表名称可让您在多个服务器之间共享一个数据库,而无需干扰。使用共享存储 HA 的每个实时备份对必须使用相同的表名称。您不能在多个(不相关的)实时备份对间共享相同的表。
    jdbc-driver-class-name
    JDBC 数据库驱动程序的完全限定类名称。有关支持的数据库的详情,请查看红帽客户门户网站 中的 Red Hat AMQ 7 支持的配置
    jdbc-network-timeout
    JDBC 网络连接超时,以毫秒为单位.默认值为 20000 毫秒。将 JDBC 用于共享存储 HA 时,建议将超时设为小于或等于 jdbc-lock-expiration 的值。
    jdbc-lock-renew-period
    当前 JDBC 锁定的续订期的时长,以毫秒为单位。当这次调整后,代理可以续订锁定。建议设置比 jdbc-lock-expiration 值小几个倍的值。这为代理提供了足够时间来扩展租期,并给予代理时间尝试在发生连接问题时续订锁定。默认值为 2000 毫秒。
    jdbc-lock-expiration

    以毫秒为单位计算当前 JDBC 锁定的时间(即获取或续订),即使 jdbc-lock-renew-period 的值已经过期。

    代理定期尝试根据 jdbc-lock-renew-period 的值续订它拥有的锁定。如果代理 无法 续订锁定(例如,因为连接问题),代理会一直尝试续订锁定,直到自锁定上次成功获取或更新后通过 jdbc-lock-expiration 的值。

    上述续订行为的例外是,当另一个代理获取锁定时。如果数据库管理系统(DBMS)和代理之间出现时间偏差,或者垃圾回收需要长时间暂停,则可能会发生这种情况。在这种情况下,最初拥有锁定的代理会认为锁定丢失,且不会尝试更新锁定。

    在过期时间过后,如果 JDBC 锁定没有被当前拥有的代理续订,则另一个代理可以建立 JDBC 锁定。

    jdbc-lock-expiration 的默认值为 20000 毫秒。

    jdbc-journal-sync-period
    代理日志与 JDBC 同步的持续时间,以毫秒为单位。默认值为 5 毫秒。

6.2.2. 配置 JDBC 连接池

如果您已经为 JDBC 持久性配置了代理,代理将使用 JDBC 连接将消息和绑定数据存储在数据库表中。

如果 JDBC 连接失败,并且只要发生故障时没有活动的连接活动(如数据库读取或写入),代理将继续运行,并尝试重新建立数据库连接。为实现这一目标,AMQ Broker 使用 JDBC 连接池

通常,连接池 提供一组开放连接,可以与多个应用之间共享的指定数据库。对于代理,如果代理与数据库之间的连接失败,代理会尝试使用来自池的不同连接重新连接到数据库。池在代理接收新连接前测试它。

下例演示了如何配置 JDBC 连接池。

重要

如果您没有明确配置 JDBC 连接池,代理将使用带有默认配置的连接池。默认配置使用现有 JDBC 配置中的值。如需更多信息,请参阅 默认连接池配置

先决条件

流程

  1. 打开 <broker-instance-dir>/etc/broker.xml 配置文件。
  2. 在您之前为 JDBC 配置添加的 database-store 元素中,删除 jdbc-driver-class-name, jdbc-connection-url, jdbc-user, jdbc-password, 参数。在此过程稍后,您将用对应的 DBCP 配置参数替换它们。

    注意

    如果您没有显式删除前面的参数,则优先选择您在此流程中添加的对应的 DBCP 参数。

  3. database-store 元素内,添加 data-source-properties 元素。例如:

    <store>
        <database-store>
            <data-source-properties>
            </data-source-properties>
            <bindings-table-name>BINDINGS</bindings-table-name>
            <message-table-name>MESSAGES</message-table-name>
            <large-message-table-name>LARGE_MESSAGES</large-message-table-name>
            <page-store-table-name>PAGE_STORE</page-store-table-name>
            <node-manager-store-table-name>NODE_MANAGER_STORE</node-manager-store-table-name>
            <jdbc-network-timeout>10000</jdbc-network-timeout>
            <jdbc-lock-renew-period>2000</jdbc-lock-renew-period>
            <jdbc-lock-expiration>20000</jdbc-lock-expiration>
            <jdbc-journal-sync-period>5</jdbc-journal-sync-period>
        </database-store>
    </store>
  4. 在新的 data-source-properties 元素内,为连接池添加 DBCP 数据源属性。指定键值对。例如:

    <store>
        <database-store>
            <data-source-properties>
                <data-source-property key="driverClassName" value="com.mysql.jdbc.Driver" />
                <data-source-property key="url" value="jdbc:mysql://localhost:3306/artemis" />
                <data-source-property key="username" value="ENC(5493dd76567ee5ec269d1182397346f)"/>
                <data-source-property key="password" value="ENC(56a0db3b71043054269d1182397346f)"/>
                <data-source-property key="poolPreparedStatements" value="true" />
                <data-source-property key="maxTotal" value="-1" />
            </data-source-properties>
            <bindings-table-name>BINDINGS</bindings-table-name>
            <message-table-name>MESSAGES</message-table-name>
            <large-message-table-name>LARGE_MESSAGES</large-message-table-name>
            <page-store-table-name>PAGE_STORE</page-store-table-name>
            <node-manager-store-table-name>NODE_MANAGER_STORE</node-manager-store-table-name>
            <jdbc-network-timeout>10000</jdbc-network-timeout>
            <jdbc-lock-renew-period>2000</jdbc-lock-renew-period>
            <jdbc-lock-expiration>20000</jdbc-lock-expiration>
            <jdbc-journal-sync-period>5</jdbc-journal-sync-period>
        </database-store>
    </store>
    driverClassName
    JDBC 数据库驱动程序的完全限定类名称。
    url
    数据库服务器的完整 JDBC 连接 URL。
    username
    您的数据库服务器的加密用户名。您还可以将此值指定为未加密的纯文本。有关加密配置文件中使用的用户名和密码的详情请参考 第 5.9 节 “加密配置文件中的密码”
    password
    加密您的数据库服务器密码。您还可以将此值指定为未加密的纯文本。有关加密配置文件中使用的用户名和密码的详情请参考 第 5.9 节 “加密配置文件中的密码”
    poolPreparedStatements
    当此参数的值设为 true 时,池可以具有无限数量的缓存就绪语句。这可降低初始化成本。
    maxTotal
    池中连接的最大数量。当此参数的值设为 -1 时,没有限制。

如果您没有明确配置 JDBC 连接池,代理将使用带有默认配置的连接池。默认配置在表中进行了描述。

表 6.1. 默认连接池配置

DBCP 配置参数默认值

driverClassName

现有 jdbc-driver-class-name 参数的值

url

现有 jdbc-connection-url 参数的值

username

现有 jdbc-user 参数的值

password

现有 jdbc-password 参数的值

poolPreparedStatements

true

maxTotal

-1

注意

重新连接 仅在 没有客户端主动向代理发送信息时才有效。如果在重新连接过程中尝试写入数据库表,代理会失败并关闭。

其它资源

6.3. 禁用持久性

在某些情况下,可能要求消息传递系统 存储任何数据。在这些情况下,您可以禁用代理上的持久性。

以下步骤演示了如何禁用持久性。

流程

  1. 打开 <broker_instance_dir>/etc/broker.xml 配置文件。
  2. core 元素中,将 persistence-enabled 参数的值设置为 false

    <configuration>
      <core>
        ...
        <persistence-enabled>false</persistence-enabled>
        ...
      </core>
    </configuration>

    不会保留消息数据、绑定数据、大消息数据、重复 ID 缓存或分页数据。

第 7 章 为地址配置最大内存用量

AMQ Broker 以透明的方式支持包含数百万消息的大型队列,即使托管代理的机器运行的内存有限。

在这些情况下,可能无法在任意时间将所有队列存储在内存中。要防止过量内存消耗,您可以配置代理上每个地址允许的最大内存用量。另外,您可以指定在给定地址达到这个限制时代理采取什么操作。

特别是,当地址的内存用量达到配置的限制时,您可以将代理配置为执行以下操作之一:

  • 页面信息
  • 静默丢弃消息
  • 丢弃消息并通知发送的客户端
  • 阻止客户端发送消息

下面的部分演示了如何为地址配置最大内存用量,以及在达到地址限制时代理可以执行的对应操作。

重要

当您使用事务时,代理可能会分配额外的内存来确保事务一致性。在这种情况下,代理报告的内存用量可能无法反映内存中使用的字节总数。因此,如果您根据指定的最大内存用量将代理配置为页面、丢弃或阻止信息,则不应该使用事务。

7.1. 配置消息分页

对于指定最大内存用量限制的任何地址,您还可以指定达到用量限制时代理执行的操作。您可以配置的一个选项是 分页

如果您配置分页选项,达到地址的最大大小时,代理会开始将该地址的消息存储在磁盘上,称为 页面文件。每个页面文件都有一个您可以配置的最大大小。以这种方式配置的每个地址在您的文件系统中都有一个用于存储分页消息的专用文件夹。

在检查队列中的消息时,队列浏览器和消费者都可以在页面文件中导航。但是,在首先使用队列中的现有消息之前,使用非常具体的过滤器的消费者可能无法使用存储在页面文件中的消息。例如,假定使用者过滤器包含字符串表达式,如 "color='red'"。如果满足此条件的消息遵循一百万条带有属性 "color='blue'" 的消息,则使用者将无法使用该消息,直到首先使用 "color='blue'" 的消息。

当客户端准备好使用时,代理将消息从磁盘传输(即 解页)到内存中。当该文件中的所有消息都已确认后,代理会从磁盘中删除页面文件。

以下流程演示了如何配置消息分页。

7.1.1. 指定分页目录

以下步骤演示了如何指定分页目录的位置。

流程

  1. 打开 <broker_instance_dir>/etc/broker.xml 配置文件。
  2. core 元素内,添加 分页目录 元素。指定文件系统中分页目录的位置。

    <configuration ...>
      <core ...>
        ...
        <paging-directory>/path/to/paging-directory</paging-directory>
        ...
      </core>
    </configuration>

    对于您随后为分页配置的每个地址,代理会在您指定的分页目录中添加一个专用目录。

7.1.2. 配置地址以进行分页

以下步骤演示了如何为分页配置地址。

先决条件

流程

  1. 打开 <broker_instance_dir>/etc/broker.xml 配置文件。
  2. 对于您为匹配地址或地址 配置的 address-setting 元素,添加配置元素以指定最大内存使用量并定义分页行为。例如:

    <address-settings>
        <address-setting match="my.paged.address">
            ...
            <max-size-bytes>104857600</max-size-bytes>
            <page-size-bytes>10485760</page-size-bytes>
            <address-full-policy>PAGE</address-full-policy>
            ...
        </address-setting>
    </address-settings>
    max-size-bytes
    代理执行为 address-full-policy 指定策略之前,地址允许的最大内存大小,以字节为单位。默认值为 -1,这意味着没有限制。您指定的值还支持字节表示法,如 "K"、"MB" 和 "GB"。
    page-size-bytes
    分页系统中使用的每个页面文件的大小(以字节为单位)。默认值为 10485760 (即 10 MiB)。您指定的值还支持字节表示法,如 "K"、"MB" 和 "GB"。
    address-full-policy

    代理在达到地址最大值时执行的操作。默认值为 PAGE。有效值为:

    页面
    代理将进一步的信息传输到磁盘。
    DROP
    代理会静默丢弃任何进一步的信息。
    FAIL
    代理会向客户端消息制作者丢弃任何其他消息和问题。
    BLOCK
    当客户端消息制作者尝试发送更多消息时,它们会阻止它们。

    以上示例中 未显示 的其他分页配置元素如下所述。

    page-max-cache-size
    代理保留在内存中的页面文件数量,以便在分页导航期间优化 IO。默认值为 5
    page-sync-timeout
    定期页面同步之间的时间(以纳秒为单位)。如果您使用异步 IO 日志(即 journal-typebroker.xml 配置文件中被设置为 ASYNCIO ),则默认值为 3333333。如果您使用标准 Java NIO 日志(即 journal-type 设置为 NIO),则默认值是 journal-buffer-timeout 参数的配置值。

在前面的示例中,当发送到地址 my.paged.address 的消息超过内存 104857600 字节时,代理将开始分页。

注意

如果在 address -setting 元素中指定了 max-size- bytes,则该值将应用到 每个 匹配地址。指定这个值 并不意味着 所有匹配地址 的总 大小都仅限于 max-size-bytes 的值。

7.1.3. 配置全局分页大小

有时,每个地址 配置内存限制是不现实的,例如,当代理管理许多使用模式的地址时。在这些情况下,您可以指定一个全局内存限值。全局限制是代理可用于所有地址的内存 总量。达到此内存限制时,代理会为与新传入消息关联的地址执行为 address-full-policy 指定的策略。

以下步骤演示了如何配置全局分页大小。

先决条件

流程

  1. 停止代理。

    1. 在 Linux 中:

      <broker_instance_dir>/bin/artemis stop
    2. 在 Windows 中:

      <broker_instance_dir>\bin\artemis-service.exe stop
  2. 打开 <broker_instance_dir>/etc/broker.xml 配置文件。
  3. core 元素中,添加 global-max-size 元素并指定一个值。例如:

    <configuration>
      <core>
        ...
        <global-max-size>1GB</global-max-size>
        ...
      </core>
    </configuration>
    global-max-size

    代理可用于所有地址的内存总量,以字节为单位。达到这个限制时,对于与传入消息关联的地址,代理会执行指定为 address-full-policy 值的策略global-max-size 的默认值是托管代理的 Java 虚拟机(JVM)可用的最大内存的一半。

    global-max-size 的值以字节为单位,但也支持字节表示法(例如:"K"、"Mb"、"GB")。

    在前面的示例中,代理被配置为在处理消息时最多使用一千兆字节的可用内存。

  4. 启动代理。

    1. 在 Linux 中:

      <broker_instance_dir>/bin/artemis run
    2. 在 Windows 中:

      <broker_instance_dir>\bin\artemis-service.exe start

7.1.4. 在分页过程中限制磁盘用量

您可以在代理阻止传入消息而不是分页信息前限制代理可以使用的物理磁盘空间量。

以下流程演示了如何在分页期间设置磁盘用量限制。

流程

  1. 停止代理。

    1. 在 Linux 中:

      <broker_instance_dir>/bin/artemis stop
    2. 在 Windows 中:

      <broker_instance_dir>\bin\artemis-service.exe stop
  2. 打开 <broker_instance_dir>/etc/broker.xml 配置文件。
  3. core 元素中添加 max-disk-usage 配置元素并指定一个值。例如:

    <configuration>
      <core>
        ...
        <max-disk-usage>50</max-disk-usage>
        ...
      </core>
    </configuration>
    max-disk-usage

    代理在分页消息时可使用的可用磁盘空间的最大百分比。达到这个限制时,代理会阻止传入的信息,而不是分页它们。默认值为 90

    在前面的示例中,代理仅在分页消息时使用 50% 的磁盘空间。

  4. 启动代理。

    1. 在 Linux 中:

      <broker_instance_dir>/bin/artemis run
    2. 在 Windows 中:

      <broker_instance_dir>\bin\artemis-service.exe start

7.2. 配置消息丢弃

第 7.1.2 节 “配置地址以进行分页” 显示如何配置分页地址。作为该流程的一部分,您要将 address-full-policy 的值设置为 PAGE

要在地址达到指定的最大大小时 丢弃 信息(而不是分页),将 address-full-policy 的值设置为以下之一:

DROP
当达到给定地址的最大值时,代理会静默地丢弃任何其他信息。
FAIL
当达到给定地址的最大大小时,代理会向生产者丢弃任何其他消息和问题。

7.3. 配置消息阻止

以下流程演示了如何在给定地址达到您指定的最大大小限制时配置消息阻止。

注意

只能 为核心、OpenWire 和 AMQP 协议配置消息阻止。

7.3.1. 阻塞内核和 OpenWire producer

以下流程演示了如何在给定地址达到您指定的最大大小限制时为 Core 和 OpenWire 消息生成器配置消息阻塞。

先决条件

流程

  1. 打开 <broker_instance_dir>/etc/broker.xml 配置文件。
  2. 对于您已为匹配地址或地址 配置的 address-setting 元素,请添加配置元素来定义消息阻止行为。例如:

    <address-settings>
        <address-setting match="my.blocking.address">
            ...
            <max-size-bytes>300000</max-size-bytes>
            <address-full-policy>BLOCK</address-full-policy>
            ...
        </address-setting>
    </address-settings>
    max-size-bytes

    代理执行为 address-full-policy 指定策略之前,地址允许的最大内存大小,以字节为单位。您指定的值还支持字节表示法,如 "K"、"MB" 和 "GB"。

    注意

    如果在 address -setting 元素中指定了 max-size- bytes,则该值将应用到 每个 匹配地址。指定这个值 并不意味着 所有匹配地址 的总 大小都仅限于 max-size-bytes 的值。

    address-full-policy
    代理在达到地址最大值时执行的操作。

    在前面的示例中,当发送到地址 my.blocking.address 的消息超过 300000 字节时,代理开始阻止来自 Core 或 OpenWire 消息制作者进一步的消息。

7.3.2. 阻塞 AMQP 制作者

Core 和 OpenWire 等协议使用窗口大小流控制系统。在这个系统中,信用代表字节,并分配给生产者。如果制作者希望发送消息,制作者必须等待消息的大小得到足够的学分。

相比之下,AMQP 流控制贡献不代表字节。相反,AMQP 贡献度代表了生产者被允许发送的消息数量,而不考虑消息大小。因此,在某些情况下,AMQP 生产者可能会明显超过地址 的 max-size-bytes 值。

因此,要阻止 AMQP 制作者,您必须使用不同的配置元素 max-size-bytes-reject-threshold。对于匹配的地址或一组地址,此元素指定内存中所有 AMQP 消息的最大大小(以字节为单位)。当内存中所有消息的总大小达到指定的限制时,代理会阻止 AMQP 生产者发送进一步消息。

以下步骤演示了如何为 AMQP 消息制作者配置消息阻塞。

先决条件

流程

  1. 打开 <broker_instance_dir>/etc/broker.xml 配置文件。
  2. 对于您已为匹配地址或地址 配置的 address-setting 元素,请指定内存中所有 AMQP 消息的最大大小。例如:

    <address-settings>
        <address-setting match="my.amqp.blocking.address">
            ...
            <max-size-bytes-reject-threshold>300000</max-size-bytes-reject-threshold>
            ...
        </address-setting>
    </address-settings>
    max-size-bytes-reject-threshold

    代理在进一步阻止 AMQP 消息前,地址允许的最大内存大小,以字节为单位。您指定的值还支持字节表示法,如 "K"、"MB" 和 "GB"。默认情况下,max-size-bytes-reject-threshold 设置为 -1,这意味着没有最大大小。

    注意

    如果在 address -setting 元素中指定了 max-size-bytes-reject- threshold,则该值将应用到 每个 匹配地址。指定这个值 并不意味着 所有匹配地址 的总 大小都仅限于 max-size-bytes-reject-threshold 的值。

在前面的示例中,当发送到地址 my.amqp.blocking.address 的消息超过内存中 300000 字节时,代理开始阻止来自 AMQP 制作者的其他消息。

7.4. 了解多播地址的内存使用情况

当消息路由到绑定了多播队列的地址时,内存中仅有一个消息副本。每个队列仅具有 对该消息的引用。因此,只有在引用了消息 的所有队列都 传送后,相关的内存才会被释放。

在这种情况下,如果消费者较慢,整个地址可能会受到性能负面影响。

例如,考虑这种情况:

  • 地址有十个使用多播路由类型的队列。
  • 由于消费者速度较慢,其中一个队列不发送其消息。其他九个队列继续发送消息,并且为空。
  • 消息继续到达地址。具有较慢消费者的队列继续积累对消息的引用,从而导致代理将消息保留在内存中。
  • 当达到地址的最大大小时,代理会开始页信息。

在这种场景中,因为单一消费者较慢,所有 队列中的消费者都被迫消耗来自页面系统的消息,需要额外的 IO。

其它资源

  • 要了解如何配置流控制来规范代理和生产者与消费者之间的数据流,请参阅 AMQ Core Protocol JMS 文档中的 流控制

第 8 章 处理大量消息

客户端可能会发送可能会超过代理内部缓冲大小的大信息,从而导致意外错误。要防止这种情况,您可以将代理配置为在消息大于指定最小值时将消息存储为文件。以这种方式处理大量消息意味着代理不会将消息保存在内存中。相反,您可以指定磁盘上或数据库表中存储大型消息文件的目录。

当代理将消息存储为大消息时,队列会在大型消息目录或数据库表中保留对文件的引用。

大型消息处理可用于核心协议、AMQP、OpenWire 和 STOMP 协议。

对于核心协议和 OpenWire 协议,客户端在其连接配置中指定最小大的消息大小。对于 AMQP 和 STOMP 协议,您可以在代理配置中为各个协议定义的接收器中最少的大消息大小。

注意

建议您 不要将 不同的协议用于生成和使用大型消息。为此,代理可能需要对消息执行多次转换。例如,假设您想要使用 AMQP 协议发送消息并使用 OpenWire 接收消息。在这种情况下,代理必须首先读取大信息正文,并将其转换为使用 Core 协议。然后,代理必须执行另一转换,这一次到 OpenWire 协议。诸如这样的消息转换会给代理带来大量处理开销。

您为上述任何协议指定的最小大消息大小都受到系统资源(如可用磁盘空间量)以及消息大小的影响。建议您使用多个值运行性能测试来确定适当的大小。

本节中的步骤显示如何:

  • 配置代理以存储大型信息
  • 为大型消息处理配置 AMQP 和 STOMP 协议的接收器

本节还链接有关配置 AMQ 核心协议和 AMQ OpenWire JMS 客户端以便处理大量消息的其他资源。

8.1. 配置代理以进行大型消息处理

以下流程演示了如何指定磁盘上的目录或代理在其中存储大型消息文件的数据库表。

流程

  1. 打开 <broker_instance_dir>/etc/broker.xml 配置文件。
  2. 指定代理存储大型消息文件的位置。

    1. 如果您在磁盘上存储大型消息,请在 核心 元素中添加 large-messages-directory 参数,并指定文件系统位置。例如:

      <configuration>
        <core>
          ...
          <large-messages-directory>/path/to/my-large-messages-directory</large-messages-directory>
          ...
        </core>
      </configuration>
      注意

      如果您没有明确为 large-messages-directory 指定值,代理将使用默认值 <broker_instance_dir>/data/largemessages

    2. 如果您在数据库表中存储大型消息,请将 large-message-table 参数添加到 database-store 元素并指定一个值。例如:

      <store>
        <database-store>
          ...
          <large-message-table>MY_TABLE</large-message-table>
          ...
        </database-store>
      </store>
      注意

      如果没有为 large-message-table 明确指定值,代理将使用默认值 LARGE_MESSAGE_TABLE

其它资源

8.2. 为大型消息处理配置 AMQP 接收器

以下流程演示了如何配置 AMQP 接收器来处理大于指定大小的 AMQP 消息作为大型消息。

流程

  1. 打开 <broker_instance_dir>/etc/broker.xml 配置文件。

    代理配置文件中的默认 AMQP 接收器如下:

    <acceptors>
        ...
        <acceptor name="amqp">tcp://0.0.0.0:5672?tcpSendBufferSize=1048576;tcpReceiveBufferSize=1048576;protocols=AMQP;useEpoll=true;amqpCredits=1000;amqpLowCredits=300</acceptor>
        ...
    </acceptors>
  2. 在默认的 AMQP 接收器(或其他您配置的 AMQP 接收器)中,添加 amqpMinLargeMessageSize 属性并指定值。例如:

    <acceptors>
        ...
        <acceptor name="amqp">tcp://0.0.0.0:5672?tcpSendBufferSize=1048576;tcpReceiveBufferSize=1048576;protocols=AMQP;useEpoll=true;amqpCredits=1000;amqpLowCredits=300;amqpMinLargeMessageSize=204800</acceptor>
        ...
    </acceptors>

    在前面的示例中,代理配置为接受端口 5672 上的 AMQP 消息。根据 amqpMinLargeMessageSize 的值,如果接收器收到 AMQP 消息,其正文大于或等于 204800 字节(即 200 KB),代理会将消息存储为大消息。如果您未明确为此属性指定值,代理将使用默认值 102400(即 100 KB)。

注意
  • 如果将 amqpMinLargeMessageSize 设置为 -1,则禁用对 AMQP 消息的大型消息处理。
  • 如果代理收到的 AMQP 消息没有超过 amqpMinLargeMessageSize 的值,但会 超过 消息传递日志缓冲区的大小(使用 journal-buffer-size 配置参数指定),代理会将消息转换为大型核心协议消息,然后再将其存储在日志中。

8.3. 为大型消息处理配置 STOMP 接收器

以下步骤演示了如何配置 STOMP 接收器来处理大于指定大小的 STOMP 消息作为大信息。

流程

  1. 打开 <broker_instance_dir>/etc/broker.xml 配置文件。

    代理配置文件中的默认 AMQP 接收器如下:

    <acceptors>
        ...
        <acceptor name="stomp">tcp://0.0.0.0:61613?tcpSendBufferSize=1048576;tcpReceiveBufferSize=1048576;protocols=STOMP;useEpoll=true</acceptor>
        ...
    </acceptors>
  2. 在默认的 STOMP 接收器(或其他您配置的 STOMP 接收器)中,添加 stompMinLargeMessageSize 属性并指定一个值。例如:

    <acceptors>
        ...
        <acceptor name="stomp">tcp://0.0.0.0:61613?tcpSendBufferSize=1048576;tcpReceiveBufferSize=1048576;protocols=STOMP;useEpoll=true;stompMinLargeMessageSize=204800</acceptor>
        ...
    </acceptors>

在前面的示例中,代理被配置为接受端口 61613 上的 STOMP 消息。根据 stomp MinLargeMessageSize 的值,如果接收器收到大于或等于 204800 字节(即 200 KB)的 STOMP 消息,代理会将消息存储为大信息。如果您未明确为此属性指定值,代理将使用默认值 102400(即 100 KB)。

注意

要向 STOMP 消费者发送大条消息,代理会在将消息发送到客户端之前自动将消息从大消息转换为普通消息。如果压缩大型消息,代理会在将其发送到 STOMP 客户端前解压缩。

8.4. 大消息和 Java 客户端

Java 开发人员可使用两种选项来编写使用大型消息的客户端。

种选择是使用 输入流和 输出流 的实例。例如,file InputStream 可用于发送从物理磁盘上的大型文件获取的消息。然后,接收方可以使用 FileOutputStream 将消息流传输到其本地文件系统上的位置。

另一种选择是直接流传输 JMS BytesMessageStreamMessage。例如:

BytesMessage rm = (BytesMessage)cons.receive(10000);
byte data[] = new byte[1024];
for (int i = 0; i < rm.getBodyLength(); i += 1024)
{
   int numberOfBytes = rm.readBytes(data);
   // Do whatever you want with the data
}

其它资源

第 9 章 检测拒绝连接

有时,客户端会意外停止,并且无法清理其资源。如果出现这种情况,可能会导致资源处于故障状态,并导致代理内存或其他系统资源不足。代理检测到在垃圾收集时客户端的连接没有被正确关闭。然后连接关闭,日志中与以下类似的消息写入日志。日志捕获客户端会话实例化的确切代码行。这可让您识别并修正错误。

[Finalizer] 20:14:43,244 WARNING [org.apache.activemq.artemis.core.client.impl.DelegatingSession]  I'm closing a JMS Conection you left open. Please make sure you close all connections explicitly before let
ting them go out of scope!
[Finalizer] 20:14:43,244 WARNING [org.apache.activemq.artemis.core.client.impl.DelegatingSession]  The session you didn't close was created here:
java.lang.Exception
   at org.apache.activemq.artemis.core.client.impl.DelegatingSession.<init>(DelegatingSession.java:83)
   at org.acme.yourproject.YourClass (YourClass.java:666) 1
1
连接实例化的客户端代码中的 行。

9.1. 连接时间到学习

因为客户端和服务器之间的网络连接可能会失败,然后返回到在线,允许客户端重新连接,AMQ Broker 会等待清理不活跃的服务器端资源。此等待时间称为生存时间(TTL)。基于网络连接的默认 TTL 为 60000 毫秒(1 分钟)。in-VM 连接中的默认 TTL 是 -1,这意味着代理永远不会超时代理端的连接。

在代理中配置时间到学习

如果您不希望客户端指定自己的连接 TTL,您可以在代理一侧设置全局值。这可以通过在代理配置中指定 connection-ttl-override 元素来完成。

检查 TTL 违反连接的逻辑定期在代理上运行,具体由 connection-ttl-check-interval 元素决定。

流程

  • 通过添加 connection-ttl-override 配置元素并提供生存时间的值来编辑 <broker_instance_dir> /etc/broker.xml

    <configuration>
     <core>
      ...
      <connection-ttl-override>30000</connection-ttl-override> 1
      <connection-ttl-check-interval>1000</connection-ttl-check-interval> 2
      ...
     </core>
    </configuration>
    1
    所有连接的全局 TTL 设为 30000 毫秒。默认值为 -1,它允许客户端设置自己的 TTL。
    2
    死连接检查之间的间隔被设置为 1000 毫秒。默认情况下,检查每 2000 毫秒执行一次。

9.2. 禁用异步连接执行

代理一侧收到的大多数数据包都在 远程线程 中执行。这些数据包代表短期运行的操作,出于性能的原因,始终在远程 线程 中执行。但是,一些数据包类型是使用线程池而不是远程 线程 来执行的,这增加了一些网络延迟。

使用线程池的数据包类型在下面列出的 Java 类中实施。这些类均在软件包 org.apache.actiinvemq.artemis.core.protocol.core.impl.wireformat 中找到。

  • RollbackMessage
  • SessionCloseMessage
  • SessionCommitMessage
  • SessionXACommitMessage
  • SessionXAPrepareMessage
  • SessionXARollbackMessage

流程

  • 要禁用异步连接执行,请将 async-connection-execution-enabled 配置元素添加到 <broker_instance_dir>/etc/broker.xml 并将其设置为 false,如下例所示。默认值为 true

    <configuration>
     <core>
      ...
      <async-connection-execution-enabled>false</async-connection-execution-enabled>
      ...
     </core>
    </configuration>

其它资源

第 10 章 检测重复信息

您可以将代理配置为自动检测和过滤重复的信息。这意味着您不必实施自己的重复检测逻辑。

如果没有重复检测,在出现意外连接失败时,客户端无法判断是否收到了它发送到代理的消息。在这种情况下,客户端可能假定代理没有接收消息,并重新发送消息。这会产生重复的信息。

例如,假设客户端向代理发送消息。如果在代理接收和处理消息 代理或连接失败,信息永远不会到达其地址。由于失败,客户端不会从代理收到响应。如果在代理接收和处理消息 代理或连接失败,则会正确路由消息,但客户端仍不会收到响应。

此外,在这些情况下,使用交易来确定成功不一定会有所帮助。如果在处理事务提交时代理或连接失败,客户端仍无法确定它是否成功发送消息。

在这些情况下,为了更正假定的失败,客户端会重新发送最新的消息。结果可能是对您的系统造成负面影响的重复消息。例如,如果您在订单系统中使用代理,则重复的消息可能意味着处理两次采购订单。

以下步骤演示了如何配置重复的消息检测以防止这些类型的情况。

10.1. 配置重复 ID 缓存

要让代理能够检测重复的消息,生产者必须在发送每条消息时为消息属性 _AMQ_DUPL_ID 提供唯一值。代理维护收到的 _AMQ_DUPL_ID 属性值的缓存。代理在地址上收到新消息时,它将检查该地址的缓存,以确保之前没有处理此属性值相同的消息。

每个地址都有自己的缓存。每个缓存都是循环的,并固定大小。这意味着,新条目会根据缓存空间需求替换最旧的条目。

以下流程演示了如何全局配置代理上每个地址使用的 ID 缓存。

流程

  1. 打开 <broker_instance_dir>/etc/broker.xml 配置文件。
  2. core 元素中,添加 id-cache-sizepersistent-id-cache 属性并指定值。例如:

    <configuration>
      <core>
        ...
        <id-cache-size>5000</id-cache-size>
        <persist-id-cache>false</persist-id-cache>
      </core>
    </configuration>
    id-cache-size

    ID 缓存的最大大小,指定为缓存中的单个条目数。默认值为 20,000 个条目。在本例中,缓存大小设置为 5,000 个条目。

    注意

    当达到缓存的最大大小时,代理可能会开始处理重复的消息。例如,假设您将缓存的大小设置为 3000。如果在发送新消息之前到达 3,000 条消息,且值为 _AMQ_DUPL_ID,代理将无法检测到重复消息。这会导致代理处理这两个消息。

    persist-id-cache
    当此属性的值设为 true 时,代理会在收到 ID 时将其保留为磁盘。默认值为 true。在上例中,您可以通过将值设置为 false 来禁用持久性。

其它资源

  • 要了解如何使用 AMQ 核心协议 JMS 客户端设置重复 ID 消息属性,请参阅 AMQ Core Protocol JMS 客户端文档中的使用 重复消息检测

10.2. 为集群连接配置重复检测

您可以配置集群连接,为移动到集群中的每个消息插入重复的 ID 标头。

先决条件

流程

  1. 打开 <broker_instance_dir>/etc/broker.xml 配置文件。
  2. core 元素中,为给定的集群连接添加 use-duplicate-detection 属性 并指定一个值。例如:

    <configuration>
      <core>
        ...
        <cluster-connections>
           <cluster-connection name="my-cluster">
             <use-duplicate-detection>true</use-duplicate-detection>
             ...
           </cluster-connection>
             ...
        </cluster-connections>
      </core>
    </configuration>
    use-duplicate-detection
    当此属性的值设为 true 时,集群连接会为其处理的每个消息插入一个重复的 ID 标头。

第 11 章 截获消息

使用 AMQ Broker,您可以拦截进入或退出代理的数据包,允许您审核数据包或过滤信息。拦截器可以更改它们拦截的数据包,这使它们的功能强大,但也具有危险性。

您可以开发拦截器来满足您的业务需求。拦截器是特定于协议的,必须实施相应的接口。

拦截器必须实施 intercept () 方法,这将返回布尔值。如果值为 true,则消息数据包将继续。如果为 false,则进程将被中止,不会调用其他拦截器,并且不会进一步处理消息数据包。

11.1. 创建 Interceptors

您可以创建自己的传入和传出拦截器。所有拦截器都是特定的协议,对于分别进入或退出服务器的任何数据包调用。这可让您创建拦截器来满足审计数据包等业务要求。拦截器可以更改它们拦截的数据包。这使得它们的功能强大以及潜在的危险性,因此务必谨慎使用。

拦截器及其依赖项必须放在代理的 Java 类路径中。由于 <broker_instance_dir> /lib 目录默认是类路径的一部分,因此可以使用 & lt;broker_instance_dir> /lib 目录。

流程

以下示例演示了如何创建一个拦截器来检查传递给它的每个数据包的大小。请注意,这些示例为每个协议实施特定的接口。

  • 实施适当的接口并覆盖其 intercept () 方法。

    • 如果您使用 AMQP 协议,实施 org.apache.activemq.artemis.protocol.amqp.broker.AmqpInterceptor 接口。

      package com.example;
      
      import org.apache.activemq.artemis.protocol.amqp.broker.AMQPMessage;
      import org.apache.activemq.artemis.protocol.amqp.broker.AmqpInterceptor;
      import org.apache.activemq.artemis.spi.core.protocol.RemotingConnection;
      
      public class MyInterceptor implements AmqpInterceptor
      {
        private final int ACCEPTABLE_SIZE = 1024;
      
        @Override
        public boolean intercept(final AMQPMessage message, RemotingConnection connection)
        {
          int size = message.getEncodeSize();
          if (size <= ACCEPTABLE_SIZE) {
            System.out.println("This AMQPMessage has an acceptable size.");
            return true;
          }
          return false;
        }
      }
    • 如果您使用的是核心协议,您的拦截器必须实现 org.apache.artemis.activemq.api.core.Interceptor 接口。

      package com.example;
      
      import org.apache.artemis.activemq.api.core.Interceptor;
      import org.apache.activemq.artemis.core.protocol.core.Packet;
      import org.apache.activemq.artemis.spi.core.protocol.RemotingConnection;
      
      public class MyInterceptor implements Interceptor
      {
        private final int ACCEPTABLE_SIZE = 1024;
      
        @Override
        boolean intercept(Packet packet, RemotingConnection connection)
        throws ActiveMQException
        {
          int size = packet.getPacketSize();
          if (size <= ACCEPTABLE_SIZE) {
            System.out.println("This Packet has an acceptable size.");
            return true;
          }
          return false;
        }
      }
    • 如果您使用的是 MQTT 协议,请实施 org.apache.activemq.artemis.core.protocol.mqtt.MQTTInterceptor 接口。

      package com.example;
      
      import org.apache.activemq.artemis.core.protocol.mqtt.MQTTInterceptor;
      import io.netty.handler.codec.mqtt.MqttMessage;
      import org.apache.activemq.artemis.spi.core.protocol.RemotingConnection;
      
      public class MyInterceptor implements Interceptor
      {
        private final int ACCEPTABLE_SIZE = 1024;
      
        @Override
        boolean intercept(MqttMessage mqttMessage, RemotingConnection connection)
        throws ActiveMQException
        {
          byte[] msg = (mqttMessage.toString()).getBytes();
          int size = msg.length;
          if (size <= ACCEPTABLE_SIZE) {
            System.out.println("This MqttMessage has an acceptable size.");
            return true;
          }
          return false;
        }
      }
    • 如果您使用 STOMP 协议,请实施 org.apache.activemq.artemis.core.protocol.stomp.StompFrameInterceptor 接口。

      package com.example;
      
      import org.apache.activemq.artemis.core.protocol.stomp.StompFrameInterceptor;
      import org.apache.activemq.artemis.core.protocol.stomp.StompFrame;
      import org.apache.activemq.artemis.spi.core.protocol.RemotingConnection;
      
      public class MyInterceptor implements Interceptor
      {
        private final int ACCEPTABLE_SIZE = 1024;
      
        @Override
        boolean intercept(StompFrame stompFrame, RemotingConnection connection)
        throws ActiveMQException
        {
          int size = stompFrame.getEncodedSize();
          if (size <= ACCEPTABLE_SIZE) {
            System.out.println("This StompFrame has an acceptable size.");
            return true;
          }
          return false;
        }
      }

11.2. 将代理配置为使用 Interceptors

创建拦截器后,您必须配置代理来使用它。

先决条件

您必须创建一个拦截器类,并将其(及其依赖软件包)添加到代理的 Java 类路径中,然后才能将其配置为代理使用。由于 <broker_instance_dir> /lib 目录默认是类路径的一部分,因此可以使用 & lt;broker_instance_dir> /lib 目录。

流程

  • 通过在 <broker_instance_dir> /etc/broker.xml中添加配置,将代理配置为使用拦截器

    • 如果您的拦截器旨在传入邮件,请将其 class -name 添加到远程交互器 列表中。

      <configuration>
        <core>
          ...
          <remoting-incoming-interceptors>
             <class-name>org.example.MyIncomingInterceptor</class-name>
          </remoting-incoming-interceptors>
          ...
        </core>
      </configuration>
    • 如果您的拦截器用于传出消息,请将其 class-name 添加到 remoting-out-interceptors 列表中。

      <configuration>
        <core>
          ...
          <remoting-outgoing-interceptors>
             <class-name>org.example.MyOutgoingInterceptor</class-name>
          </remoting-outgoing-interceptors>
        </core>
      </configuration>

其它资源

  • 要了解如何在 AMQ 核心协议 JMS 客户端中配置拦截器,请参阅 AMQ 核心协议 JMS 文档中的 使用消息拦截器

第 12 章 转换消息和分割消息流

在 AMQ Broker 中,您可以配置名为偏 移的对象, 以便您可以透明地将消息从一个地址转移到另一个地址,而无需更改任何客户端应用程序逻辑。您还可以配置一个转换,将消息 副本 转发到指定的转发地址,从而有效地分割消息流。

12.1. 邮件如何改变工作

转换可让您透明地将路由到某个其他地址的消息转移到某个其他地址,而不更改任何客户端应用逻辑。考虑将代理服务器上的移动作为消息的路由表类型。

转换可以是 独占 的,即消息会转移到指定的转发地址,而不转至其原始地址。

转换也可能不是 独占 性的,这意味着消息继续转至其原始地址,而代理会将消息副本发送到指定的转发地址。因此,您可以使用非独占偏移来分割消息流。例如,如果您想单独监控发送到订单队列的每个顺序,您可以分割消息流。

当地址同时配置了排他性和非独占性时,代理会首先处理独占性转换。如果某一特定消息已被排解,代理不会处理针对该消息的任何非排他性转变。在这种情况下,邮件永远不会发送到原始地址。

当代理转换消息时,代理会分配一个新的消息 ID,并将消息地址设置为新的转发地址。您可以通过 _AMQ_ORIG_ ADDRESS(字符串类型)和 _AMQ_ORIG_ MESSAGE_ID (长类型)消息属性来检索原始消息 ID 和地址值。如果您使用 Core API,请使用 Message.HDR_ORIGINAL_ADDRESSMessage.HDR_ORIG_MESSAGE_ID 属性。

注意

您只能将消息传送到同一代理服务器上的地址。如果您想转用其他服务器上的地址,常见的解决方案是首先将消息转移到本地存储转发队列。然后,设置一个使用来自该队列的桥接,并将消息转发到不同代理上的地址。通过将转换与网桥相结合,您可以在地理分布式代理服务器之间创建路由连接的分布式网络。这样,您可以创建一个全局消息传递网格。

12.2. 配置消息会引发问题

要在代理实例中配置转变,请在 broker.xml 配置文件 的核心 元素中添加一个转变元素。

<core>
...
   <divert name= >
        <address> </address>
        <forwarding-address> </forwarding-address>
        <filter string= >
        <routing-type> </routing-type>
        <exclusive> </exclusive>
   </divert>
...
</core>
颠覆性
移动的命名实例.您可以向 broker.xml 配置文件添加多个转换 元素,只要每个元素都有唯一的名称。
地址
从中转 邮件的地址
forwarding-address
要转发 邮件的地址
filter
可选的消息过滤器.如果您配置过滤器,则只会引发与过滤器字符串匹配的消息。如果没有指定过滤器,则所有消息都被视为匹配项。
routing-type

转变的消息的路由类型。您可以配置转向:

  • anycast 或多 路由类型应用到消息
  • 离(即,删除)现有的路由类型
  • 通过 (即,保留)现有的路由类型

当消息已设置了路由类型时,路由类型的控制很有用,但您想要将消息转移到使用不同路由类型的地址。例如,代理无法将带有 anycast 路由类型的消息路由到使用 多播 的队列,除非您将传送 的 routing-type 参数设置为 MULTICAST。转换的 routing-type 参数的有效值为 ANYCASTMULTICASTPASSSTRIP。默认值为 STRIP

exclusive
指定转变是排他性(将属性设为 true)还是非专用(将属性设为 false)。

以下小节显示了独占和非独占性转变的配置示例。

12.2.1. 排他性转变示例

下面是独占偏移的配置示例。独家转义会将来自最初配置的地址的所有匹配消息转移到新地址。匹配的消息不会路由到原始地址。

<divert name="prices-divert">
   <address>priceUpdates</address>
   <forwarding-address>priceForwarding</forwarding-address>
   <filter string="office='New York'"/>
   <exclusive>true</exclusive>
</divert>

在前面的示例中,您定义了一个名为 price -divert 的转变,它将发送至地址 价格更新的所有 消息移至另一个本地地址 Pre warding。您还要指定一个消息过滤器字符串。只有消息属性 office 和值为 New York 的消息才会被转移。所有其他消息都将路由到其原始地址。最后,您指定这种转变是排他性的。

12.2.2. 非独有转变示例

下面是非独家移动的配置示例。在非独家转移中,消息继续转至其原始地址,代理也会将消息副本发送到指定的转发地址。因此,非独占性转换是一种分割消息流的方法。

<divert name="order-divert">
   <address>orders</address>
   <forwarding-address>spyTopic</forwarding-address>
   <exclusive>false</exclusive>
</divert>

在前面的示例中,您定义了一个被称为 order-divert 的转变,它获取发送到地址 订单 的每个邮件的副本,并将其发送到名为 spy Topic 的本地地址。您还要指定,转变是非独家的。

其它资源

有关使用排他和非独占性移动的详细示例,以及将消息转发到另一个代理的桥接,请参阅 Divert Example (外部)。

第 13 章 过滤消息

AMQ Broker 提供了强大的过滤器语言,它基于 SQL 92 表达式语法的子集。过滤器语言使用的语法与 JMS 选择器相同,但预定义的标识符是不同的。下表列出了应用到 AMQ Broker 消息的标识符。

标识符属性

AMQPriority

消息的优先级。消息优先级是具有从 09 的有效值的整数。0 是最低优先级,9 是最高优先级。

AMQExpiration

消息的过期时间。该值是一个长整数。

AMQDurable

消息是否持久.该值是一个字符串。有效值为 DUR ABLE 或 NON_DURABLE

AMQTimestamp

创建消息时的时间戳。该值是一个长整数。

AMQSize

消息的 encodeSize 属性的值。encode Size 的值是消息在日志中占用的空间(以字节为单位)。由于代理使用双字节字符集对消息进行编码,消息的实际大小为 encode Size 值的一半。

核心过滤器表达式中使用的任何其他标识符均假定为消息的属性。有关 JMS 消息选择器语法的文档,请参见 Java EE API

13.1. 配置队列以使用过滤器

您可以在 <broker_instance_dir> /etc/broker.xml 中配置的队列中添加过滤器。只有与过滤器表达式匹配的消息进入队列。

流程

  • filter 元素添加到所需 队列 中,并包含您要应用的过滤器作为元素的值。在以下示例中,过滤器 NEWS='tech' 被添加到队列 技术队列中。

    <configuration>
      <core>
        ...
        <addresses>
            <address name="myQueue">
               <anycast>
                  <queue name="myQueue">
                    <filter string="NEWS='technology'"/>
                  </queue>
               </anycast>
            </address>
         </addresses>
       </core>
    </configuration>

13.2. 过滤 JMS 消息属性

JMS 规范指出,在选择器中使用时,String 属性不能转换为数字类型。例如,如果消息的 age 属性设置为 String 值 21,则选择器 age > 18 必须与它不匹配。此限制限制 STOMP 客户端,因为它们只能使用 String 属性发送消息。

配置 Filter 以将字符串转换为数字

要将 String 属性转换为数字类型,请将前缀 convert_string_expressions: 添加到 过滤器 的值。

流程

  • 通过将前缀 convert_string _expressions: 应用到所需 过滤器 来编辑 <broker_instance_dir> / etc/broker.xml。以下示例编辑 age > 18 的过滤器 值以 convert_string_expressions:age > 18

    <configuration>
      <core>
        ...
        <addresses>
            <address name="myQueue">
               <anycast>
                  <queue name="myQueue">
                    <filter string="convert_string_expressions='age > 18'"/>
                  </queue>
               </anycast>
            </address>
         </addresses>
       </core>
    </configuration>

13.3. 根据注解上的属性过滤 AMQP 消息

在代理将过期或未交付的 AMQP 消息移至您配置的过期或死信队列之前,代理会将注释和属性应用到消息。客户端可以根据属性或注释创建过滤器,从到期或死信队列中选择要使用的特定消息。

注意

代理应用的属性是 内部 属性,这些属性不向客户端公开以供常规使用,但 可以由 过滤器中的客户端指定。

以下是基于消息属性和注释的过滤器示例。建议尽可能根据属性进行过滤,因为这种方法需要较少的代理处理。

基于消息属性过滤

ConnectionFactory factory = new JmsConnectionFactory("amqp://localhost:5672");
Connection connection = factory.createConnection();
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
connection.start();
javax.jms.Queue queue = session.createQueue("my_DLQ");
MessageConsumer consumer = session.createConsumer(queue, "_AMQ_ORIG_ADDRESS='original_address_name'");
Message message = consumer.receive();

基于消息注解进行过滤

ConnectionFactory factory = new JmsConnectionFactory("amqp://localhost:5672");
Connection connection = factory.createConnection();
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
connection.start();
javax.jms.Queue queue = session.createQueue("my_DLQ");
MessageConsumer consumer = session.createConsumer(queue, "\"m.x-opt-ORIG-ADDRESS\"='original_address_name'");
Message message = consumer.receive();

注意

在使用基于注释的 AMQP 消息时,客户端必须将 m. 前缀附加到消息注释,如上例中所示。

其它资源

13.4. 过滤 XML 消息

AMQ Broker 提供了过滤文本消息的方法,该消息包含使用 XPath 的 XML 正文。XPath(XML 路径语言)是用于从 XML 文档中选择节点的查询语言。

注意

仅支持基于文本的消息。不支持过滤大量消息。

要过滤基于文本的信息,您需要创建一个 XPATH '<xpath-expression> 格式的 Message Selector。

消息正文示例

<root>
    <a key='first' num='1'/>
    <b key='second' num='2'>b</b>
</root>

基于 XPath 查询进行过滤

PATH 'root/a'

警告

由于 XPath 适用于消息的正文并需要解析 XML,因此过滤可能比一般的过滤器要慢得多。

使用以下协议支持与生产者和消费者一同使用 XPath 过滤器:

  • OpenWire JMS
  • core(和核心 JMS)
  • STOMP
  • AMQP

配置 XML 解析器

默认情况下,代理使用的 XML Parser 是 JDK 使用的平台默认 DocumentBuilderFactory 实例。

用于 XPath 默认配置的 XML 解析器包括以下设置:

但是,为了处理任何特定于实施的问题,可以通过在 artemis.profile 配置文件中配置系统属性来自定义功能。

org.apache.activemq.documentBuilderFactory.feature:prefix

功能配置示例

-Dorg.apache.activemq.documentBuilderFactory.feature:http://xml.org/sax/features/external-general-entities=true

第 14 章 设置代理集群

集群由多个代理实例组成,这些代理实例分组在一起。代理集群通过在多个代理间分布消息处理负载来提高性能。此外,代理集群可通过高可用性最大限度地减少停机时间。

您可以在许多不同的集群拓扑中将代理连接在一起。在集群中,每个活跃代理管理自己的消息并处理自己的连接。

您还可以平衡集群中的客户端连接并重新分发消息,以避免代理不足。

14.1. 了解代理集群

在创建代理集群前,您应该了解一些重要的集群概念。

14.1.1. 代理集群均衡消息负载

当代理被连接组成集群时,AMQ Broker 会自动在代理之间平衡消息负载。这样可确保集群能够维护高消息吞吐量。

考虑由四个代理组成的对称集群。每个代理都配置了一个名为 OrderQueue 的队列。OrderProducer 客户端连接到 Broker1,并将消息发送到 OrderQueueBroker1 以轮循方式将消息转发到其他代理。连接到各个代理的 OrderConsumer 客户端会使用消息。确切的顺序取决于代理的启动顺序。

图 14.1. 消息负载平衡

在集群中的代理间平衡消息

如果没有消息负载均衡,发送到 Broker1 的消息将保留在 Broker1 中,只有 OrderConsumer1 才可以使用它们。

虽然 AMQ Broker 默认自动对信息进行负载均衡,但您可以配置:

  • 用于向具有匹配队列的代理平衡消息的集群。
  • 集群用于向具有与活跃使用者匹配队列的代理平衡消息。
  • 群集以不进行负载平衡,而是执行从没有使用者到有使用者队列的队列中重新分发消息。
  • 个地址,用于自动重新分发队列中不包含任何消费者的具有消费者的队列的消息。

其它资源

14.1.2. 代理集群如何提高可靠性

代理集群使高可用性和故障转移成为可能,这使其比独立代理更可靠。通过配置高可用性,您可以确保客户端应用程序可以继续发送和接收消息,即使代理遇到故障事件。

借助高可用性,集群中的代理被分组为 live-backup 组。live-backup 组包括服务客户端请求的 live 代理,以及一个或多个被动等待替换 live 代理(如果 live 代理失败)的备份代理。如果发生故障,备份代理将替换其 live-backup 组中的 live 代理,客户端重新连接并继续工作。

14.1.3. 了解节点 ID

代理 节点 ID 是首次创建并初始化代理实例日志时,以编程方式生成的全局唯一标识符(GUID)。节点 ID 存储在 server.lock 文件中。节点 ID 用于唯一标识代理实例,无论代理是独立实例还是集群的一部分。实时备份代理对共享相同的节点 ID,因为它们共享相同的日志。

在代理集群中,代理实例(节点)互相连接,并创建网桥和内部"存储转发"队列。这些内部队列的名称基于其他代理实例的节点 ID。代理实例还会监控集群广播中与自己的节点 ID 匹配的节点 ID。如果代理标识了重复的 ID,则代理会在日志中生成警告消息。

当您使用复制高可用性(HA)策略时,启动并会将 check-live-server 设置为 true 的 master 代理会搜索正在使用其节点 ID 的代理。如果 master 代理使用相同的节点 ID 找到另一个代理,它不会启动,或者会根据 HA 配置启动故障恢复。

节点 ID 持久化,即代理重启后它保留下来。但是,如果您删除了代理实例(包括其日志),则节点 ID 也会被永久删除。

其它资源

14.1.4. 通用代理集群拓扑

您可以连接代理形成 对称 集群拓扑。您实施的拓扑取决于您的环境和消息传递要求。

对称集群

在对称集群中,每个代理都连接到所有其他代理。这意味着每个代理不会超过一个与其他代理的跃点。

图 14.2. 对称集群

在 4broker 对称集群中,每个代理都连接到其他代理

对称集群中的每个代理都了解集群中所有其他代理上存在的所有队列,以及侦听这些队列的用户。因此,对称集群可以比链集群更优地负载平衡和重新分发消息。

对称集群比链集群更容易设置,但可能很难在网络限制阻止代理被直接连接的环境中使用。

链集群

在链集群中,集群中的每个代理都不直接连接到集群中的每个代理。相反,代理形成一个链,在链的每个端都有一个代理,所有其他代理都只连接到链中的之前和下一个代理。

图 14.3. 链集群

在一个四代理链集群中,代理被连接在一个链中

链集群比对称集群更难设置,但当代理位于单独的网络中且无法直接连接时,可以使用。通过使用链集群,中间代理可以间接连接两个代理,使消息在它们之间流动,即使两个代理没有直接连接。

14.1.5. 代理发现方法

发现是集群中的代理相互传播其连接详情的机制。AMQ Broker 支持 动态发现和 静态发现

动态发现

群集中的每个代理通过 UDP 多播或 JGroups 将其连接设置广播给其他成员。在这个方法中,每个代理使用:

  • 广播组,将有关其集群连接的信息推送到集群的其他潜在成员。
  • 个用于接收和存储集群中其他代理的集群连接信息的 发现组
静态发现

如果您无法在网络中使用 UDP 或 JGroups,或者要手动指定群集的每个成员,您可以使用静态发现。在这个方法中,一个代理"加入"集群的方式是连接到第二个代理并发送其连接详情。然后,第二个代理将这些详情传播到集群中的其他代理。

14.1.6. 集群大小注意事项

在创建代理集群前,请考虑消息传递吞吐量、拓扑和高可用性要求。这些因素会影响集群中要包括的代理数量。

注意

创建集群后,您可以通过添加和删除代理来调整大小。您可以在不丢失任何信息的情况下添加和删除代理。

消息传递吞吐量

集群应包含足够的代理,以提供您需要的消息传递吞吐量。集群中的代理越多,吞吐量越高。但是,大型集群可能难以管理。

Topology

您可以创建对称集群或链集群。您选择的拓扑类型会影响您可能需要的代理数量。

如需更多信息,请参阅 第 14.1.4 节 “通用代理集群拓扑”

高可用性

如果您需要高可用性(HA),请在创建集群前考虑选择 HA 策略。HA 策略会影响集群的大小,因为每个 master 代理应至少有一个从代理。

如需更多信息,请参阅 第 14.3 节 “实施高可用性”

14.2. 创建代理集群

您可以通过在应加入集群的每个代理上配置集群连接来创建代理集群。集群连接定义了代理应该如何连接到其他代理。

您可以创建一个使用静态发现或动态发现的代理集群(UDP 多播或 JGroups)。

先决条件

14.2.1. 创建带有静态发现的代理集群

您可以通过指定代理的静态列表来创建代理集群。如果您无法在网络上使用 UDP 多播或 JGroups,请使用这个静态发现方法。

流程

  1. 打开 <broker_instance_dir>/etc/broker.xml 配置文件。
  2. <core> 元素中,添加以下连接器:

    • 定义其他代理如何连接到这个连接器
    • 一个或多个用来定义这个代理如何连接到集群中的其他代理的连接器
    <configuration>
        <core>
            ...
            <connectors>
                <connector name="netty-connector">tcp://localhost:61617</connector>  1
                <connector name="broker2">tcp://localhost:61618</connector>  2
                <connector name="broker3">tcp://localhost:61619</connector>
            </connectors>
            ...
        </core>
    </configuration>
    1
    此连接器定义了其他代理可用于连接此连接信息的连接信息。此信息会在发现过程中发送到集群中的其他代理。
    2
    broker2broker3 连接器定义了此代理如何连接到集群中的另外两个代理,其中一个将始终可用。如果集群中存在其他代理,则在进行初始连接时,其中一个连接器会发现它们。

    有关连接器的详情请参考 第 2.3 节 “关于连接器”

  3. 添加集群连接并将其配置为使用静态发现。

    默认情况下,集群连接将对对称拓扑中所有地址的消息进行负载均衡。

    <configuration>
        <core>
            ...
            <cluster-connections>
                <cluster-connection name="my-cluster">
                    <connector-ref>netty-connector</connector-ref>
                    <static-connectors>
                        <connector-ref>broker2-connector</connector-ref>
                        <connector-ref>broker3-connector</connector-ref>
                    </static-connectors>
                </cluster-connection>
            </cluster-connections>
            ...
        </core>
    </configuration>
    cluster-connection
    使用 name 属性指定集群连接的名称。
    connector-ref
    定义其他代理如何连接到这个连接器的连接器。
    static-connectors
    此代理可用于与集群中的其他代理进行初始连接的一个或多个连接器。建立此初始连接后,代理将发现集群中的其他代理。只有在集群使用静态发现时,才需要配置此属性。
  4. 为集群连接配置任何附加属性。

    这些额外的集群连接属性具有适合大多数常见用例的默认值。因此,当您不想默认行为时,您只需要配置这些属性。如需更多信息,请参阅 附录 C, 集群连接配置元素

  5. 创建集群用户和密码。

    AMQ Broker 附带默认集群凭证,但您应该更改这些凭证以防止未经授权的远程客户端使用这些默认凭证连接到代理。

    重要

    群集密码必须在集群中的每个代理上都相同。

    <configuration>
        <core>
            ...
            <cluster-user>cluster_user</cluster-user>
            <cluster-password>cluster_user_password</cluster-password>
            ...
        </core>
    </configuration>
  6. 对每个其他代理重复此步骤。

    您可以将集群配置复制到每个额外代理中。但是,请勿复制任何其他 AMQ 代理数据文件(如绑定、日志和大型消息目录)。这些文件必须在群集中的节点之间唯一,否则群集无法正确组成。

其它资源

14.2.2. 使用基于 UDP 的动态发现创建代理集群

您可以在其中创建一个代理集群,代理集群通过 UDP 多播动态发现彼此。

流程

  1. 打开 <broker_instance_dir>/etc/broker.xml 配置文件。
  2. <core> 元素中添加连接器。

    此连接器定义了其他代理可用于连接此连接信息的连接信息。此信息会在发现过程中发送到集群中的其他代理。

    <configuration>
        <core>
            ...
            <connectors>
                <connector name="netty-connector">tcp://localhost:61617</connector>
            </connectors>
            ...
        </core>
    </configuration>
  3. 添加 UDP 广播组。

    广播组可让代理将有关集群连接的信息推送到集群中的其他代理。这个广播组使用 UDP 来广播连接设置:

    <configuration>
        <core>
            ...
            <broadcast-groups>
                <broadcast-group name="my-broadcast-group">
                    <local-bind-address>172.16.9.3</local-bind-address>
                    <local-bind-port>-1</local-bind-port>
                    <group-address>231.7.7.7</group-address>
                    <group-port>9876</group-port>
                    <broadcast-period>2000</broadcast-period>
                    <connector-ref>netty-connector</connector-ref>
                </broadcast-group>
            </broadcast-groups>
            ...
        </core>
    </configuration>

    除非另有说明,否则需要以下参数:

    broadcast-group
    使用 name 属性为广播组指定唯一的名称。
    local-bind-address
    绑定 UDP 套接字的地址。如果您在代理中有多个网络接口,您应该指定您要用于广播的网络接口。如果未指定此属性,套接字将绑定到操作系统选择的 IP 地址。这是与 UDP 相关的属性。
    local-bind-port
    数据报套接字绑定的端口。在大多数情况下,使用默认值 -1,它指定匿名端口。此参数用于与 local-bind-address 连接。这是与 UDP 相关的属性。
    group-address
    数据要广播的多播地址。它是 224.0.0.0 - 239.255.255 范围中的 D IP 地址。地址 224.0.0.0 已保留,不能使用。这是与 UDP 相关的属性。
    group-port
    用于广播的 UDP 端口号。这是与 UDP 相关的属性。
    broadcast-period (可选)
    连续广播之间的间隔,以毫秒为单位。默认值为 2000 毫秒。
    connector-ref
    之前配置的群集连接器应广播。
  4. 添加 UDP 发现组。

    发现组定义此代理如何从其他代理接收连接器信息。代理维护连接器列表(每个代理一个条目)。当它从代理接收广播时,它会更新其条目。如果从代理接收广播的时间段长,它会删除该条目。

    这个发现组使用 UDP 来发现集群中的代理:

    <configuration>
        <core>
            ...
            <discovery-groups>
                <discovery-group name="my-discovery-group">
                    <local-bind-address>172.16.9.7</local-bind-address>
                    <group-address>231.7.7.7</group-address>
                    <group-port>9876</group-port>
                    <refresh-timeout>10000</refresh-timeout>
                </discovery-group>
            <discovery-groups>
            ...
        </core>
    </configuration>

    除非另有说明,否则需要以下参数:

    discovery-group
    使用 name 属性为发现组指定唯一的名称。
    local-bind-address (可选)
    如果运行代理的机器使用多个网络接口,您可以指定发现组应侦听的网络接口。这是与 UDP 相关的属性。
    group-address
    要监听的组的多播地址。它应与您要从中侦听的广播组中的 group-address 匹配。这是与 UDP 相关的属性。
    group-port
    多播组的 UDP 端口号。它应与您要从中侦听的广播组中的 group-port 匹配。这是与 UDP 相关的属性。
    refresh-timeout (可选)

    在从特定代理中删除代理连接器对条目前,发现组在从特定代理接收最后一次广播后等待的时间,以毫秒为单位。默认值为 10000 毫秒(10 秒)。

    将它设置为比广播组中的 broadcast-period 高得多的值。否则,代理可能会定期从列表中消失(即使它们仍在广播)(因为时间稍有差异)。

  5. 创建集群连接并将其配置为使用动态发现。

    默认情况下,集群连接将对对称拓扑中所有地址的消息进行负载均衡。

    <configuration>
        <core>
            ...
            <cluster-connections>
                <cluster-connection name="my-cluster">
                    <connector-ref>netty-connector</connector-ref>
                    <discovery-group-ref discovery-group-name="my-discovery-group"/>
                </cluster-connection>
            </cluster-connections>
            ...
        </core>
    </configuration>
    cluster-connection
    使用 name 属性指定集群连接的名称。
    connector-ref
    定义其他代理如何连接到这个连接器的连接器。
    discovery-group-ref
    此代理应该用来查找群集其他成员的发现组。仅当集群使用动态发现时,才需要配置此属性。
  6. 为集群连接配置任何附加属性。

    这些额外的集群连接属性具有适合大多数常见用例的默认值。因此,当您不想默认行为时,您只需要配置这些属性。如需更多信息,请参阅 附录 C, 集群连接配置元素

  7. 创建集群用户和密码。

    AMQ Broker 附带默认集群凭证,但您应该更改这些凭证以防止未经授权的远程客户端使用这些默认凭证连接到代理。

    重要

    群集密码必须在集群中的每个代理上都相同。

    <configuration>
        <core>
            ...
            <cluster-user>cluster_user</cluster-user>
            <cluster-password>cluster_user_password</cluster-password>
            ...
        </core>
    </configuration>
  8. 对每个其他代理重复此步骤。

    您可以将集群配置复制到每个额外代理中。但是,请勿复制任何其他 AMQ 代理数据文件(如绑定、日志和大型消息目录)。这些文件必须在群集中的节点之间唯一,否则群集无法正确组成。

其它资源

14.2.3. 使用基于 JGroups 的动态发现创建代理集群

如果您的环境中已在使用 JGroups,您可以使用它来创建代理集群,在其中代理会动态发现对方。

先决条件

流程

  1. 打开 <broker_instance_dir>/etc/broker.xml 配置文件。
  2. <core> 元素中添加连接器。

    此连接器定义了其他代理可用于连接此连接信息的连接信息。此信息会在发现过程中发送到集群中的其他代理。

    <configuration>
        <core>
            ...
            <connectors>
                <connector name="netty-connector">tcp://localhost:61617</connector>
            </connectors>
            ...
        </core>
    </configuration>
  3. <core> 元素中添加 JGroups 广播组。

    广播组可让代理将有关集群连接的信息推送到集群中的其他代理。这个广播组使用 JGroups 来广播连接设置:

    <configuration>
        <core>
            ...
            <broadcast-groups>
                <broadcast-group name="my-broadcast-group">
                    <jgroups-file>test-jgroups-file_ping.xml</jgroups-file>
                    <jgroups-channel>activemq_broadcast_channel</jgroups-channel>
                    <broadcast-period>2000</broadcast-period>
                    <connector-ref>netty-connector</connector-ref>
                </broadcast-group>
            </broadcast-groups>
            ...
        </core>
    </configuration>

    除非另有说明,否则需要以下参数:

    broadcast-group
    使用 name 属性为广播组指定唯一的名称。
    jgroups-file
    用于初始化 JGroups 频道的 JGroups 配置文件的名称。文件必须位于 Java 资源路径中,以便代理可以加载它。
    jgroups-channel
    要连接进行广播的 JGroups 通道的名称。
    broadcast-period (可选)
    连续广播之间的间隔,以毫秒为单位。默认值为 2000 毫秒。
    connector-ref
    之前配置的群集连接器应广播。
  4. 添加 JGroups 发现组。

    发现组定义如何接收连接器信息。代理维护连接器列表(每个代理一个条目)。当它从代理接收广播时,它会更新其条目。如果从代理接收广播的时间段长,它会删除该条目。

    此发现组使用 JGroups 来发现集群中的代理:

    <configuration>
        <core>
            ...
            <discovery-groups>
                <discovery-group name="my-discovery-group">
                    <jgroups-file>test-jgroups-file_ping.xml</jgroups-file>
                    <jgroups-channel>activemq_broadcast_channel</jgroups-channel>
                    <refresh-timeout>10000</refresh-timeout>
                </discovery-group>
            <discovery-groups>
            ...
        </core>
    </configuration>

    除非另有说明,否则需要以下参数:

    discovery-group
    使用 name 属性为发现组指定唯一的名称。
    jgroups-file
    用于初始化 JGroups 频道的 JGroups 配置文件的名称。文件必须位于 Java 资源路径中,以便代理可以加载它。
    jgroups-channel
    用于接收广播的 JGroups 频道名称。
    refresh-timeout (可选)

    在从特定代理中删除代理连接器对条目前,发现组在从特定代理接收最后一次广播后等待的时间,以毫秒为单位。默认值为 10000 毫秒(10 秒)。

    将它设置为比广播组中的 broadcast-period 高得多的值。否则,代理可能会定期从列表中消失(即使它们仍在广播)(因为时间稍有差异)。

  5. 创建集群连接并将其配置为使用动态发现。

    默认情况下,集群连接将对对称拓扑中所有地址的消息进行负载均衡。

    <configuration>
        <core>
            ...
            <cluster-connections>
                <cluster-connection name="my-cluster">
                    <connector-ref>netty-connector</connector-ref>
                    <discovery-group-ref discovery-group-name="my-discovery-group"/>
                </cluster-connection>
            </cluster-connections>
            ...
        </core>
    </configuration>
    cluster-connection
    使用 name 属性指定集群连接的名称。
    connector-ref
    定义其他代理如何连接到这个连接器的连接器。
    discovery-group-ref
    此代理应该用来查找群集其他成员的发现组。仅当集群使用动态发现时,才需要配置此属性。
  6. 为集群连接配置任何附加属性。

    这些额外的集群连接属性具有适合大多数常见用例的默认值。因此,当您不想默认行为时,您只需要配置这些属性。如需更多信息,请参阅 附录 C, 集群连接配置元素

  7. 创建集群用户和密码。

    AMQ Broker 附带默认集群凭证,但您应该更改这些凭证以防止未经授权的远程客户端使用这些默认凭证连接到代理。

    重要

    群集密码必须在集群中的每个代理上都相同。

    <configuration>
        <core>
            ...
            <cluster-user>cluster_user</cluster-user>
            <cluster-password>cluster_user_password</cluster-password>
            ...
        </core>
    </configuration>
  8. 对每个其他代理重复此步骤。

    您可以将集群配置复制到每个额外代理中。但是,请勿复制任何其他 AMQ 代理数据文件(如绑定、日志和大型消息目录)。这些文件必须在群集中的节点之间唯一,否则群集无法正确组成。

其它资源

14.3. 实施高可用性

您可以通过实施高可用性(HA)提高可靠性,使代理集群即使在一个或多个代理离线时仍能继续工作。

实施 HA 涉及几个步骤:

  1. 为您的 HA 实施配置代理集群,如 第 14.2 节 “创建代理集群” 所述。
  2. 您应该了解什么是实时备份组,然后选择最能满足您需求的 HA 策略。请参阅 了解 HA 在 AMQ Broker 中的工作方式
  3. 当您选择了合适的 HA 策略时,在集群中的每个代理上配置 HA 策略。请参阅:

  4. 配置您的客户端应用以使用故障转移
注意

在后续情况下,您需要对配置了高可用性的代理集群进行故障排除,建议您为在集群中运行代理的每个 Java 虚拟机(JVM)实例启用 Garbage Collection(GC)日志记录。要了解如何在 JVM 上启用 GC 日志,请参阅 JVM 使用的 Java Development Kit(JDK)版本的官方文档。如需有关 AMQ 代理支持的 JVM 版本的更多信息,请参阅 Red Hat AMQ 7 支持的配置

14.3.1. 了解高可用性

在 AMQ Broker 中,您可以通过将集群中的代理分组到 live-backup 组 来实现高可用性(HA)。在 live-backup 组中,实时代理链接到备份代理,如果 live 代理失败,该代理可以接管该代理。AMQ 代理还为实时备份组中的故障切换(称为 HA 策略)提供多个不同的策略

14.3.1.1. 实时备份组如何提供高可用性

在 AMQ Broker 中,您可以通过链接集群中的代理组成 live-backup 组 来实现高可用性(HA)。实时备份组提供 故障转移,这意味着如果一个代理出现故障,另一个代理可以接管其消息处理。

实时备份组由一个实时代理(有时称为 代理)组成,链接到一个或多个备份代理(有时称为 slave 代理)。live 代理服务客户端请求,备份代理以被动模式等待。如果 live 代理失败,备份代理将替换 live 代理,使客户端能够重新连接并继续工作。

14.3.1.2. 高可用性策略

高可用性(HA)策略定义实时备份组中如何发生故障转移。AMQ 代理提供多个不同的 HA 策略:

共享存储(推荐)

实时和备份代理将其消息传递数据存储在共享文件系统上的通用目录中,通常是存储区域网络(SAN)或网络文件系统(NFS)服务器。如果您配置了基于 JDBC 的持久性,您还可以将代理数据存储在指定的数据库中。使用共享存储时,如果 live 代理失败,备份代理会从共享存储中加载消息数据,并接管失败的实时代理。

在大多数情况下,您应该使用共享存储而不是复制。由于共享存储不会通过网络复制数据,它通常比复制提供更好的性能。共享存储还可避免出现实时代理及其备份同时现场出现的网络隔离(也称为"脑裂")问题。

在共享存储 HA 策略中,实时和备份代理会从共享位置访问日志。
复制

实时和备份代理不断通过网络同步其消息传递数据。如果 live 代理失败,备份代理会加载同步的数据并接管失败的实时代理。

实时和备份代理之间的数据同步可确保在实时代理失败时不会丢失消息传递数据。当实时和备份代理最初一起时,实时代理会通过网络将其所有现有数据复制到备份代理。完成这个初始阶段后,实时代理会在实时代理接收数据时将持久数据复制到备份代理。这意味着,如果 live 代理丢弃网络,备份代理会一直具有实时代理接收的所有持久性数据。

由于复制通过网络同步数据,因此网络故障可能会导致网络隔离,其中实时代理及其备份会同时上线。

在复制 HA 策略中,实时和备份代理通过网络将其日志相互同步。
仅实时(限 HA)

当一个实时代理被安全停止时,它会将其消息和事务状态复制到另一个实时代理中,然后关闭。然后客户端可以重新连接到其他代理,以继续发送和接收消息。

在实时 HA 策略中,代理将其消息和事务状态复制到另一个代理。

其它资源

14.3.1.3. 复制策略限制

网络隔离(有时称为"脑裂")是复制高可用性(HA)策略的一个限制。您应该了解它的发生方式以及如何避免它。

如果实时代理及其备份丢失连接,则可能会出现网络隔离。在这种情况下,实时代理及其备份可以同时处于活跃状态。特别是,如果备份代理仍然可以连接到集群中超过一半的 live 代理,它也会变为活跃状态。由于在这种情况下,代理之间没有消息复制,因此它们各自提供客户端和进程消息,而不知道它。在这种情况下,每个代理都有完全不同的日志。从这种情形中恢复可能非常困难,在某些情况下不可能。

要避免网络隔离,请考虑以下几点:

  • 为消除 网络隔离的可能性,请使用 共享存储 HA 策略。
  • 如果您使用复制 HA 策略,可以通过 至少使用三个实时备份对减少(但不消除)遇到网络隔离的几率。

    至少使用三个实时备份对可确保在出现复制中断时任何 仲裁票数 实现大多数结果。

以下是在使用复制 HA 策略时的一些额外注意事项:

  • 当实时代理失败且备份转换为实时时,在将新备份代理附加到实时或故障恢复到原始 live 代理前,不会再进行复制。
  • 如果 live-backup 组中的备份代理失败,live 代理将继续提供消息。但是,在添加其他代理作为备份或重启原始备份代理之前,消息不会复制。在该时间段内,信息只会保留至 live 代理。
  • 假设 live-backup 对中的两个代理之前都已关闭,但现在可以重新启动。在这种情况下,为了避免消息丢失,您需要首先重启最近活跃的代理。如果最新的活跃代理是 backup 代理,您需要手动重新配置这个代理作为 master 代理,以便首先重启它。

14.3.2. 配置共享存储高可用性

您可以使用共享存储高可用性(HA)策略在代理集群中实施 HA。使用共享存储时,实时和备份代理访问共享文件系统上的通用目录,通常是存储区域网络(SAN)或网络文件系统(NFS)服务器。如果您配置了基于 JDBC 的持久性,您还可以将代理数据存储在指定的数据库中。使用共享存储时,如果 live 代理失败,备份代理会从共享存储中加载消息数据,并接管失败的实时代理。

通常,SAN 比 NFS 服务器提供更好的性能(如速度),建议使用 选项(如果可用)。如果您需要使用 NFS 服务器,请参阅 Red Hat AMQ 7 支持的配置 以了解有关 AMQ 代理支持的网络文件系统的更多信息。

在大多数情况下,您应该使用共享存储 HA,而不是复制。由于共享存储不会通过网络复制数据,它通常比复制提供更好的性能。共享存储还可避免出现实时代理及其备份同时现场出现的网络隔离(也称为"脑裂")问题。

注意

使用共享存储时,备份代理的启动时间取决于消息日志的大小。当备份代理接管失败的实时代理时,它会从共享存储中加载日志。如果日志包含大量数据,此过程可能非常耗时。

14.3.2.1. 配置 NFS 共享存储

使用共享存储高可用性时,您必须将实时和备份代理配置为使用共享文件系统上的通用目录。通常,您使用存储区域网络(SAN)或者网络文件系统(NFS)服务器。

在您的每个代理机器实例上挂载 NFS 服务器导出的目录时,如下所列为一些推荐的配置选项。

sync
指定所有更改都会立即刷新到磁盘。
intr
如果服务器已关闭或无法访问,允许中断 NFS 请求。
noac
禁用属性缓存。在多个客户端之间实现属性缓存一致性需要此行为。
soft
指定如果 NFS 服务器不可用,应报告错误,而不是等待服务器恢复在线。
lookupcache=none
禁用查找缓存。
timeo=n
以秒为单位,NFS 客户端(即代理)在重试请求前会等待来自 NFS 服务器的响应。对于 NFS over TCP,默认的 timeo 值为 600 (60 秒)。对于 NFS over UDP,客户端使用自适应算法为常用请求类型(如读取和写入请求)估算适当的超时值。
retrans=n
NFS 客户端尝试进一步恢复操作前重试请求的次数。如果没有指定 retrans 选项,NFS 客户端会尝试每个请求三次。
重要

在配置 timeo 和重新传输 选项时,务必要使用合理的值。默认的 timeo 等待时间为 600 毫秒(60 秒),以及 重新传输 值 5 次重试可能会导致 AMQ Broker 检测到 NFS 断开连接。

其它资源

14.3.2.2. 配置共享存储高可用性

此流程演示了如何为代理集群配置共享存储高可用性。

先决条件

  • 共享存储系统必须可以被实时和备份代理访问。

流程

  1. 将集群中的代理分组到 live-backup 组。

    在大多数情况下,实时备份组应该由两个代理组成:实时代理和备份代理。如果集群中有六个代理,则需要三个 live-backup 组。

  2. 创建第一个由实时代理和一个备份代理组成的实时备份组。

    1. 打开 live 代理的 <broker_instance_dir>/etc/broker.xml 配置文件。
    2. 如果您使用:

      1. 用于提供共享存储的网络文件系统,验证实时代理的分页、绑定、日志和大型消息目录指向备份代理也可以访问的共享位置。

        <configuration>
            <core>
                ...
                <paging-directory>../sharedstore/data/paging</paging-directory>
                <bindings-directory>../sharedstore/data/bindings</bindings-directory>
                <journal-directory>../sharedstore/data/journal</journal-directory>
                <large-messages-directory>../sharedstore/data/large-messages</large-messages-directory>
                ...
            </core>
        </configuration>
      2. 用于提供共享存储的数据库,确保主代理和备份代理能够连接到同一数据库,并且具有在 broker.xml 配置文件 的数据库存储 元素中指定的相同配置。下面显示了一个配置示例:

        <configuration>
          <core>
            <store>
               <database-store>
                  <jdbc-connection-url>jdbc:oracle:data/oracle/database-store;create=true</jdbc-connection-url>
                  <jdbc-user>ENC(5493dd76567ee5ec269d11823973462f)</jdbc-user>
                  <jdbc-password>ENC(56a0db3b71043054269d11823973462f)</jdbc-password>
                  <bindings-table-name>BINDINGS_TABLE</bindings-table-name>
                  <message-table-name>MESSAGE_TABLE</message-table-name>
                  <large-message-table-name>LARGE_MESSAGES_TABLE</large-message-table-name>
                  <page-store-table-name>PAGE_STORE_TABLE</page-store-table-name>
                  <node-manager-store-table-name>NODE_MANAGER_TABLE<node-manager-store-table-name>
                  <jdbc-driver-class-name>oracle.jdbc.driver.OracleDriver</jdbc-driver-class-name>
                  <jdbc-network-timeout>10000</jdbc-network-timeout>
                  <jdbc-lock-renew-period>2000</jdbc-lock-renew-period>
                  <jdbc-lock-expiration>15000</jdbc-lock-expiration>
                  <jdbc-journal-sync-period>5</jdbc-journal-sync-period>
               </database-store>
            </store>
          </core>
        </configuration>
    3. 配置 live 代理,以将共享存储用于其 HA 策略。

      <configuration>
          <core>
              ...
              <ha-policy>
                  <shared-store>
                      <master>
                          <failover-on-shutdown>true</failover-on-shutdown>
                      </master>
                  </shared-store>
              </ha-policy>
              ...
          </core>
      </configuration>
      failover-on-shutdown
      如果这个代理被正常停止,这个属性会控制备份代理是否应该存活并接管。
    4. 打开备份代理的 <broker_instance_dir>/etc/broker.xml 配置文件。
    5. 如果您使用:

      1. 用于提供共享存储的网络文件系统,验证备份代理的分页、绑定、日志和大型消息目录指向与实时代理相同的共享位置。

        <configuration>
            <core>
                ...
                <paging-directory>../sharedstore/data/paging</paging-directory>
                <bindings-directory>../sharedstore/data/bindings</bindings-directory>
                <journal-directory>../sharedstore/data/journal</journal-directory>
                <large-messages-directory>../sharedstore/data/large-messages</large-messages-directory>
                ...
            </core>
        </configuration>
      2. 用于提供共享存储的数据库,确保主代理和备份代理能够连接到同一数据库,并且具有在 broker.xml 配置文件 的数据库存储 元素中指定的相同配置。
    6. 配置备份代理,将共享存储用于其 HA 策略。

      <configuration>
          <core>
              ...
              <ha-policy>
                  <shared-store>
                      <slave>
                          <failover-on-shutdown>true</failover-on-shutdown>
                          <allow-failback>true</allow-failback>
                          <restart-backup>true</restart-backup>
                      </slave>
                  </shared-store>
              </ha-policy>
              ...
          </core>
      </configuration>
      failover-on-shutdown
      如果这个代理已激活,然后被正常停止,则此属性将控制备份代理(原始 live 代理)是否处于活动状态并接管。
      allow-failback

      如果发生故障转移,并且备份代理接管了 live 代理,则此属性会控制备份代理在重启并重新连接到集群时是否应该恢复到原始 live 代理。

      注意

      故障恢复适用于实时备份对(一个实时代理与单个备份代理对)。如果 live 代理配置了多个备份,则不会发生故障恢复。如果发生故障转移事件,备份代理将变为实时,下一次备份将变为备份。当原始 live 代理恢复在线时,它将无法启动故障恢复,因为现已在线的代理已存在备份。

      restart-backup
      此属性控制备份代理在恢复到 live 代理后是否可以自动重启。此属性的默认值为 true
  3. 为群集中剩余的每个 live-backup 组重复第 2 步。

14.3.3. 配置复制高可用性

您可以使用复制高可用性(HA)策略在代理集群中实施 HA。通过复制,持久数据会在实时和备份代理之间同步。如果实时代理遇到故障,消息数据将同步到备份代理,并接管失败的实时代理。

如果没有共享文件系统,您应该使用复制作为共享存储的替代方法。但是,复制可能会导致网络隔离,使实时代理及其备份同时上线。

复制要求 至少三个实时备份对,以减少(但不消除)网络隔离的风险。至少使用三个实时备份代理对可让集群使用 仲裁投票 以避免有两个实时代理。

下面的部分解释了仲裁投票如何工作,以及如何为至少使用三个实时备份对代理集群配置复制 HA。

注意

由于实时和备份代理必须通过网络同步其消息传递数据,因此复制会增加性能开销。此同步进程会阻止日志操作,但它不会阻止客户端。您可以配置日志操作在数据同步时可以被阻止的最大时间。

14.3.3.1. 关于仲裁投票

如果实时代理及其备份遇到中断的复制连接,您可以配置名为 仲裁投票 的进程来缓解网络隔离(或"脑裂")问题。在网络隔离期间,实时代理及其备份可以同时处于活跃状态。

下表描述了 AMQ Broker 使用的两种仲裁投票类型。

投票类型Descriptioninitiator所需的配置参与者基于投票结果的操作

备份投票

如果备份代理丢失了与 live 代理的复制连接,备份代理会根据这个投票的结果决定启动。

备份代理

none.当备份代理丢失与其复制合作伙伴的连接时,会自动进行备份投票。

但是,您可以通过为这些参数指定自定义值来控制备份投票的属性:

  • quorum-vote-wait
  • vote-retries
  • vote-retry-wait

集群中的其他实时代理

如果备份代理收到来自集群中其他实时代理的多数(即 仲裁)投票,这表示其复制合作伙伴不再可用。

实时投票

如果实时代理丢失了其复制合作伙伴的连接,live 代理将决定是否根据此投票继续运行。

实时代理

当实时代理丢失与其复制合作伙伴的连接,并且 vote-on-replication-failure 被设置为 true 时,将实时投票。已激活的备份代理被视为实时代理,并可启动现场投票。

集群中的其他实时代理

如果没有从集群中的其他实时代理获得 大多数投票,实时代理将关闭,这表示其集群连接仍处于活跃状态。

重要

下面列出有关代理集群配置如何影响仲裁投票行为的一些重要事项。

  • 要成功仲裁票数,集群的大小必须允许实现大多数结果。因此,在使用复制 HA 策略时,您的集群 应至少具有三个 实时备份代理对。
  • 您添加到集群中的实时备份代理对越多,集群的整体容错能力就越多。例如,假设您有三个实时备份对:如果您丢失了完整的实时备份对,剩余的两个 live-backup 对无法在随后的仲裁投票中实现大多数结果。这种情形意味着集群中的任何进一步复制中断可能会导致实时代理关闭,并防止其备份代理启动。通过使用五个代理对配置集群,集群至少可能会出现两个故障,同时仍然确保任何仲裁投票产生大多数结果。
  • 如果您有意 减少 集群中的 live-backup 代理对数量,则之前为大多数投票设定的阈值不会自动降低。此时,任何由丢失复制连接触发的仲裁投票都无法成功,使您的集群更容易受到网络隔离的影响。要使集群重新计算仲裁票数的主要阈值,请首先关闭您要从集群中移除的实时备份对。然后,在集群中重启剩余的 live-backup 对。当所有剩余的代理都重启后,集群会重新计算仲裁票数阈值。

14.3.3.2. 配置代理集群以复制高可用性

以下流程描述了如何为 6 broker 集群配置复制高可用性(HA)。在这个拓扑中,六个代理被分成三个实时备份对:三个实时代理各自与专用备份代理配对。

复制要求至少三个实时备份对,以减少(但不消除)网络隔离的风险。

先决条件

  • 您必须有一个带有至少 6 个代理的代理集群。

    六个代理配置为三个实时备份对。有关在集群中添加代理的详情请参考 第 14 章 设置代理集群

流程

  1. 将集群中的代理分组到 live-backup 组。

    在大多数情况下,实时备份组应该由两个代理组成:实时代理和备份代理。如果您在集群中有六个代理,则需要三个 live-backup 组。

  2. 创建第一个由实时代理和一个备份代理组成的实时备份组。

    1. 打开 live 代理的 <broker_instance_dir>/etc/broker.xml 配置文件。
    2. 配置 live 代理,以将复制用于其 HA 策略。

      <configuration>
          <core>
              ...
              <ha-policy>
                  <replication>
                      <master>
                          <check-for-live-server>true</check-for-live-server>
                          <group-name>my-group-1</group-name>
                          <vote-on-replication-failure>true</vote-on-replication-failure>
                          ...
                      </master>
                  </replication>
              </ha-policy>
              ...
          </core>
      </configuration>
      check-for-live-server

      如果 live 代理失败,此属性控制客户端重启时是否应该失败。

      如果您将此属性设置为 true,当 live 代理在以前的故障切换后重启时,它会搜索集群中具有相同节点 ID 的另一个代理。如果 live 代理找到具有相同节点 ID 的另一个代理,这表示在 live 代理失败时备份代理成功启动。在这种情况下,live 代理将其数据与备份代理同步。然后,实时代理会请求备份代理关闭。如果为备份代理配置了故障恢复,如下所示,它会关闭。然后,实时代理恢复其活跃角色,客户端重新与其连接。

      警告

      如果您没有在 live 代理 上将 check-for-live-server 设置为 true,在以前的故障转移后重启 live 代理时可能会遇到重复的消息处理。特别是,如果您重启了这个属性设置为 false 的 live 代理,实时代理不会与其备份代理同步数据。在这种情况下,实时代理可能会处理备份代理已经处理的信息,从而导致重复。

      group-name
      此 live-backup 组的名称。要形成实时备份组,则必须使用相同的组名称配置 live 和 backup 代理。
      vote-on-replication-failure

      此属性控制在出现中断的复制连接时,实时代理是否启动名为实时投票 的仲裁投票。

      实时投票是实时代理确定其或其合作伙伴是否是中断复制连接的原因的一种方式。根据投票的结果,实时代理会保持运行或关闭。

      重要

      要成功仲裁票数,集群的大小必须允许实现大多数结果。因此,在使用复制 HA 策略时,您的集群 应至少具有三个 实时备份代理对。

      您在集群中配置的代理对越多,集群总体容错能力越高。例如,假设您有三个实时备份代理对。如果您丢失了与完整 live-backup 对的连接,剩余的两个实时备份对将不再达到仲裁票数。这种情形意味着,任何后续复制中断都可能导致 live 代理关闭,并阻止其备份代理启动。通过使用五个代理对配置集群,集群至少可能会出现两个故障,同时仍然确保任何仲裁投票产生大多数结果。

    3. 为 live 代理配置任何其他 HA 属性。

      这些附加 HA 属性具有适合大多数常见用例的默认值。因此,当您不想默认行为时,您只需要配置这些属性。如需更多信息,请参阅 附录 F, 复制高可用性配置元素

    4. 打开备份代理的 <broker_instance_dir>/etc/broker.xml 配置文件。
    5. 配置备份(即从)代理,以将复制用于其 HA 策略。

      <configuration>
          <core>
              ...
              <ha-policy>
                  <replication>
                      <slave>
                          <allow-failback>true</allow-failback>
                          <restart-backup>true</restart-backup>
                          <group-name>my-group-1</group-name>
                          <vote-on-replication-failure>true</vote-on-replication-failure>
                          ...
                      </slave>
                  </replication>
              </ha-policy>
              ...
          </core>
      </configuration>
      allow-failback

      如果发生故障转移,并且备份代理接管了 live 代理,则此属性会控制备份代理在重启并重新连接到集群时是否应该恢复到原始 live 代理。

      注意

      故障恢复适用于实时备份对(一个实时代理与单个备份代理对)。如果 live 代理配置了多个备份,则不会发生故障恢复。如果发生故障转移事件,备份代理将变为实时,下一次备份将变为备份。当原始 live 代理恢复在线时,它将无法启动故障恢复,因为现已在线的代理已存在备份。

      restart-backup
      此属性控制备份代理在恢复到 live 代理后是否可以自动重启。此属性的默认值为 true
      group-name
      此备份应连接到的 live 代理的组名称。备份代理仅连接到共享相同组名的实时代理。
      vote-on-replication-failure

      此属性控制在出现中断的复制连接时,实时代理是否启动名为实时投票 的仲裁投票。已激活的备份代理被视为实时代理,并可启动现场投票。

      实时投票是实时代理确定其或其合作伙伴是否是中断复制连接的原因的一种方式。根据投票的结果,实时代理会保持运行或关闭。

    6. (可选)配置备份代理启动的仲裁票数的属性。

      <configuration>
          <core>
              ...
              <ha-policy>
                  <replication>
                      <slave>
                      ...
                          <vote-retries>12</vote-retries>
                          <vote-retry-wait>5000</vote-retry-wait>
                      ...
                      </slave>
                  </replication>
              </ha-policy>
              ...
          </core>
      </configuration>
      vote-retries
      此属性控制备份代理重试仲裁投票的次数,以便获得允许备份代理启动的主要结果。
      vote-retry-wait
      此属性控制备份代理在每次重试仲裁投票之间等待的时长,以毫秒为单位。
    7. 为备份代理配置任何其他 HA 属性。

      这些附加 HA 属性具有适合大多数常见用例的默认值。因此,当您不想默认行为时,您只需要配置这些属性。如需更多信息,请参阅 附录 F, 复制高可用性配置元素

  3. 为群集中每个额外的 live-backup 组重复步骤 2。

    如果群集中有六个代理,请重复此过程两次;每个剩余的 live-backup 组一次。

其它资源

14.3.4. 使用实时配置有限的高可用性

实时 HA 策略允许您在不丢失任何信息的情况下关闭集群中的代理。使用实时代理时,当实时代理被安全停止时,它会将其消息和事务状态复制到另一个实时代理中,然后关闭。然后客户端可以重新连接到其他代理,以继续发送和接收消息。

只有在安全停止代理时,实时 HA 策略才会处理情况。它无法处理意外代理失败。

虽然仅实时 HA 可以防止消息丢失,但可能不会保留消息顺序。如果停止配置了实时 HA 的代理,其消息将附加到另一个代理队列的末尾。

注意

当代理准备缩减时,它会在断开连接通知哪些新代理准备好处理消息前向其客户端发送消息。但是,只有在初始代理完成缩减后,客户端才会重新连接到新的代理。这样可确保当客户端重新连接时,其他代理上都可以使用队列或事务等状态。常规重新连接设置在客户端重新连接时应用,因此您应该设置这些高,以处理缩减所需的时间。

这个步骤描述了如何在集群中配置每个代理进行缩减。完成此步骤后,每当代理被安全停止时,它会将其消息和事务状态复制到集群中的其他代理中。

流程

  1. 打开第一个代理的 <broker_instance_dir>/etc/broker.xml 配置文件。
  2. 将代理配置为使用实时 HA 策略。

    <configuration>
        <core>
            ...
            <ha-policy>
                <live-only>
                </live-only>
            </ha-policy>
            ...
        </core>
    </configuration>
  3. 配置缩减 broker 集群的方法。

    指定此代理应缩减的代理或代理组。

    缩减至…​do this…​

    集群中的特定代理

    指定您要缩减的代理的连接器。

    <live-only>
        <scale-down>
            <connectors>
                <connector-ref>broker1-connector</connector-ref>
            </connectors>
        </scale-down>
    </live-only>

    集群中的任何代理

    指定代理集群的发现组。

    <live-only>
        <scale-down>
            <discovery-group-ref discovery-group-name="my-discovery-group"/>
        </scale-down>
    </live-only>

    特定代理组中的代理

    指定代理组。

    <live-only>
        <scale-down>
            <group-name>my-group-name</group-name>
        </scale-down>
    </live-only>
  4. 对集群中的每个剩余的代理重复此步骤。

其它资源

14.3.5. 使用并置备份配置高可用性

除了配置 live-backup 组外,您还可以在与其他实时代理相同的 JVM 中并置备份代理。在这种配置中,每个 live 代理配置为请求另一个 live 代理在其 JVM 中创建和启动备份代理。

图 14.4. 并置实时和备份代理

HA Colocated

您可以将并置与共享存储或复制一起使用,作为高可用性(HA)策略。新备份代理从创建它的 live 代理继承其配置。备份的名称设置为 colocated _backup_n,其中 n 是实时代理创建的备份数。

另外,备份代理会继承其连接器和接收器的配置,来自创建它的 live 代理。默认情况下,端口偏移 100 应用到每个端口偏移。例如,如果 live 代理具有端口 616 的接收器,则创建的第一个备份代理将使用端口 61716,第二个备份将使用 61816,以此类推。

日志、大消息和分页的目录会根据您选择的 HA 策略来设置。如果您选择共享存储,请求代理会通知要使用的目标代理。如果选择了复制,则从创建代理继承目录,并将新备份的名称附加到其中。

此流程将集群中的每个代理配置为使用共享存储 HA,并请求创建备份并与集群中的其他代理在一起。

流程

  1. 打开第一个代理的 <broker_instance_dir>/etc/broker.xml 配置文件。
  2. 将代理配置为使用 HA 策略和 colocation。

    在本例中,代理配置了共享存储 HA 和 colocation。

    <configuration>
        <core>
            ...
            <ha-policy>
                <shared-store>
                    <colocated>
                        <request-backup>true</request-backup>
                        <max-backups>1</max-backups>
                        <backup-request-retries>-1</backup-request-retries>
                        <backup-request-retry-interval>5000</backup-request-retry-interval/>
                        <backup-port-offset>150</backup-port-offset>
                        <excludes>
                            <connector-ref>remote-connector</connector-ref>
                        </excludes>
                        <master>
                            <failover-on-shutdown>true</failover-on-shutdown>
                        </master>
                        <slave>
                            <failover-on-shutdown>true</failover-on-shutdown>
                            <allow-failback>true</allow-failback>
                            <restart-backup>true</restart-backup>
                        </slave>
                    </colocated>
                </shared-store>
            </ha-policy>
            ...
        </core>
    </configuration>
    request-backup
    通过将此属性设置为 true,此代理将请求集群中另一个实时代理创建备份代理。
    max-backups
    此代理可以创建的备份代理数量。如果将此属性设置为 0,这个代理将不接受来自集群中其他代理的备份请求。
    backup-request-retries
    此代理应尝试创建备份代理的次数。默认值为 -1,这意味着无限尝试。
    backup-request-retry-interval
    代理在重试创建备份代理请求前应等待的时间,以毫秒为单位。默认值为 5000 或 5 秒。
    backup-port-offset
    用于新备份代理的接收器和连接器的端口偏移。如果这个代理收到为集群中的另一个代理创建备份的请求,它将创建带有这个数量偏移的端口的备份代理。默认值为 100
    excludes (可选)
    从备份端口偏移中排除连接器。如果您为备份端口偏移中应当排除的外部代理配置了任何连接器,请 为每个连接器添加一个 <connector-ref>
    master
    此代理的共享存储或复制故障切换配置。
    slave
    此代理备份的共享存储或复制故障转移配置。
  3. 对集群中的每个剩余的代理重复此步骤。

其它资源

14.3.6. 将客户端配置为故障切换

在代理集群中配置高可用性后,您可以将客户端配置为故障切换。客户端故障切换可确保代理出现故障时,与之连接的客户端可以在最小停机时间的情况下重新连接到集群中的其他代理。

注意

如果出现临时网络问题,AMQ Broker 会自动将连接重新连接到同一代理。这与故障转移类似,除了客户端重新连接到同一代理。

您可以配置两种不同类型的客户端故障转移:

自动客户端故障切换
客户端在首次连接时接收有关代理集群的信息。如果代理连接失败,客户端会自动重新连接到代理的备份,备份代理会在故障转移前重新创建每个连接上存在的会话和消费者。
应用程序级别的客户端故障切换
作为自动客户端故障转移的替代方案,您可以改为使用故障处理程序中您自己的自定义重新连接逻辑来编写客户端应用。

流程

14.4. 启用消息重新发布

如果您的代理集群配置了 消息加载平衡 设置为 ON_DEMANDOFF_WITH_REDISTRIBUTION,您可以配置 消息重新 发布,以防止在没有消费者使用消息的队列中出现"stuck"。

本节包含以下内容的信息:

14.4.1. 了解消息重新发布

代理集群使用负载均衡来在集群中分发消息负载。在集群连接中配置负载平衡时,您可以使用以下 消息负载均衡 设置启用重新发布:

  • ON_DEMAND - 启用负载平衡并允许重新发布
  • OFF_WITH_REDISTRIBUTION - 禁用负载平衡,但允许重新发布

在这两种情况下,代理都只将消息转发到有匹配消费者的其他代理。此行为可确保消息不会移到没有使用者使用这些消息的队列中。但是,如果在消息转发到代理后附加到队列关闭的消费者,这些消息将变为队列中"stuck"且不会被使用。这个问题有时被称为" 不足 "。

消息重新发布通过自动从没有使用者的队列重新分发消息来防止资源不足。

使用 OFF_WITH_REDISTRIBUTION 时,代理仅当没有活跃的本地消费者时将消息转发到其他有匹配消费者的代理,使您能够在客户不可用时提供替代的代理。

消息重新发布支持使用过滤器(也称为 选择器),也就是说,消息在与可用本地使用者的选择器不匹配时会被重新分发。

其它资源

14.4.2. 配置消息重新发布

此流程演示了如何通过负载平衡配置消息重新发布。如果您希望在没有负载均衡的情况下重新发布消息,请将 <message-load-balancing> 设置为 OFF_WITH_REDISTRIBUTION

流程

  1. 打开 <broker_instance_dir>/etc/broker.xml 配置文件。
  2. <cluster-connection> 元素中,验证 <message-load-balancing> 是否已设置为 ON_DEMAND

    <configuration>
        <core>
            ...
            <cluster-connections>
                <cluster-connection name="my-cluster">
                    ...
                    <message-load-balancing>ON_DEMAND</message-load-balancing>
                    ...
                </cluster-connection>
            </cluster-connections>
        </core>
    </configuration>
  3. <address-settings> 元素中,为队列或队列集设置重新发布延迟。

    在本例中,平衡到 my.queue 的消息将在最后一个消费者关闭后重新分发 5000 毫秒。

    <configuration>
        <core>
            ...
            <address-settings>
                <address-setting match="my.queue">
                    <redistribution-delay>5000</redistribution-delay>
                </address-setting>
            </address-settings>
            ...
        </core>
    </configuration>
    address-setting
    match 属性设置为您要重新分发消息的队列的名称。您可以使用代理通配符语法来指定队列范围。如需更多信息,请参阅 第 4.2 节 “将地址设置应用到一组地址”
    redistribution-delay
    代理在此队列最终消费者关闭后应等待的时间(以毫秒为单位),然后再将消息重新分发到集群中的其他代理。如果将其设置为 0,消息将立即重新分发。但是,您通常应该在重新分发前设置延迟 - 用户通常会关闭另一个延迟,但在同一队列中可以快速创建另一个延迟。
  4. 对集群中的每个额外代理重复此步骤。

其它资源

14.5. 配置集群消息分组

通过消息分组,客户端能够发送由同一消费者序列处理特定类型的消息组。通过向集群中的每个代理添加分组处理程序,您可以确保客户端可以将分组的消息发送到集群中的任何代理,并且仍以正确顺序使用这些消息。

注意

群集提供并行性,使您能够水平扩展,而分组则提供序列化技术,以将分组消息定向到特定的使用者。

红帽建议您使用集群 分组,并避免使用集群和分组。

有两种类型的分组处理程序: 本地处理程序 和远程处理程序。它们可让代理集群将特定组中的所有消息路由到适当的队列,以便预期消费者能够以正确的顺序消耗它们。

先决条件

  • 集群中每个代理应至少有一个消费者。

    当消息固定到队列上的使用者时,具有相同组 ID 的所有消息都将路由到该队列。如果移除使用者,队列将继续接收消息,即使没有消费者也是如此。

流程

  1. 在群集中的一个代理上配置本地处理程序。

    如果您使用高可用性,这应该是 master 代理。

    1. 打开代理的 <broker_instance_dir>/etc/broker.xml 配置文件。
    2. <core> 元素中添加本地处理器:

      本地处理程序充当远程处理程序的仲裁程序。它存储路由信息,并将其与其他代理通信。

      <configuration>
          <core>
              ...
              <grouping-handler name="my-grouping-handler">
                  <type>LOCAL</type>
                  <timeout>10000</timeout>
              </grouping-handler>
              ...
          </core>
      </configuration>
      grouping-handler
      使用 name 属性为组处理程序指定唯一的名称。
      type
      将它设置为 LOCAL
      timeout

      等待时间(以毫秒为单位),以便决定将邮件路由到何处。默认值为 5000 毫秒。如果在做出路由决策前已达到超时时间,则会引发异常,以确保严格消息顺序。

      代理收到带有组 ID 的消息时,它会提出到消费者附加到的队列的路由。如果路由被集群中的其他代理上的分组处理程序接受,则路由会被建立:集群中的所有代理都使用这个组 ID 将消息转发到该队列。如果代理的路由建议被拒绝,则它提议了一个替代路由,重复该过程,直到路由被接受。

  2. 如果您使用高可用性,请将本地处理器配置复制到 master 代理的 slave 代理。

    将本地处理程序配置复制到从代理可防止本地处理程序出现单点故障。

  3. 在集群中的每个剩余的代理中,配置一个远程处理器。

    1. 打开代理的 <broker_instance_dir>/etc/broker.xml 配置文件。
    2. <core> 元素中添加远程处理器:

      <configuration>
          <core>
              ...
              <grouping-handler name="my-grouping-handler">
                  <type>REMOTE</type>
                  <timeout>5000</timeout>
              </grouping-handler>
              ...
          </core>
      </configuration>
      grouping-handler
      使用 name 属性为组处理程序指定唯一的名称。
      type
      将它设置为 REMOTE
      timeout
      等待时间(以毫秒为单位),以便决定将邮件路由到何处。默认值为 5000 毫秒。将此值设置为本地处理程序值至少一半。

其它资源

14.6. 将客户端连接到代理集群

您可以使用 AMQ JMS 客户端连接集群。通过使用 JMS,您可以将消息传递客户端配置为动态或静态发现代理列表。您还可以配置客户端负载平衡,以在集群中分发从连接中创建的客户端会话。

流程

第 15 章 使用 Ceph 配置多站点、容错消息传递系统

大型企业消息传递系统通常具有分散的代理集群,位于地理分散的数据中心。如果数据中心中断,系统管理员可能需要保留现有的消息传递数据,并确保客户端应用可以继续生成和使用消息。您可以使用特定的代理拓扑和红帽 Ceph 存储(软件定义存储平台)来确保数据中心中断期间消息传递系统的连续性。此类解决方案称为 多站点、容错架构

注意

如果您只需要 AMQP 协议支持,请考虑 第 16 章 使用代理连接配置多站点、容错消息传递系统

以下小节解释了如何使用 Red Hat Ceph Storage 保护您的消息传递系统免受数据中心中断的影响:

注意

多站点容错能力不能取代数据中心 的高可用性(HA)代理冗余。基于实时备份组的代理冗余提供自动保护,防止单一群集内出现单一代理故障。相比之下,多站点容错功能可防止大规模数据中心中断。

注意

要使用 Red Hat Ceph Storage 来确保消息传递系统的连续性,您必须将代理配置为使用共享存储高可用性(HA)策略。您不能将代理配置为使用复制 HA 策略。有关这些策略的更多信息,请参阅 实施高可用性

15.1. Red Hat Ceph Storage 集群如何工作

红帽 Ceph 存储是集群对象存储系统。红帽 Ceph 存储使用对象的数据分片和基于策略的复制来确保数据完整性和系统可用性。

红帽 Ceph 存储使用一种称为 CRUSH(可扩展哈希下的受控复制)的算法,以确定如何通过自动计算数据存储位置来存储和检索数据。您可以配置名为 CRUSH map 的 Ceph 项目,它详细说明集群拓扑结构,并指定如何在存储集群之间复制数据。

CRUSH map 包含对象存储设备(OSD)的列表、用于将设备聚合到故障域层次结构中的"bucket"列表,以及告知 CRUSH 如何在 Ceph 集群的池中复制数据的规则。

通过反映安装的底层物理组织,CRUSH map 可以模拟(从而解决)关联设备故障的潜在来源,如物理相似点、共享电源和共享网络。通过将此信息编码到集群映射中,CRUSH 可以在不同故障域(如数据中心)之间分隔对象副本,同时仍然保持存储群集间数据的伪随机分布。这有助于防止数据丢失,并使集群能够在降级状态下运行。

红帽 Ceph 存储群集需要运行多个节点(物理或虚拟)。集群必须包括以下类型的节点:

监控节点

每个 monitor(MON)节点运行 monitor 守护进程(ceph-mon),后者维护 cluster map 的主副本。集群映射包含集群拓扑。连接 Ceph 集群的客户端从 monitor 中检索 cluster map 的当前副本,这使得客户端能够从集群读取和写入数据。

重要

红帽 Ceph 存储群集可以使用一个 monitor 节点运行;但是,为了确保在生产集群中高可用性,红帽仅支持至少具有三个 monitor 节点的部署。至少三个 monitor 节点意味着,在一个 monitor 出现故障或不可用时,集群中的其余 monitor 节点存在仲裁来选举新的领导。

Manager 节点

每一管理器(MGR)节点运行 Ceph 管理器守护进程(ceph-mgr),它负责跟踪运行时指标和 Ceph 集群的当前状态,包括存储利用率、当前性能指标和系统负载。通常,管理器节点与 monitor 节点共存(即在同一主机上)。

对象存储设备节点

每个对象存储设备(OSD)节点运行 Ceph OSD 守护进程(ceph-osd),它与附加到节点的逻辑卷交互。Ceph 将数据存储在 OSD 节点上。Ceph 可以在非常少的 OSD 节点(默认为三个)运行,但生产集群在适度范围内实现了更高的性能,例如,一个存储集群中有 50 个 OSD。在存储集群中拥有多个 OSD 使得系统管理员能够在 CRUSH map 中定义隔离的故障域。

元数据服务器节点

每个元数据服务器(MDS)节点运行 MDS 守护进程(ceph-mds),后者管理与 Ceph 文件系统(CephFS)中存储的文件相关的元数据。MDS 守护进程也协调对共享集群的访问。

其它资源

有关红帽 Ceph 存储的更多信息,请参阅 什么是 Red Hat Ceph Storage?

15.2. 安装 Red Hat Ceph Storage

AMQ 代理多站点、容错架构使用红帽 Ceph 存储 3。通过在数据中心之间复制数据,红帽 Ceph 存储集群可以有效地在单独的数据中心内创建一个可供代理使用的共享存储。您可以将代理配置为使用共享存储高可用性(HA)策略,并将消息传递数据存储在红帽 Ceph 存储集群中。

专用于生产环境的 Red Hat Ceph Storage 集群应至少有以下值:

  • 三个 monitor(MON)节点
  • 三个管理器(MGR)节点
  • 包含多个 OSD 守护进程的三个对象存储设备(OSD)节点
  • 三个元数据服务器(MDS)节点
重要

您可以在相同或独立的物理或虚拟机上运行 OSD、MON、MGR 和 MDS 节点上运行。但是,要确保红帽 Ceph 存储集群内的容错能力,最好是在不同的数据中心之间分发这些类型的节点。特别是,您必须确保在单个数据中心停机时,您的存储集群仍然至少有两个可用的 MON 节点。因此,如果您集群中有三个 MON 节点,则每个节点必须在独立数据中心的独立主机上运行。不要在单个数据中心中运行两个 MON 节点,因为此数据中心失败将使得您的存储集群仅有一个剩余的 MON 节点。在这种情况下,存储集群无法再运行。

本节链接到的步骤演示了如何安装包括 MON、MGR、OSD 和 MDS 节点在内的红帽 Ceph 存储 3 集群。

先决条件

流程

15.3. 配置 Red Hat Ceph Storage 集群

本示例步骤演示了如何配置红帽 Ceph 存储群集以实现容错。您可以创建 CRUSH 存储桶,将对象存储设备(OSD)节点聚合到数据中心中,以反映您的实时物理安装。此外,您还将创建一条规则,告知 CRUSH 如何在存储池中复制数据。这些步骤更新 Ceph 安装创建的默认 CRUSH map。

先决条件

  • 您已安装了一个红帽 Ceph 存储集群。如需更多信息,请参阅 安装 Red Hat Ceph Storage
  • 您应该了解红帽 Ceph 存储如何使用 PG 在池中组织大量数据对象,以及如何计算要在池中使用的 PG 数量。如需更多信息,请参阅 PG。
  • 您应该了解如何在池中设置对象副本的数量。如需更多信息,请 设置对象副本的数量

流程

  1. 创建 CRUSH bucket 以组织您的 OSD 节点。bucket 是基于数据中心等物理位置的 OSD 列表。在 Ceph 中,这些物理位置称为 故障域

    ceph osd crush add-bucket dc1 datacenter
    ceph osd crush add-bucket dc2 datacenter
  2. 将 OSD 节点的主机计算机移到您创建的数据中心 CRUSH bucket。将主机名 host1-host4 替换为您的主机计算机的名称。

    ceph osd crush move host1 datacenter=dc1
    ceph osd crush move host2 datacenter=dc1
    ceph osd crush move host3 datacenter=dc2
    ceph osd crush move host4 datacenter=dc2
  3. 确保您创建的 CRUSH bucket 是 默认 CRUSH 树的一部分。

    ceph osd crush move dc1 root=default
    ceph osd crush move dc2 root=default
  4. 创建一条规则来映射数据中心内的存储对象副本。这有助于防止数据丢失,并使集群能够在单个数据中心中断时继续运行。

    创建规则的命令使用以下语法: ceph osd crush rule create-replicated <rule-name> <root> <failure-domain> <class>。下面是一个示例。

    ceph osd crush rule create-replicated multi-dc default datacenter hdd
    注意

    在前面的命令中,如果您的存储集群使用固态驱动器(SSD),请指定 ssd 而不是 hdd (硬盘)。

  5. 配置您的 Ceph 数据和元数据池,以使用您创建的规则。最初,这可能会导致数据回填到由 CRUSH 算法决定的存储目的地。

    ceph osd pool set cephfs_data crush_rule multi-dc
    ceph osd pool set cephfs_metadata crush_rule multi-dc
  6. 指定元数据和数据池的 PG 和放置 PG 数量。PGP 值应当等于 PG 值。

    ceph osd pool set cephfs_metadata pg_num 128
    ceph osd pool set cephfs_metadata pgp_num 128
    
    ceph osd pool set cephfs_data pg_num 128
    ceph osd pool set cephfs_data pgp_num 128
  7. 指定数据和元数据池将使用的副本数。

    ceph osd pool set cephfs_data min_size 1
    ceph osd pool set cephfs_metadata min_size 1
    
    ceph osd pool set cephfs_data size 2
    ceph osd pool set cephfs_metadata size 2

下图显示了上例过程创建的红帽 Ceph 存储集群。存储集群将 OSD 组织到 CRUSH bucket 中,对应于数据中心。

代理灾难恢复 1

下图显示了第一个数据中心的可能布局,包括代理服务器。具体来说,数据中心主机:

  • 两个实时备份代理对的服务器
  • 您在前面的流程中分配给第一个数据中心的 OSD 节点
  • 单个元数据服务器、监控器和管理器节点.monitor 和 Manager 节点通常在同一台计算机上在一起。
代理灾难恢复 2
重要

您可以在相同或独立的物理或虚拟机上运行 OSD、MON、MGR 和 MDS 节点上运行。但是,要确保红帽 Ceph 存储集群内的容错能力,最好是在不同的数据中心之间分发这些类型的节点。特别是,您必须确保在单个数据中心停机时,存储集群仍然至少有两个可用的 MON 节点。因此,如果您集群中有三个 MON 节点,则每个节点必须在独立数据中心的独立主机上运行。

下图显示了一个完整的示例拓扑。为确保存储集群中容错,MON、MGR 和 MDS 节点分布在三个独立的数据中心。

代理灾难恢复 10
注意

在与代理服务器相同的数据中心查找特定 OSD 节点的主机计算机并不意味着您将消息传递数据存储在这些特定的 OSD 节点上。您将代理配置为将消息传递数据存储在 Ceph 文件系统的指定目录中。然后,集群中的元数据服务器节点决定如何在数据中心的所有可用 OSD 之间分发存储的数据,并处理这些数据在数据中心之间的复制。以下部分演示了如何配置代理以在 Ceph 文件系统上存储消息传递数据。

下图演示了使用代理服务器的两个数据中心之间的数据复制。

代理灾难恢复 3

其它资源

有关以下的更多信息:

  • 为您的红帽 Ceph 存储集群管理 CRUSH,请参阅 CRUSH 管理
  • 您可以在存储池上设置的完整属性集合,请参阅 池值

15.4. 在代理服务器上挂载 Ceph 文件系统

在消息传递系统中配置代理以将消息传递数据存储在红帽 Ceph 存储集群中之前,首先需要挂载 Ceph 文件系统(CephFS)。

本节中链接到的步骤演示了如何将 CephFS 挂载到代理服务器上。

先决条件

流程

有关在代理服务器上挂载 Ceph 文件系统的说明,请参阅 将 Ceph 文件系统挂载为内核客户端

15.5. 在多站点、容错消息传递系统中配置代理

要将代理配置为多站点、容错消息传递系统的一部分,您需要:

15.5.1. 添加备份代理

在您的每个数据中心中,您需要添加空闲备份代理,这些代理可从实时主代理组中接管,以便在数据中心停机时关闭的代理组。您应该在空闲备份代理中复制实时 master 代理的配置。您还需要配置备份代理以接受与现有代理相同的客户端连接。

在稍后的步骤中,您将了解如何配置空闲备份代理以加入现有 master-slave 代理组。您必须在单独的数据中心中找到空闲备份代理到 live master-slave 代理组。另外,建议您仅在数据中心发生故障时手动启动空闲备份代理。

下图显示了一个示例拓扑。

代理灾难恢复 4

其它资源

15.5.2. 将代理配置为 Ceph 客户端

添加容错系统所需的备份代理后,您必须使用 Ceph 客户端角色配置所有代理服务器。客户端角色使代理能够将数据存储在红帽 Ceph 存储集群中。

要了解如何配置 Ceph 客户端,请参阅 安装 Ceph 客户端角色

15.5.3. 配置共享存储高可用性

红帽 Ceph 存储集群有效创建可供不同数据中心内的代理使用的共享存储。要确保信息在失败时仍可以被代理客户端使用,您可以在 live-backup 组中配置每个代理以使用:

  • 共享存储高可用性(HA)策略
  • Ceph 文件系统中相同的日志、分页和大消息目录

以下步骤演示了如何在 live-backup 组的主、从卷和空闲备份代理上配置共享存储 HA 策略。

流程

  1. 编辑 live-backup 组中每个代理的 broker.xml 配置文件。将每个代理配置为使用 Ceph 文件系统中相同的分页、绑定、日志和大消息目录。

    # Master Broker - DC1
    <paging-directory>mnt/cephfs/broker1/paging</paging-directory>
    <bindings-directory>/mnt/cephfs/data/broker1/bindings</bindings-directory>
    <journal-directory>/mnt/cephfs/data/broker1/journal</journal-directory>
    <large-messages-directory>mnt/cephfs/data/broker1/large-messages</large-messages-directory>
    
    # Slave Broker - DC1
    <paging-directory>mnt/cephfs/broker1/paging</paging-directory>
    <bindings-directory>/mnt/cephfs/data/broker1/bindings</bindings-directory>
    <journal-directory>/mnt/cephfs/data/broker1/journal</journal-directory>
    <large-messages-directory>mnt/cephfs/data/broker1/large-messages</large-messages-directory>
    
    # Backup Broker (Idle) - DC2
    <paging-directory>mnt/cephfs/broker1/paging</paging-directory>
    <bindings-directory>/mnt/cephfs/data/broker1/bindings</bindings-directory>
    <journal-directory>/mnt/cephfs/data/broker1/journal</journal-directory>
    <large-messages-directory>mnt/cephfs/data/broker1/large-messages</large-messages-directory>
  2. 将备份代理配置为其 HA 策略中的主代理,如下所示:此配置设置可确保在手动启动 backup 代理时立即成为 master。因为代理是一个空闲备份,所以您可以为活跃 master 代理指定的 failover-on-shutdown 参数不会在此情况下应用。

    <configuration>
        <core>
            ...
            <ha-policy>
                <shared-store>
                    <master>
                    </master>
                </shared-store>
            </ha-policy>
            ...
        </core>
    </configuration>

其它资源

15.6. 在多站点、容错消息传递系统中配置客户端

内部客户端应用程序是在位于与代理服务器位于同一数据中心的计算机上运行的应用程序。下图显示了此拓扑。

代理灾难恢复 5

外部客户端应用程序是在代理数据中心之外的机器上运行。下图显示了此拓扑。

代理灾难恢复 6

以下子部分描述在数据中心停机时将您的内部和外部客户端应用程序连接到另一个数据中心的备份代理的示例。

15.6.1. 配置内部客户端

如果您遇到数据中心中断,内部客户端应用程序将与代理一起关闭。为缓解这种情况,您必须在单独的数据中心中提供另一个客户端应用程序实例。如果数据中心中断,您可以手动启动备份客户端以连接到您已手动启动的备份代理。

要启用备份客户端连接到备份代理,您需要配置与主数据中心中客户端类似的客户端连接。

示例

下方显示了 AMQ 核心协议 JMS 客户端到主从代理组的基本连接配置。在本例中,host1host2 是主代理和从属代理的主机服务器。

<ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(“(tcp://host1:port,tcp://host2:port)?ha=true&retryInterval=100&retryIntervalMultiplier=1.0&reconnectAttempts=-1”);

要将备份客户端配置为在数据中心停机时连接到备份代理,请使用类似的连接配置,但仅指定备份代理服务器的主机名。在本例中,备份代理服务器是 host3。

<ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(“(tcp://host3:port)?ha=true&retryInterval=100&retryIntervalMultiplier=1.0&reconnectAttempts=-1”);

其它资源

15.6.2. 配置外部客户端

要让外部代理客户端在数据中心中断时继续生成或消耗消息传递数据,您必须将客户端配置为切换到另一个数据中心中的代理。对于多站点、容错系统,您可以将客户端配置为故障转移到您在中断时手动启动的备份代理。

示例

下面是将 AMQ 核心协议 JMS 和 AMQ JMS 客户端配置为在主 master-slave 组不可用时故障转移到备份代理的示例。在这些示例中,host1host2 是主主代理和从属代理的主机服务器,而 host3 是您在数据中心中断时手动启动的备份代理的主机服务器。

  • 要配置 AMQ 核心协议 JMS 客户端,请在客户端尝试连接到的有序代理列表中包含备份代理。

    <ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(“(tcp://host1:port,tcp://host2:port,tcp://host3:port)?ha=true&retryInterval=100&retryIntervalMultiplier=1.0&reconnectAttempts=-1”);
  • 若要配置 AMQ JMS 客户端,请将备份代理包含在您在客户端上配置的故障切换 URI 中。

    failover:(amqp://host1:port,amqp://host2:port,amqp://host3:port)?jms.clientID=foo&failover.maxReconnectAttempts=20

其它资源

15.7. 在数据中心中断期间验证存储集群健康状况

当您配置了红帽 Ceph 存储群集以实现容错功能后,即使其中一个数据中心出现故障,集群也会继续以降级状态运行,而不丢失数据。

此流程演示了如何在集群处于降级状态运行时验证集群的状态。

流程

  1. 要验证 Ceph 存储集群的状态,请使用 健康或 status 命令:

    # ceph health
    # ceph status
  2. 要在命令行中观察集群的持续事件,请打开一个新终端。然后输入:

    # ceph -w

当您运行上述任何命令时,您会看到表明存储集群仍在运行的输出,但处于降级状态。特别是,您应该看到类似以下内容的警告:

health: HEALTH_WARN
        2 osds down
        Degraded data redundancy: 42/84 objects degraded (50.0%), 16 pgs unclean, 16 pgs degraded

其它资源

  • 有关监控红帽 Ceph 存储集群健康状况的更多信息,请参阅 监控

15.8. 在数据中心中断期间保持消息传递连续性

以下流程演示了如何在数据中心中断期间保持代理和相关消息传递数据可供客户端使用。特别是,当数据中心失败时,您需要:

  • 手动启动您创建的任何空闲备份代理,以便从失败的数据中心中的代理接管。
  • 将内部或外部客户端连接到新活动代理。

先决条件

流程

  1. 对于失败的数据中心中的每个 master-slave 代理对,请手动启动您添加的空闲备份代理。

    代理灾难恢复 7
  2. 重新建立客户端连接。

    1. 如果您在失败的数据中心中使用内部客户端,请手动启动您创建的备份客户端。如在 多站点、容错消息传递系统中配置客户端 所述,您必须将客户端配置为连接到您手动启动的备份代理。

      下图显示了新的拓扑。

      代理灾难恢复 8
    2. 如果您有一个外部客户端,请根据配置手动将外部客户端连接到新活跃代理,或观察客户端自动切换到新的活跃代理。如需更多信息,请参阅配置外部客户端

      下图显示了新的拓扑。

      代理灾难恢复 9

15.9. 重启之前失败的数据中心

当之前失败的数据中心恢复在线时,请按照以下步骤恢复消息传递系统的原始状态:

  • 重启托管 Red Hat Ceph Storage 集群节点的服务器
  • 重启消息传递系统中的代理
  • 重新建立从客户端应用程序到恢复的代理的连接

以下子部分显示了执行这些步骤的步骤。

15.9.1. 重启存储集群服务器

当您在之前失败的数据中心中重启 monitor、元数据服务器、管理器和对象存储设备(OSD)节点时,您的红帽 Ceph 存储集群会自我修复,以恢复完整的数据冗余。在此过程中,红帽 Ceph 存储可根据需要自动将数据回填恢复的 OSD 节点。

要验证存储集群是否自动自我修复并恢复完整的数据冗余,请使用之前在 数据中心中断期间验证存储集群健康状况 中显示的命令。重新执行这些命令时,您会看到上一 HEALTH_WARN 消息所指示的百分比降级开始提高,直到它返回到 100%。

15.9.2. 重启代理服务器

以下流程演示了当存储集群不再处于降级状态时,如何重启代理服务器。

流程

  1. 停止任何连接到备份代理的客户端应用程序,这些应用程序会在数据中心中断时手动启动。
  2. 停止您手动启动的备份代理。

    1. 在 Linux 中:

      <broker_instance_dir>/bin/artemis stop
    2. 在 Windows 中:

      <broker_instance_dir>\bin\artemis-service.exe stop
  3. 在之前失败的数据中心中,重启原始的主代理和从代理。

    1. 在 Linux 中:

      <broker_instance_dir>/bin/artemis run
    2. 在 Windows 中:

      <broker_instance_dir>\bin\artemis-service.exe start

原始 master 代理重启时自动恢复其角色作为 master。

15.9.3. 重新建立客户端连接

当您重启代理服务器后,请将客户端应用程序重新连接到这些代理。以下小节描述了如何重新连接内部和外部客户端应用程序。

15.9.3.1. 重新连接内部客户端

内部客户端是指在之前失败的数据中心和恢复的代理中运行的客户端。要重新连接内部客户端,请重新启动它们。每个客户端应用程序都会重新连接到在其连接配置中指定的恢复的 master 代理。

有关配置代理网络连接的详情请参考 第 2 章 在网络连接中配置接收器和连接器

15.9.3.2. 重新连接外部客户端

外部客户端是指在数据中心外部运行的用户。根据您的客户端类型以及 配置外部代理客户端 中的信息,您可以将客户端配置为自动切换到备份代理,或者手动建立此连接。当您恢复之前失败的数据中心时,您将以类似的方式从客户端重新建立到恢复的 master 代理的连接,如下所述。

  • 如果您将外部客户端配置为自动切换到备份代理,当关闭备份代理并重启原始 master 代理时,客户端会自动返回到原始 master 代理。
  • 如果您在数据中心中断时手动将外部客户端连接到备份代理,则必须手动将客户端重新连接到您重启的原始 master 代理。

第 16 章 使用代理连接配置多站点、容错消息传递系统

大型企业消息传递系统通常具有分散的代理集群,位于地理分散的数据中心。如果数据中心中断,系统管理员可能需要保留现有的消息传递数据,并确保客户端应用可以继续生成和使用消息。您可以使用代理连接来确保在数据中心中断期间消息传递系统的连续性。此类解决方案称为 多站点、容错架构

注意

仅支持 AMQP 协议,用于代理连接的代理之间的通信。客户端可以使用任何受支持的协议。目前,消息将通过镜像过程转换为 AMQP。

以下小节解释了如何使用代理连接防止您的消息传递系统停机:

注意

多站点容错能力不能取代数据中心 的高可用性(HA)代理冗余。基于实时备份组的代理冗余提供自动保护,防止单一群集内出现单一代理故障。相比之下,多站点容错功能可防止大规模数据中心中断。

16.1. 关于代理连接

通过代理连接,代理可以建立到另一个代理的连接,并将信息镜像到该代理或从该代理镜像。

AMQP 服务器连接
代理可以使用代理连接使用 AMQP 协议启动到其他端点的连接。例如,这意味着代理可以连接到其他 AMQP 服务器,并在这些连接中创建元素。

AMQP 服务器连接支持以下类型的操作:

  • mirrors - 代理使用 AMQP 与另一个代理的连接,并重复消息并通过线路发送确认。
  • 发送者 - 特定队列中收到的消息传输到另一个代理。
  • 接收器 - 代理从另一个代理拉取消息。
  • peers - 代理在 AMQ 互连端点上创建发送者和接收器。

本章论述了如何使用代理连接来创建容错系统。有关 sender、接收器和对等选项的详情,请查看 第 17 章 桥接代理

以下事件通过镜像发送:

  • 消息发送 - 发送到一个代理的消息将"复制"到目标代理。
  • 消息确认 - 确认从一个代理中删除信息将发送到目标代理。
  • 队列和地址创建.
  • 队列和地址删除.
注意

如果目标镜像上的消费者的消息处于待处理状态,则确认不会成功,信息也可能由两个代理发送。

镜像不会阻止任何操作,不会影响代理的性能。

代理只会镜像从镜像配置时到达的信息。在以前的版本中,现有信息不会转发到其他代理。

16.2. 配置代理连接

以下流程演示了如何配置代理连接来镜像代理之间的消息。在任何时候只能激活一个代理,所有消息都会被镜像到其他代理中。

先决条件

  • 您有两个工作代理。

流程

  1. 在第一个 代理的 broker .xml 文件中创建一个 broker -connections 元素,例如:

    <broker-connections>
      <amqp-connection uri="tcp://<hostname>:<port>" name="DC1">
        <mirror/>
      </amqp-connection>
    </broker-connections>
    <hostname>
    其他代理实例的主机名。
    <port>
    由代理在其他主机上使用的端口。

    第一个代理中的所有消息都将镜像到第二个代理,但创建镜像前存在的消息不会镜像(mirror)。

    您还可以配置以下附加功能:

    • queue-removal :指定是发送队列或地址-removal 事件。默认值为 true
    • message-acknowledgements:指定是否发送消息确认。默认值为 true
    • queue-creation:指定是发送队列或地址创建事件。默认值为 true
    注意

    示例中的代理连接名称 DC1 用于创建名为 $ACTIVEMQ_ARTEMIS_MIRROR_mirror 的队列。确保对应的代理配置为接受这些消息,即使队列在该代理中不可见。

  2. 在第二个 代理的 broker .xml 文件中创建一个 broker -connections 元素,例如:

    <broker-connections>
      <amqp-connection uri="tcp://<hostname>:<port>" name="DC2">
        <mirror/>
      </amqp-connection>
    </broker-connections>
    注意

    红帽建议将消费者配置为接受来自其中一个代理(而不是两者)的消息。

  3. 使用 第 15.6 节 “在多站点、容错消息传递系统中配置客户端” 中记录的说明配置客户端,请注意,通过代理连接,没有共享存储。

第 17 章 桥接代理

网桥提供了一种连接两个代理的方法,将消息从一个代理转发到另一个代理。

可用的网桥如下:

Core
提供了一个示例,它演示了一个代理上部署的核心桥接,它消耗来自本地队列的消息并将其转发到第二个代理上的地址。请参阅位于代理安装的 <install_dir>/examples/features/standard/ 目录中的 core-bridge 示例。
mirror
请查看 第 16 章 使用代理连接配置多站点、容错消息传递系统
sender 和 receiver
请查看 第 17.1 节 “代理连接的发送者和接收器配置”
peer
请查看 第 17.2 节 “代理连接的对等配置”
注意

Core 网桥的 broker.xml 元素是 bridge。其他桥接技术使用 <broker-connection> 元素。

17.1. 代理连接的发送者和接收器配置

通过在 broker.xml<broker-connections> 部分中创建发件人或接收器代理连接元素,可以将代理连接到另一个代理。

对于 发件人,代理会在将消息发送到另一个代理的队列上创建一个消息使用者。

对于 接收方,代理会在接收来自另一个代理的消息地址上创建一个消息制作者。

这两个元素充当消息网桥。但是,处理消息不需要额外的开销。发送者和接收方的行为与代理中的任何其他消费者或生产者的行为都一样。

特定的队列可以由发送方或接收方配置。通配符表达式可用于将发送者和接收器与特定地址或地址 匹配。在配置发送方或接收器时,可以设置以下属性:

  • address-match :使用通配符表达式,将发件人或接收方与特定的地址或 一组 地址匹配。
  • queue-name :为特定队列配置发件人或接收方。
  • 使用地址表达式:

    <broker-connections>
      <amqp-connection uri="tcp://HOST:PORT" name="other-server">
        <sender address-match="queues.#"/>
        <!-- notice the local queues for remotequeues.# need to be created on this broker -->
        <receiver address-match="remotequeues.#"/>
      </amqp-connection>
    </broker-connections>
    
    <addresses>
      <address name="remotequeues.A">
        <anycast>
          <queue name="remoteQueueA"/>
        </anycast>
      </address>
      <address name="queues.B">
        <anycast>
          <queue name="localQueueB"/>
        </anycast>
      </address>
    </addresses>
  • 使用队列名称:

    <broker-connections>
      <amqp-connection uri="tcp://HOST:PORT" name="other-server">
        <receiver queue-name="remoteQueueA"/>
        <sender queue-name="localQueueB"/>
      </amqp-connection>
    </broker-connections>
    
    <addresses>
       <address name="remotequeues.A">
         <anycast>
           <queue name="remoteQueueA"/>
         </anycast>
       </address>
       <address name="queues.B">
         <anycast>
           <queue name="localQueueB"/>
         </anycast>
       </address>
    </addresses>
注意

接收器只能与已存在的本地队列匹配。因此,如果使用接收器,请确保在本地预先创建队列。否则,代理将无法与远程队列和地址匹配。

注意

不要创建具有相同目的地的发件者和接收方,因为这会产生发送和接收的无限循环。

17.2. 代理连接的对等配置

代理可以配置为连接到 AMQ 互连实例的对等点,并指示代理将为该路由器上配置的给定 AMQP 方法点地址充当存储转发队列。在这种情况下,客户端连接到路由器以使用一个方法点地址发送和接收消息,路由器将这些消息路由到代理上的队列或从该队列路由。

此对等配置为每个目的地创建一个发送者和接收器对,该端点与代理上的代理连接配置匹配。这些对包括使路由器能够与代理协作的配置。此功能避免路由器启动连接和创建自动链接的要求。

如需有关可能路由器配置的更多信息,请参阅使用 AMQ Interconnect 路由器

使用对等配置时,存在与有发送方和接收器时相同的属性。例如:具有名称开头队列的 队列 的配置。作为匹配路由器方法点地址的存储将是:

<broker-connections>
  <amqp-connection uri="tcp://HOST:PORT" name="router">
    <peer address-match="queues.#"/>
  </amqp-connection>
</broker-connections>

<addresses>
   <address name="queues.A">
     <anycast>
       <queue name="queues.A"/>
     </anycast>
   </address>
   <address name="queues.B">
     <anycast>
       <queue name="queues.B"/>
     </anycast>
   </address>
</addresses>

路由器上必须具有匹配的地址点配置。这指示它将代理连接到的特定路由器地址视为方法点。例如,请查看以下基于前缀的路由器地址配置:

address {
    prefix: queue
    waypoint: yes
}

有关这个选项的更多信息,请参阅 使用 AMQ Interconnect 路由器

注意

不要使用 peer 选项直接连接到其他代理。如果您使用这个选项连接到另一个代理,所有消息都会立即准备好使用,创建无限回显发送和接收。

第 18 章 日志

AMQ Broker 使用 JBoss Logging 框架进行日志记录,并通过 <broker_instance_dir>/etc/logging.properties 配置文件进行配置。此配置文件是键值对的列表。

您可以在代理配置中指定日志记录器,方法是将它们包含在 logging.properties 配置文件的 loggers 密钥中,如下所示。

loggers=org.eclipse.jetty,org.jboss.logging,org.apache.activemq.artemis.core.server,org.apache.activemq.artemis.utils,org.apache.activemq.artemis.journal,org.apache.activemq.artemis.jms.server,org.apache.activemq.artemis.integration.bootstrap,org.apache.activemq.audit.base,org.apache.activemq.audit.message,org.apache.activemq.audit.resource

下表中显示了 AMQ Broker 中可用的日志记录器。

日志记录器Description

org.jboss.logging

根日志记录器.记录其他代理日志记录器未处理的所有调用。

org.apache.activemq.artemis.core.server

记录代理内核

org.apache.activemq.artemis.utils

日志实用程序调用

org.apache.activemq.artemis.journal

日志日志调用

org.apache.activemq.artemis.jms

日志 JMS 调用

org.apache.activemq.artemis.integration.bootstrap

日志 bootstrap 调用

org.apache.activemq.audit.base

记录对所有 JMX 对象方法的访问

org.apache.activemq.audit.message

记录消息操作,如生产、消耗和浏览消息

org.apache.activemq.audit.resource

从 JMX 或 AMQ Broker 管理控制台记录身份验证事件、创建或删除代理资源,并在管理控制台中浏览消息

logger.handlers 键中也配置了两个默认的日志记录处理程序,如下所示:

logger.handlers=FILE,CONSOLE
logger.handlers=FILE
日志记录器将日志条目输出到文件中。
logger.handlers=CONSOLE
日志记录器将日志条目输出到 AMQ Broker 管理控制台。

18.1. 更改日志级别

所有日志记录器的默认日志记录级别为 INFO,在根日志记录器上配置,如下所示。

logger.level=INFO

您可以单独为所有其他日志记录器配置日志级别,如下所示:

logger.org.apache.activemq.artemis.core.server.level=INFO
logger.org.apache.activemq.artemis.journal.level=INFO
logger.org.apache.activemq.artemis.utils.level=INFO
logger.org.apache.activemq.artemis.jms.level=INFO
logger.org.apache.activemq.artemis.integration.bootstrap.level=INFO
logger.org.apache.activemq.audit.base.level=INFO
logger.org.apache.activemq.audit.message.level=INFO
logger.org.apache.activemq.audit.resource.level=INFO

下表中描述了可用的日志记录级别。日志记录级别以升序列出,从最不详细到最不详细的顺序。

级别Description

FATAL

对于指示关键服务失败的事件,使用 FATAL 日志记录级别。如果服务发出 FATAL 错误,则完全无法执行任何类型的请求。

ERROR

将 ERROR 日志记录级别用于指示请求中中断的事件或为请求服务的功能。服务应具有 一些 容量,以便在出现此级别的错误时继续服务请求。

WARN

对于可能指示非关键服务错误的事件,请使用 WARN 日志记录级别。请求预期可重复使用的错误或次要漏洞符合此描述。WARN 和 ERROR 之间的区别是应用开发人员可以做出的。进行此区别的一个简单标准是错误是否需要用户寻求技术支持。如果错误需要技术支持,请将日志级别设置为 ERROR。否则,将级别设置为 WARN。

INFO

将 INFO 日志记录级别用于服务生命周期事件和其他关键相关信息。给定服务类别的 INFO 级别消息应清楚指明服务所处的状态。

DEBUG

将 DEBUG 日志级别用于日志消息,这些消息为生命周期事件传达额外信息。使用此日志级别获取面向开发人员的信息或技术支持所需的深度信息。启用 DEBUG 日志记录级别后,JBoss 服务器日志 不应与 服务器请求数量成比例增长。给定服务类别的 DEBUG 和 INFO 级别消息应清楚指明服务所处的状态,以及该服务使用的代理资源、端口、接口和日志文件等。

TRACE

将 TRACE 日志记录级别用于与请求活动直接关联的日志消息。此类消息不应提交到日志记录器,除非日志记录器类别优先级阈值表示将呈现消息。使用 Logger.isTraceEnabled() 方法确定是否启用类别优先级阈值。TRACE 级别日志记录可在需要时深入探查代理行为。启用 TRACE 日志记录级别后,JBoss sever 日志中的消息数量至少增长 * N,其中 N 是代理收到的请求数,并且 a 是一个恒定的。根据正在跟踪的请求处理层,服务器日志可能会增大到 N 的一些动力。

注意
  • INFO 是 logger.org.apache.activemq .audit.base、logger.org.apache.activemq.audit .message 和 logger.org.apache.activemq.audit .message 和 logger.activemq.audit.resource 审计日志记录器唯一可用的日志记录级别。
  • 为根日志记录器指定的日志记录级别决定了 所有 日志记录器的最详细日志记录级别,即使其他日志记录器在其配置中指定了更详细的日志记录级别。例如,假设 org.apache.activemq.artemis.utils 具有指定的 DEBUG 记录,而根日志记录器 org.jboss.logging 具有指定的日志记录级别 WARN。在这种情况下,两个日志记录器都使用日志记录器的日志记录级别 WARN

18.2. 启用审计日志记录

有三个审计日志记录器可供您启用:基础审计日志记录器、消息审计日志记录器和资源审计日志记录器。

基础审计日志记录器(org.apache.activemq.audit.base)
记录对所有 JMX 对象方法 的访问,如创建和删除地址和队列。日志 指示这些操作是成功还是失败。
消息审计日志记录器(org.apache.activemq.audit.message)
记录消息相关的代理操作,如生产、消耗或浏览消息。
资源审计日志记录器(org.apache.activemq.audit.resource)
记录客户端、路由和 AMQ Broker 管理控制台的身份验证成功或失败。另外,记录从 JMX 或管理控制台创建、更新或删除队列的日志,并在管理控制台中浏览消息。

您可以独立于其他审计日志记录器启用每个审计日志记录器。默认情况下,每个审计日志记录器都已禁用(即日志记录级别设为 ERROR,这不是审计日志记录器的有效日志记录级别)。若要启用其中一个审计日志记录器,可将日志记录级别设置为 INFO。例如:

logger.org.apache.activemq.audit.base.level=INFO
重要

消息审计日志记录器在代理上的性能密集型路径中运行。启用日志记录器可能会对代理的性能造成负面影响,特别是代理在高消息传递负载下运行时。不建议在需要高吞吐量的消息传递系统上使用消息审计日志记录器。

18.3. 配置控制台日志

您可以使用以下密钥配置控制台日志:

handler.CONSOLE=org.jboss.logmanager.handlers.ConsoleHandler
handler.CONSOLE.properties=autoFlush
handler.CONSOLE.level=DEBUG
handler.CONSOLE.autoFlush=true
handler.CONSOLE.formatter=PATTERN
注意

handler.CONSOLE 引用 logger.handlers 键中给出的名称。

下表中描述了控制台日志配置选项。

属性Description

name

处理程序名称

编码

处理程序使用的字符编码

level

日志记录级别,指定记录的消息级别。低于这个值的消息级别会被丢弃。

formatter

定义格式化器。请参阅 第 18.5 节 “配置日志记录格式”

autoflush

在每次写入后是否自动清除日志

目标

控制台处理程序的目标。该值可以是 SYSTEM_OUT 或 SYSTEM_ERR。

18.4. 配置文件日志记录

您可以使用以下密钥配置文件记录:

handler.FILE=org.jboss.logmanager.handlers.PeriodicRotatingFileHandler
handler.FILE.level=DEBUG
handler.FILE.properties=suffix,append,autoFlush,fileName
handler.FILE.suffix=.yyyy-MM-dd
handler.FILE.append=true
handler.FILE.autoFlush=true
handler.FILE.fileName=${artemis.instance}/log/artemis.log
handler.FILE.formatter=PATTERN
注意

handler.FILE 引用 logger.handlers 键中给出的名称。

下表描述了文件日志配置选项。

属性Description

name

处理程序名称

编码

处理程序使用的字符编码

level

日志记录级别,指定记录的消息级别。低于这个值的消息级别会被丢弃。

formatter

定义格式化器。请参阅 第 18.5 节 “配置日志记录格式”

autoflush

在每次写入后是否自动清除日志

附加

指定是否附加到目标文件

file

文件描述,由路径和可选相对于路径的相对路径组成.

18.5. 配置日志记录格式

formatter 描述了日志消息的显示方式。以下是默认配置:

formatter.PATTERN=org.jboss.logmanager.formatters.PatternFormatter
formatter.PATTERN.properties=pattern
formatter.PATTERN.pattern=%d{HH:mm:ss,SSS} %-5p [%c] %s%E%n

在前面的配置中,%s 是消息,%E 就是例外(如果存在)。

格式与 Log4J 格式相同。可 在此处 找到完整描述。

18.6. 客户端或嵌入式服务器日志记录

如果要启用客户端登录,您需要在客户端的类路径中包含 JBoss 日志 JAR。如果使用 Maven,请添加以下依赖项:

<dependency>
   <groupId>org.jboss.logmanager</groupId>
   <artifactId>jboss-logmanager</artifactId>
   <version>1.5.3.Final</version>
</dependency>
<dependency>
   <groupId>org.apache.activemq</groupId>
   <artifactId>artemis-core-client</artifactId>
   <version>1.0.0.Final</version>
</dependency>

启动 Java 程序时,您需要设置两个属性:第一种方法是将日志管理器设置为使用 JBoss 日志管理器。这可以通过设置 '-Djava.util.logging.manager'property 来完成。例如:

-Djava.util.logging.manager=org.jboss.logmanager.LogManager

第二步是设置要使用的 logging.properties 文件的位置。这可以通过使用有效 URL 设置 -Dlogging.configuration 属性来完成。例如:

-Dlogging.configuration=file:///home/user/projects/myProject/logging.properties

以下是客户端的典型 logging.properties 文件:

# Root logger option
loggers=org.jboss.logging,org.apache.activemq.artemis.core.server,org.apache.activemq.artemis.utils,org.apache.activemq.artemis.journal,org.apache.activemq.artemis.jms,org.apache.activemq.artemis.ra

# Root logger level
logger.level=INFO
# ActiveMQ Artemis logger levels
logger.org.apache.activemq.artemis.core.server.level=INFO
logger.org.apache.activemq.artemis.utils.level=INFO
logger.org.apache.activemq.artemis.jms.level=DEBUG

# Root logger handlers
logger.handlers=FILE,CONSOLE

# Console handler configuration
handler.CONSOLE=org.jboss.logmanager.handlers.ConsoleHandler
handler.CONSOLE.properties=autoFlush
handler.CONSOLE.level=FINE
handler.CONSOLE.autoFlush=true
handler.CONSOLE.formatter=PATTERN

# File handler configuration
handler.FILE=org.jboss.logmanager.handlers.FileHandler
handler.FILE.level=FINE
handler.FILE.properties=autoFlush,fileName
handler.FILE.autoFlush=true
handler.FILE.fileName=activemq.log
handler.FILE.formatter=PATTERN

# Formatter pattern configuration
formatter.PATTERN=org.jboss.logmanager.formatters.PatternFormatter
formatter.PATTERN.properties=pattern
formatter.PATTERN.pattern=%d{HH:mm:ss,SSS} %-5p [%c] %s%E%n

18.7. AMQ Broker 插件支持

AMQ 支持自定义插件。您可以使用插件记录许多不同类型事件的信息,否则它们只能通过 debug 日志获得。可以一起注册、绑定和执行多个插件。这些插件将根据注册顺序执行,即,已注册的第一个插件始终先执行。

您可以使用 ActiveMQServerPlugin 接口创建自定义插件并实施它们。此接口确保插件位于类路径中,并在代理中注册。由于所有接口方法都是默认实施的,因此您必须仅添加需要实施的必要行为。

18.7.1. 在类路径中添加插件

通过将相关 .jar 文件添加到 <broker_instance_dir>/lib 目录中,将自定义创建的代理插件添加到代理运行时。

如果您使用嵌入式系统,然后将 .jar 文件放在嵌入式应用的常规类路径下。

18.7.2. 注册插件

您必须通过在 broker .xml 配置文件中添加 broker-plugins 元素来注册插件。您可以使用 attribute 元素指定插件配置值。这些属性将在插件实例化后读取并传递到插件的 init(Map<String, String>)操作中。

<broker-plugins>
   <broker-plugin class-name="some.plugin.UserPlugin">
      <property key="property1" value="val_1" />
      <property key="property2" value="val_2" />
   </broker-plugin>
 </broker-plugins>

18.7.3. 以编程方式注册插件

若要以编程方式注册插件,请使用 registerBrokerPlugin() 方法,并传递您的插件的新实例。以下示例显示了 UserPlugin 插件的注册:

Configuration config = new ConfigurationImpl();

config.registerBrokerPlugin(new UserPlugin());

18.7.4. 记录特定的事件

默认情况下,AMQ 代理提供 LoggingActiveMQServerPlugin 插件来记录特定的代理事件。LoggingActiveMQServer 插件 默认被注释掉,不会记录任何信息。

下表描述了各个插件属性。将配置属性值设为 true 以记录事件。

属性

Description

LOG_CONNECTION_EVENTS

创建或销毁连接时记录信息。

LOG_SESSION_EVENTS

在会话创建或关闭时记录信息。

LOG_CONSUMER_EVENTS

创建或关闭消费者时日志信息。

LOG_DELIVERING_EVENTS

将消息传送给消费者以及使用者确认消息时,记录信息。

LOG_SENDING_EVENTS

当消息被发送到地址以及代理中路由了消息时,记录信息。

LOG_INTERNAL_EVENTS

创建或销毁队列、消息过期、部署网桥以及发生关键故障时,记录信息。

LOG_ALL_EVENTS

所有上述事件的日志信息。

要将 LoggingActiveMQServerPlugin 插件配置为记录连接事件,请取消 broker.xml 配置文件中的 <broker-plugins> 部分的 注释。所有事件的值在注释的默认示例中被设置为 true

<configuration ...>
...
<!-- Uncomment the following if you want to use the Standard LoggingActiveMQServerPlugin plugin to log in events -->
           <broker-plugins>
         <broker-plugin class-name="org.apache.activemq.artemis.core.server.plugin.impl.LoggingActiveMQServerPlugin">
            <property key="LOG_ALL_EVENTS" value="true"/>
            <property key="LOG_CONNECTION_EVENTS" value="true"/>
            <property key="LOG_SESSION_EVENTS" value="true"/>
            <property key="LOG_CONSUMER_EVENTS" value="true"/>
            <property key="LOG_DELIVERING_EVENTS" value="true"/>
            <property key="LOG_SENDING_EVENTS" value="true"/>
            <property key="LOG_INTERNAL_EVENTS" value="true"/>
         </broker-plugin>
      </broker-plugins>
...
</configuration>

当您更改了 <broker-plugins> 部分中的配置参数 后,您必须重启代理来重新载入配置更新。这些配置更改 不会 根据 configuration-file-refresh-period 设置重新加载。

当日志级别设置为 INFO 时,会在事件发生后记录条目。如果日志级别设为 DEBUG,则在事件前后都会生成日志条目,例如: CreateConsumer()afterCreateConsumer()。如果日志级别设为 DEBUG,则日志记录器会在可用时记录通知的更多信息。

附录 A. 接收器和连接器配置参数

下表详细介绍了用于配置 Netty 网络连接的一些可用参数。参数及其值附加到连接字符串的 URI。如需更多信息,请参阅在网络连接中配置接收器和连接器。每个表格按名称列出参数,并记录它们是否能与接收器或连接器一起使用。例如,您可以使用一些参数,例如仅与接收器一起使用。

注意

所有 Netty 参数在类 org.apache.activemq.artemis.core.remoting.impl.netty.TransportConstants 中定义。源代码可用于在 客户门户 上下载。

表 A.1. Netty TCP 参数

参数与…​Description

batchDelay

两者

在将数据包写入接收器或连接器之前,可以将代理配置为批量写入,最多可进行 batchDelay 毫秒。这可以提高非常小的消息的总吞吐量。它这样做会牺牲消息传输的平均延迟。默认值为 0 ms。

connectionsAllowed

接收器

限制接收器允许的连接数。达到此限制时,会向日志发出 DEBUG 级别消息,连接将被拒绝。使用中的客户端类型决定了在连接被拒绝时会发生什么。

directDeliver

两者

当消息到达服务器并传送到等待的消费者时,默认情况下,发送操作会在与邮件到达时相同的线程上执行。这在消息相对较少和数量较少、消费者数量较少、但代价是整体吞吐量和可扩展性(特别是在多核机器上)的环境中提供了很好的延迟。如果您想要最低延迟并尽可能降低吞吐量,则可以使用 directDeliver 的默认值 这是 true。如果您希望对延迟产生一些很小的额外影响,但希望将 directDeliver 的最高吞吐量设置为 false

handshake-timeout

接收器

防止未授权的客户端打开大量连接并保持开放。由于每个连接都需要一个文件句柄,它会消耗随后其他客户端不可用的资源。

此超时限制连接可在不通过身份验证的情况下消耗资源的时间。验证连接后,您可以使用资源限制设置来限制资源消耗。

默认值为 10 秒。您可以将其设置为任何其他整数值。您可以通过将其设置为 0 或负整数来关闭这个选项。

编辑超时值后,必须重启代理。

localAddress

连接器

指定在连接到远程地址时客户端将使用的本地地址。这通常用于应用服务器或运行 Embedded 来控制用于出站连接的地址。如果没有设置 local-address,连接器将使用任何可用的本地地址。

localPort

连接器

指定在连接到远程地址时客户端将使用的本地端口。这通常用于应用服务器或运行 Embedded 来控制用于出站连接的端口。如果使用默认值,即 0,则连接器将允许系统采用临时端口。有效端口为 0 到 65535

nioRemotingThreads

两者

当配置为使用 NIO 时,代理将默认使用等于 Runtime.getRuntime().availableProcessors()报告的内核数(或超线程) 的三倍线程。如果要覆盖这个值,可以通过指定这个参数来设置线程数量。此参数的默认值为 -1,这表示使用派生自 Runtime.getRuntime().availableProcessors()* 3 的值。

tcpNoDelay

两者

如果 情况如此Nagle 的算法 将被禁用。这是 Java(客户端)套接字选项。默认值为 true

tcpReceiveBufferSize

两者

以字节为单位确定 TCP 接收缓冲区的大小。默认值为 32768

tcpSendBufferSize

两者

以字节为单位确定 TCP 发送缓冲区的大小。默认值为 32768

TCP 缓冲区大小应该根据网络的带宽和延迟来调优。

在摘要中,TCP 发送/接收缓冲区大小计算为:

buffer_size = bandwidth * RTT.

其中带宽以每秒字节为单位,而网络往返时间(RTT)则以秒为单位。RTT 可使用 ping 实用程序轻松测量。

对于快速网络,您可能希望增加默认的缓冲区大小。

表 A.2. Netty HTTP 参数

参数与…​Description

httpClientIdleTime

接收器

在发送空 HTTP 请求以保持连接处于活动状态之前,客户端可以闲置多长时间。

httpClientIdleScanPeriod

接收器

空闲客户端扫描的频率(以毫秒为单位)。

httpEnabled

接收器

不再需要。使用单一端口支持时,代理现在将自动检测是否使用 HTTP 并配置其自身。

httpRequiresSessionId

两者

如果为 true,客户端将在第一次调用后等待接收会话 ID。HTTP 连接器连接到 servlet 接收器时使用。不建议使用此配置。

httpResponseTime

接收器

服务器在发送空 HTTP 响应前可以等待的时长,以保持连接处于活动状态。

httpServerScanPeriod

接收器

需要响应的客户端扫描的频率(以毫秒为单位)。

表 A.3. Netty TLS/SSL 参数

参数与…​Description

enabledCipherSuites

两者

用于 SSL 通信的密码套件的逗号分隔列表。默认值为空,表示将使用 JVM 的默认值。

enabledProtocols

两者

用于 SSL 通信的协议的逗号分隔列表。默认值为空,表示将使用 JVM 的默认值。

forceSSLParameters

连接器

控制是否使用作为连接器上参数设置的 SSL 设置,而非 JVM 系统属性(包括 javax.net.ssl 和 AMQ Broker 系统属性),以为此连接器配置 SSL 上下文。

有效值为 true 或者 false。默认值为 false

keyStorePassword

两者

在接收器上使用时,这是服务器端密钥存储的密码。

在连接器上使用时,这是客户端密钥存储的密码。只有当您使用双向 SSL(即相互身份验证)时,这才与连接器相关。虽然可以在服务器上配置此值,但它会被客户端下载和使用。如果客户端需要使用与服务器上设置的不同密码不同的密码,那么它可以使用规范的 javax.net.ssl.keyStorePassword 系统属性或 ActiveMQ 特定的 org.apache.activemq.ssl.keyStorePassword 系统属性覆盖服务器端设置。如果客户端上的另一个组件已在使用标准的 Java 系统属性,ActiveMQ 相关的系统属性很有用。

keyStorePath

两者

在接收器上使用时,这是存储服务器证书(无论是自签名还是由颁发机构签名)的服务器上的 SSL 密钥存储路径。

在连接器中使用时,这是到存放客户端证书的客户端 SSL 密钥存储的路径。只有当您使用双向 SSL(即相互身份验证)时,这才与连接器相关。虽然此值在服务器上配置,但它会被客户端下载和使用。如果客户端需要使用与服务器上设置的不同路径不同的路径,那么它可以使用规范的 javax.net.ssl.keyStore 系统属性或 ActiveMQ 特定的 org.apache.activemq.ssl.keyStore 系统属性来覆盖服务器端设置。如果客户端上的另一个组件已在使用标准的 Java 系统属性,ActiveMQ 相关的系统属性很有用。

needClientAuth

接收器

告知客户端连接到此接收器的客户端需要双向 SSL。有效值为 true 或者 false。默认值为 false

sslEnabled

两者

必须为 true 才能启用 SSL。默认值为 false

trustManagerFactoryPlugin

两者

定义实施 org.apache.activemq.artemis.api.core.TrustManagerFactoryPlugin 的类的名称。

这是一个简单接口,它通过一个返回 javax.net.ssl.TrustManagerFactory 的方法。当初始化底层的 javax.net.ssl.SSLContext 时,会使用 TrustManagerFactory。这允许精细地自定义谁或什么代理和客户端信任。

trustManagerFactoryPlugin 的值优先于适用于信任管理器的所有其他 SSL 参数(即 trustAll、trustedstoreProvider、trusted storePath、trustedstorePasswordcrlPath)。

您需要将任何指定的插件放在代理的 Java 类路径中。您可以使用 <broker_instance_dir>/lib 目录,因为它默认是类路径的一部分。

trustStorePassword

两者

在接收器上使用时,这是服务器端信任存储的密码。只有在您使用双向 SSL(即相互身份验证)时,这才与接收器相关。

在连接器上使用时,这是客户端信任存储的密码。虽然可以在服务器上配置此值,但它会被客户端下载和使用。如果客户端需要使用与服务器上设置的不同密码不同的密码,那么它可以使用规范的 javax.net.ssl.trustStorePassword 系统属性或 ActiveMQ 特定的 org.apache.activemq.ssl.trustStorePassword 系统属性覆盖服务器端设置。如果客户端上的另一个组件已在使用标准的 Java 系统属性,ActiveMQ 相关的系统属性很有用。

sniHost

两者

在接收器上使用 时,sniHost 是一个用于匹配传入 SSL 连接中的 server_name 扩展的正则表达式(有关此扩展的更多信息,请参阅 https://tools.ietf.org/html/rfc6066)。如果名称不匹配,则拒绝与接收器的连接。如果发生这种情况,则会记录 WARN 消息。

如果传入连接不包含 server_name 扩展名,则接受连接。

在连接器上使用时,sniHost 值用于 SSL 连接上的 server_name 扩展。

sslProvider

两者

用于在 JDK 和 OPENSSL 之间更改 SSL 提供程序.默认值为 JDK

如果设置为 OPENSSL,您可以在类路径中添加 netty-tcnative,以使用原生安装的 OpenSSL。

如果要使用受 OpenSSL 支持但不通过 JDK 供应商支持的特殊密码库-elliptic curve 组合,这个选项很有用。

trustStorePath

两者

在接收器上使用时,这是服务器端 SSL 密钥存储的路径,该密钥存储存放服务器信任的所有客户端的密钥。只有在您使用双向 SSL(即相互身份验证)时,这才与接收器相关。

在连接器中使用时,这是客户端 SSL 密钥存储的路径,该密钥存储存放客户端信任的所有服务器的公钥。虽然可以在服务器上配置此值,但它会被客户端下载和使用。如果客户端需要使用与服务器上设置的不同路径不同的路径,那么它可以使用规范的 javax.net.ssl.trustStore 系统属性或 ActiveMQ 特定的 org.apache.activemq.ssl.trustStore 系统属性来覆盖服务器端设置。如果客户端上的另一个组件已在使用标准的 Java 系统属性,ActiveMQ 相关的系统属性很有用。

useDefaultSslContext

连接器

允许连接器使用"默认"SSL 上下文(通过 SSLContext.getDefault()),该上下文可以通过客户端以编程方式设置(通过 SSLContext.setDefault(SSLContext))。

如果此参数设为 true,则 忽略除 for sslEnabled 以外的所有其他 SSL 相关参数。有效值为 true 或者 false。默认值为 false

verifyHost

两者

在连接器中使用时,会将服务器的 SSL 证书的 CN 或 Subject 备用名称值与正在连接到的主机名进行比较,以验证它们是否匹配。这对单向和双向 SSL 很有用。

在接收器上使用时,将连接客户端 SSL 证书的 CN 或主题备用名称值与其主机名进行比较,以验证它们是否匹配。这仅适用于双向 SSL。

有效值为 true 或者 false。连接器的默认值为 true,接收器的默认值为 false

wantClientAuth

接收器

告知客户端连接此接收器的客户端请求双向 SSL,但不强制要求。有效值为 true 或者 false。默认值为 false

如果属性 requireClientAuth 设为 true,则该属性具有优先权,并且希望ClientAuth 被忽略。

附录 B. 地址设置配置元素

下表列出了 address-setting 的所有配置元素:请注意,一些元素被标记为 DEPRECATED。使用建议的替换以避免潜在的问题。

表 B.1. 地址设置元素

NameDescription

address-full-policy

决定在配置了 max-size-bytes 的地址满时会发生什么情况。可用的策略有:

PAGE :发送到完整地址的消息将传到磁盘。

DROP :发送到完整地址的消息将被静默丢弃。

FAIL :发送给完整地址的消息将被丢弃,信息制作者将收到异常。

BLOCK :当消息制作者尝试并发送任何其他消息时,他们将会阻止消息制作者。

注意

BLOCK 策略仅适用于 AMQP、OpenWire 和 Core 协议,因为它们功能流控制。

auto-create-addresses

客户端发送消息时是否自动创建地址,或尝试使用映射到没有队列的地址的队列中的消息。默认值为 true

auto-create-dead-letter-resources

指定代理是否自动创建一个死信地址和队列来接收未传送的信息。默认值为 false

如果参数设为 true,代理会自动创建一个 <address> 元素来定义死信地址和关联的死信队列。自动创建的 <address> 元素的名称与您为 <dead-letter-address> 指定的名称值匹配。

auto-create-jms-queues

已弃用:改为使用 auto-create-queues。确定在 JMS 制作者或消费者尝试使用此类队列时,此代理是否应自动创建与地址设置匹配的 JMS 队列。默认值为 false

auto-create-jms-topics

已弃用:改为使用 auto-create-queues。确定在 JMS 制作者或消费者尝试使用此类队列时,此代理是否应自动创建与地址设置匹配的 JMS 主题。默认值为 false

auto-create-queues

客户端发送消息时是否自动创建队列,还是尝试使用来自队列的消息。默认值为 true

auto-delete-addresses

当代理不再有队列时,是否删除自动创建的地址。默认值为 true

auto-delete-jms-queues

已弃用:改为使用 auto-delete-queues。决定 AMQ Broker 是否应该在没有消费者且没有消息时自动删除自动创建的 JMS 队列。默认值为 false

auto-delete-jms-topics

已弃用:改为使用 auto-delete-queues。决定 AMQ Broker 是否应该在没有消费者且没有消息时自动删除自动创建的 JMS 主题。默认值为 false

auto-delete-queues

当队列没有消费者且没有消息时,是否要删除自动创建的队列。默认值为 true

config-delete-addresses

重新载入配置文件时,此设置指定了如何处理从 配置文件中删除的地址(及其队列)。您可以指定以下值:

OFF (默认)
当重新加载配置文件时,该地址不会被删除。
FORCE
当重新加载配置文件时,地址及其队列将被删除。如果队列中有任何消息,它们也会被删除。

config-delete-queues

重新载入配置文件时,此设置指定了如何处理从配置文件中删除的队列。您可以指定以下值:

OFF (默认)
在重新加载配置文件时,队列不会被删除。
FORCE
重新加载配置文件时,队列将被删除。如果队列中有任何消息,它们也会被删除。

dead-letter-address

代理将死信息发送到的地址。

dead-letter-queue-prefix

代理应用到自动创建的死信队列名称的前缀。默认值为 DLQ。

dead-letter-queue-suffix

代理应用到自动创建的死信队列的后缀。未定义默认值(即代理不应用后缀)。

default-address-routing-type

自动创建地址中使用的 routing-type。默认值为 MULTICAST

default-max-consumers

此队列中任意时间允许的最大消费者数量。默认值为 200

default-purge-on-no-consumers

是否在没有消费者的情况下清除队列的内容。默认值为 false

default-queue-routing-type

自动创建的队列中使用的 routing-type。默认值为 MULTICAST

enable-metrics

指定配置的指标插件(如 Prometheus 插件)是收集匹配地址的指标或地址 。默认值为 true

expiry-address

将接收过期邮件的地址。

expiry-delay

定义将使用毫秒的过期时间(以毫秒为单位),用于使用默认到期时间的消息。默认值为 -1,即没有过期时间。

last-value-queue

队列是否只使用最后一个值。默认值为 false

management-browse-page-size

管理资源可以浏览的消息数。默认值为 200

max-delivery-attempts

在发送到死信地址之前尝试发送邮件的次数。默认值为 10

max-redelivery-delay

redelivery-delay 的最大值,以毫秒为单位。

max-size-bytes

这个地址的最大内存大小,以字节为单位指定。当 address-full-policy 为 PAGINGBLOCKFAIL 时使用,这个值使用字节表示法指定,如 "K"、"Mb" 和 "GB"。默认值为 -1,它表示无限字节。此参数用于通过限制特定地址空间消耗的内存量来保护代理内存。此设置不表示当前存储在代理地址空间中的客户端发送的总字节数。这是对代理内存使用率的估算。这个值可能会根据运行时条件和某些工作负载而有所不同。建议您为每个地址空间分配最大内存量。在典型的工作负载下,代理需要大约 150% 到 200% 的内存中过期消息的有效负载大小。

max-size-bytes-reject-threshold

address-full-policy 为 BLOCK 时使用。代理开始拒绝信息之前地址的最大大小,以字节为单位。与 max-size-bytes 相结合,仅适用于 AMQP 协议。默认值为 -1,即没有限制。

message-counter-history-day-limit

为此地址保留消息计数器历史记录的天数。默认值为 0

page-max-cache-size

要在内存中保留的页面文件数,以便在分页导航期间优化 I/O。默认值为 5

page-size-bytes

以字节为单位的分页大小。也支持 KMbGB 等字节表示法。默认值为 10485760 字节,大约为 10.5 MB。

redelivery-delay

重新传送已取消消息前,以毫秒为单位等待的时间。默认值为 0

redelivery-delay-multiplier

应用到 redelivery-delay 参数的倍数。默认值为 1.0

redistribution-delay

定义在队列中最后一个消费者关闭后等待几毫秒后再重新分发任何消息所需的时间。默认值为 -1

send-to-dla-on-no-route

当设置为 true 时,如果无法路由到任何队列,消息将发送到配置的死信地址。默认值为 false

slow-consumer-check-period

慢速消费者的检查频率(秒数)。默认值为 5

slow-consumer-policy

决定识别慢速消费者时发生的情况。有效选项为 KILLNOTIFYKILL 终止消费者的连接,这会影响使用同一连接的任何客户端线程。NOTIFY 向客户端发送 CONSUMER_SLOW 管理通知。默认值为 NOTIFY

slow-consumer-threshold

在消费者被视为缓慢之前允许的最小消息消耗率。以消息/秒为单位计算.默认值为 -1,这个值没有绑定。

附录 C. 集群连接配置元素

下表列出了 cluster-connection 的所有配置元素。

表 C.1. 集群连接配置元素

NameDescription

地址

每个集群连接仅适用于与 address 字段中指定的值匹配的地址。如果未指定地址,则所有地址都将进行负载平衡。

address 字段还支持以逗号分隔的地址列表。使用排除语法 以防止地址被匹配。以下是一些示例地址:

jms.eu
匹配以 jms.eu 开头的所有地址。
!jms.eu
匹配除以 jms.eu开头的地址以外的所有地址
jms.eu.uk,jms.eu.de
匹配以 jms.eu.ukjms.eu.de开头的所有地址
jms.eu,!jms.eu.uk
匹配以 jms.eu 开头的所有地址,但不匹配以 jms.eu.uk开头的地址
注意

您不应该有多个带有重叠地址的集群连接(如 "europe" 和 "europe.news"),因为同一消息可能会在多个集群连接之间分发,从而导致重复发送。

call-failover-timeout

在故障切换尝试期间发出调用时使用。默认值为 -1,或者没有超时。

call-timeout

当数据包通过集群连接发送时,且它是一个阻止调用,则 call-timeout 将确定代理在引发异常前等待(以毫秒为单位)回复的时长。默认值为 30000

check-period

查看集群连接是否无法从另一个代理接收 ping 之间的检查间隔,以毫秒为单位。默认值为 30000

confirmation-window-size

用于从连接到的代理发送确认的窗口的大小(以字节为单位)。当代理收到 确认-window-size 字节时,它会通知其客户端。默认值为 1048576。值 -1 表示没有窗口。

connector-ref

标识要传输到集群中的其他代理的 连接器,以便它们具有正确的集群拓扑。此参数是必需的。

connection-ttl

如果集群连接停止从集群中的特定代理接收消息,则决定集群连接应保持活动的时间。默认值为 60000

discovery-group-ref

指向用于与群集中其他代理通信的 discovery-group。此元素必须包含属性 discovery-group-name,它必须匹配之前配置的 discovery-groupname 属性。

initial-connect-attempts

设置系统最初在集群中连接代理的次数。如果实现 max-retry,则这个代理会被视为永久停机,系统不会将消息路由到这个代理。默认值为 -1,这意味着无限重试。

max-hops

将代理配置为向代理加载均衡消息,这些代理只能作为链中的中间器间接连接到代理。这可以实现更复杂的拓扑结构,同时仍然提供消息负载平衡。默认值为 1,这意味着信息只分发到直接连接到这个代理的其他代理中。这个参数是可选的。

max-retry-interval

重试的最大延迟,以毫秒为单位。默认值为 2000

message-load-balancing

决定消息是否以及如何在集群中的其他代理之间分发。包含 message-load-balancing 元素,以启用负载平衡。默认值为 ON_DEMAND。您还可以提供值。有效值为:

OFF
禁用负载平衡。
STRICT
启用负载平衡并将消息转发到具有匹配队列的所有代理,无论队列是否具有活动消费者或匹配的选择器。
ON_DEMAND
启用负载平衡并确保消息仅转发到具有匹配选择器的活动使用者的代理。
OFF_WITH_REDISTRIBUTION
禁用负载平衡,但确保当没有合适的本地使用者可用时,消息仅转发到具有匹配选择器的活动消费者的代理。

min-large-message-size

如果消息大小(以字节为单位)大于 min-large-message-size,则消息大小将在通过网络发送到其他群集成员时被分成多个网段。默认值为 102400

notification-attempts

设置集群连接在连接到集群时应自行广播的次数。默认值为 2

notification-interval

设置在附加到集群时,以毫秒为单位的集群连接广播本身的频率。默认值为 1000

producer-window-size

集群连接的制作者流控制大小,以字节为单位。默认情况下禁用,但如果您在集群中使用真正大的消息,可能需要设置一个值。值 -1 表示没有窗口。

reconnect-attempts

设置系统尝试重新连接到集群中的代理的次数。如果实现 max-retry,则这个代理将被视为永久停机,系统将停止将信息路由到这个代理。默认值为 -1,这意味着无限重试。

retry-interval

以毫秒为单位确定重试尝试之间的间隔。如果创建了集群连接且目标代理还没有启动或正在引导,则来自其他代理的集群连接会重试连接到目标直到恢复。这个参数是可选的。默认值为 500 毫秒。

retry-interval-multiplier

用于在每次 重新连接尝试后增加重试间隔 的倍数。默认值为 1。

use-duplicate-detection

群集连接使用网桥连接代理,并且可以将网桥配置为在转发的每一消息中添加重复的 ID 属性。如果桥接的目标代理崩溃,然后恢复,则信息可能会从源代理中返回。通过将 use-duplicate-detection 设置为 true,任何重复的信息都会在目标代理接收时过滤并忽略。默认值为 true

附录 D. 命令行工具

AMQ Broker 包含一组命令行界面(CLI)工具,以便您可以管理消息传递日志。下表列出了每个工具的名称及其描述。

工具Description

exp

使用特殊独立 XML 格式导出消息数据。

imp

使用 exp 提供的输出,将日志导入到正在运行的代理。

data

打印有关日志记录的报告并压缩其数据.

编码

显示编码为 String 的日志的内部格式。

decode

从编码导入内部日志格式。

有关每个工具可用的命令的完整列表,请使用 help 参数,后跟工具的名称。在以下示例中,CLI 输出列出了用户输入命令后可供 数据 工具使用的所有命令 。/artemis 帮助数据

$ ./artemis help data

NAME
        artemis data - data tools group
        (print|imp|exp|encode|decode|compact) (example ./artemis data print)

SYNOPSIS
        artemis data
        artemis data compact [--broker <brokerConfig>] [--verbose]
                [--paging <paging>] [--journal <journal>]
                [--large-messages <largeMessges>] [--bindings <binding>]
        artemis data decode [--broker <brokerConfig>] [--suffix <suffix>]
                [--verbose] [--paging <paging>] [--prefix <prefix>] [--file-size <size>]
                [--directory <directory>] --input <input> [--journal <journal>]
                [--large-messages <largeMessges>] [--bindings <binding>]
        artemis data encode [--directory <directory>] [--broker <brokerConfig>]
                [--suffix <suffix>] [--verbose] [--paging <paging>] [--prefix <prefix>]
                [--file-size <size>] [--journal <journal>]
                [--large-messages <largeMessges>] [--bindings <binding>]
        artemis data exp [--broker <brokerConfig>] [--verbose]
                [--paging <paging>] [--journal <journal>]
                [--large-messages <largeMessges>] [--bindings <binding>]
        artemis data imp [--host <host>] [--verbose] [--port <port>]
                [--password <password>] [--transaction] --input <input> [--user <user>]
        artemis data print [--broker <brokerConfig>] [--verbose]
                [--paging <paging>] [--journal <journal>]
                [--large-messages <largeMessges>] [--bindings <binding>]

COMMANDS
        With no arguments, Display help information

        print
            Print data records information (WARNING: don't use while a
            production server is running)

        ...

您可以使用 工具中的帮助来了解有关如何执行每个工具命令的更多信息。例如,在用户输入 ./artemis 帮助 打印数据 后,CLI 会列出有关数据打印 命令的更多信息。

$ ./artemis help data print

NAME
        artemis data print - Print data records information (WARNING: don't use
        while a production server is running)

SYNOPSIS
        artemis data print [--bindings <binding>] [--journal <journal>]
                [--paging <paging>]

OPTIONS
        --bindings <binding>
            The folder used for bindings (default ../data/bindings)

        --journal <journal>
            The folder used for messages journal (default ../data/journal)

        --paging <paging>
            The folder used for paging (default ../data/paging)

附录 E. 消息传递日志配置元素

下表列出了与 AMQ Broker 消息日志相关的所有配置元素。

表 E.1. 地址设置元素

NameDescription

journal-directory

消息日志所在的目录。默认值为 <broker_instance_dir>/data/journal

为获得最佳性能,日志应位于自己的物理卷上,以便最大程度减少磁盘头移动。如果日志位于与其他可能写入其他文件的进程共享的卷(如绑定日志、数据库或交易协调器)上,则磁盘头在文件写入时可能会在这些文件之间快速移动,从而显著降低性能。

使用 SAN 时,应当为每个日志实例提供自己的 LUN(逻辑单元)。

create-journal-dir

如果设置为 true,日志目录将在 journal-directory 中指定的位置(如果尚未存在)自动创建。默认值为 true

journal-type

有效值为 NIOASYNCIO

如果设置为 NIO,代理将使用 Java NIO 接口进行其日志。设置为 ASYNCIO,代理将使用 Linux 异步 IO 日志。如果您选择 ASYNCIO 但没有运行 Linux,或者您没有安装 libaio,那么代理会检测到这一点,并自动退回到使用 NIO

journal-sync-transactional

如果设置为 true,代理会在事务边界(即提交、准备和回滚)将所有事务数据刷新到磁盘。默认值为 true

journal-sync-non-transactional

如果设置为 true,代理每次都会将非事务消息数据(发送和确认)刷新到磁盘。默认值为 true

journal-file-size

以字节为单位的每个日志文件的大小。默认值为 10485760 字节(10MiB)。

journal-min-files

代理在启动时预先创建的最少文件数。只有不存在现有消息数据时,才会预先创建文件。

根据您期望队列以稳定状态包含的数据量,您应该调整这一文件数,使其与预期的数据总量匹配。

journal-pool-files

系统将根据需要创建尽可能多的文件;但是,在回收文件时,它将缩减回 journal-pool-file

默认值为 -1,表示它不会在创建后删除日志中的文件。但是,系统无法无限增长,因为您仍需要为可能无限增长的目的地使用分页。

journal-max-io

控制任意时间上 IO 队列中的最大写入请求数。如果队列已满,则写入将阻止,直到空间被释放。

使用 NIO 时,这个值应该始终为 1。使用 AIO 时,默认值为 500。max AIO 总数不能超过操作系统级别设置的值(/proc/sys/fs/aio-max-nr),通常为 65536。

journal-buffer-timeout

控制何时清除缓冲区的超时。AIO 通常可以使用高于 NIO 的清空率,因此系统会为 NIO 和 AIO 维护不同的默认值。

NIO 的默认值为 3333333 纳秒,每秒 300 倍,AIO 的默认值为 50000 纳秒,每秒为 2000 倍。

注意

通过增大超时值,您可能会以延迟为代价提高系统吞吐量,因为选择默认值以在吞吐量和延迟之间合理平衡。

journal-buffer-size

AIO 上定时缓冲的大小。默认值为 490KiB

journal-compact-min-files

代理压缩日志前需要的最少文件数。只有至少有 journal-compact-min-files 才会启动压缩算法。默认值为 10

注意

将值设为 0 将禁用压缩,可能会很危险,因为日志可能会无限期地增长。

journal-compact-percentage

开始紧凑的阈值。如果确定少于 journal-compact-centage 是 实时数据,则将压缩日志数据。另请注意,在 日志中至少有 journal-compact-min-files 数据文件前,压缩才会开始。默认值为 30

附录 F. 复制高可用性配置元素

下表列出在使用复制 HA 策略时有效的 ha-policy 配置元素:

表 F.1. 使用复制高可用性时可用的配置元素

NameDescription

check-for-live-server

仅适用于配置为主代理的代理。指定原始 master 代理是否在启动时使用自己的服务器 ID 检查集群是否有另一个 live 代理。设置为 true,以返回到原始 master 代理,并避免出现两个代理同时存活的"脑裂"情况。此属性的默认值为 false

cluster-name

用于复制的集群配置的名称。只有在配置多个集群连接时才需要此设置。如果配置,则在连接到集群时使用这个名称的集群配置。如果未设置,则使用配置中定义的第一个集群连接。

group-name

如果设置,备份代理将只带有与 group-name 匹配值的 live 代理对。

initial-replication-sync-timeout

副本代理在完成初始复制过程后将等待时间,以便副本确认它已收到所有必要的数据。此属性的默认值为 30,000 毫秒。

注意

在此间隔内,任何其他与日志相关的操作都会被阻止。

max-saved-replicated-journals-size

仅适用于备份代理。指定备份代理保留的备份日志文件数量。达到此值后,代理通过删除最旧的日志文件来为每个新备份日志文件腾出空间。此属性的默认值为 2

allow-failback

仅适用于备份代理。决定备份代理是否在另一个代理(如 live 代理)请求代替时恢复其原始角色。此属性的默认值为 true

restart-backup

仅适用于备份代理。确定备份代理是否在故障后自动重启到另一个代理。此属性的默认值为 true

修订 2022-10-22 21:07:13 +1000