配置 AMQ Broker
使开源包含更多
红帽致力于替换我们的代码、文档和 Web 属性中存在问题的语言。我们从这四个术语开始:master、slave、黑名单和白名单。由于此项工作十分艰巨,这些更改将在即将推出的几个发行版本中逐步实施。有关更多详情,请参阅我们的首席技术官 Chris Wright 提供的消息。
第 1 章 概述
AMQ Broker 配置文件为代理实例定义重要的设置。通过编辑代理的配置文件,您可以控制代理在环境中如何工作。
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. 了解默认代理配置
您可以通过编辑 broker.xml
配置文件来配置大多数代理的功能。此文件包含默认设置,这足以启动和操作代理。但是,您可能需要更改一些默认设置,并添加新设置来为您的环境配置代理。
默认情况下,broker.xml
包含以下功能的默认设置:
- 消息持久性
- acceptors
- 安全性
- 消息地址
默认消息持久性设置
默认情况下,AMQ Broker 持久性使用由磁盘上一组文件组成的只附加文件日志。日志会保存消息、事务和其他信息。
<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>
默认接受器设置
代理通过使用 acceptor
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 密钥存储和信任存储,以建立新证书,而不影响现有客户端。连接的客户端(即使具有旧证书或不同证书)也可以继续发送和接收消息。
证书撤销列表文件(使用 crlPath
参数配置)也可以重新加载。
diverts
重新加载配置会部署您添加的 任何新的 区别。但是,在重启代理前,从配置中移除或更改 <
;divert
> 元素中的子元素不会生效。
以下流程演示了如何更改代理检查 broker.xml
配置文件更改的时间间隔。
流程
-
打开 &
lt;broker_instance_dir> /etc/broker.xml
配置文件。 在 <
;core&
gt; 元素中,添加<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 中的 使用管理 API
1.4. 修改代理配置文件
如果您有多个共享通用配置设置的代理,您可以在单独的文件中定义通用配置,然后在每个代理的 broker.xml
配置文件中包括这些文件。
您可以在代理间共享的最常见配置设置包括:
- addresses
- 地址设置
- 安全设置
流程
为您要共享的每个
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>
-
为每个应使用通用配置设置的代理打开 &
lt;broker_instance_dir> /etc/broker.xml
配置文件。 对于您打开的每个
broker.xml
文件,请执行以下操作:在
broker.xml
开头的 <configuration
> 元素中,验证是否出现以下行:xmlns:xi="http://www.w3.org/2001/XInclude"
为每个包含共享配置设置的 XML 文件添加一个 XML 包括。
这个示例包括
my-security-settings.xml
文件。broker.xml
<configuration ...> <core ...> ... <xi:include href="/opt/my-broker-config/my-security-settings.xml"/> ... </core> </configuration>
如果需要,验证
broker.xml
以验证 XML 是否对 schema 有效。您可以使用任何 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
其他资源
- 有关 XML 包含(XIncludes)的详情,请参考 https://www.w3.org/TR/xinclude/。
1.4.1. 重新载入模块化配置文件
当代理定期检查配置更改(根据 config-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 中的 使用管理 API
1.4.2. 禁用外部 XML 实体(XXE)处理
如果您不想将代理配置嵌套到 broker.xml
文件包含的独立文件中,您可以禁用 XXE 处理来保护 AMQ Broker 免受 XXE 安全漏洞。如果您没有模块化代理配置,红帽建议您禁用 XXE 处理。
流程
-
打开 &
lt;broker_instance_dir>/etc/artemis.profile
文件。 将新参数
-Dartemis.disableXxe
添加至 Java 系统参数的JAVA_ARGS
列表中。-Dartemis.disableXxe=true
-
保存
artemis.profile
文件。
1.5. 文档惯例
本文档对 sudo
命令、文件路径和可替换值使用以下惯例:
sudo
命令
在本文档中,sudo
用于任何需要 root 特权的命令。使用 sudo
时,您应始终谨慎操作,因为任何更改都可能会影响整个系统。
有关使用 sudo
的更多信息,请参阅管理 sudo 访问。
关于在此文档中使用文件路径
在这个文档中,所有文件路径都对 Linux、UNIX 和类似操作系统(例如 /home/...
)有效。如果您使用的是 Microsoft Windows,则应使用等效的 Microsoft Windows 路径(例如,C:\Users\...
)。
可替换值
本文档有时会使用可替换值,您必须将这些值替换为特定于环境的值。可替换的值为小写,以尖括号(<>)
括起,样式则使用斜体和 monospace
字体。用下划线(_
)分隔多个词语。
例如,在以下命令中,将 <install_dir>
替换为您自己的目录名称。
$ <install_dir>/bin/artemis create mybroker
第 2 章 在网络连接中配置接受器和连接器
AMQ Broker 中使用两种连接类型:网络连接和 VM 连接。两台方位于不同的虚拟机时,无论位于同一服务器还是物理远程,都使用网络连接。客户端(无论是应用程序还是服务器)位于与代理相同的虚拟机上时,会使用 in-VM 连接。
网络连接使用 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>
以下章节描述了网络连接和内连接所需的两个重要配置元素: acceptors 和 connectors。这些部分演示了如何为 TCP、HTTP 和 SSL/TLS 网络连接配置接受器和连接器,以及 in-VM 连接。
2.1. 关于接受者
acceptors 定义如何向代理进行连接。每个接受者定义客户端可用于建立连接的端口和协议。下面显示了一个简单的接受器配置。
<acceptors> <acceptor name="example-acceptor">tcp://localhost:61617</acceptor> </acceptors>
代理配置中定义的每个 acceptor
元素都包含在单个 acceptors
元素中。您可以为代理定义的 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. 配置接受者
以下示例演示了如何配置接受者。
流程
-
打开 &
lt;broker_instance_dir> /etc/broker.xml
配置文件。 在
acceptors
元素中,添加新的acceptor
元素。指定代理上的协议和端口。例如:<acceptors> <acceptor name="example-acceptor">tcp://localhost:61617</acceptor> </acceptors>
前面的示例定义了 TCP 协议的接受者。代理侦听端口 61617,以获取使用 TCP 的客户端连接。
将键值对附加到为 acceptor 定义的 URI。使用分号(
;
)分隔多个键值对。例如:<acceptor name="example-acceptor">tcp://localhost:61617?sslEnabled=true;key-store-path=</path/to/key_store></acceptor>
配置现在定义了一个使用 TLS/SSL 的 acceptor,并定义到所需密钥存储的路径。
其他资源
- 有关接受者和连接器可用配置选项的详情,请参考 附录 A, acceptor 和 Connector 配置参数。
2.3. 关于连接器
acceptors 定义代理如何接受连接,客户端使用的连接器定义它们如何连接到一个代理。
代理本身充当客户端时,会在代理上配置连接器。例如:
- 当代理桥接到另一个代理时
- 当代理在集群中执行部分时
下方显示了一个简单的连接器配置。
<connectors> <connector name="example-connector">tcp://localhost:61617</connector> </connectors>
2.4. 配置连接器
以下示例演示了如何配置连接器。
流程
-
打开 &
lt;broker_instance_dir> /etc/broker.xml
配置文件。 在
connector
元素中,添加新的connector
元素。指定代理上的协议和端口。例如:<connectors> <connector name="example-connector">tcp://localhost:61617</connector> </connectors>
前面的示例为 TCP 协议定义了一个连接器。客户端可以使用连接器配置,使用 TCP 协议连接到端口 61617 上的代理。代理本身也可以使用这个连接器进行出站连接。
将键值对附加到为连接器定义的 URI。使用分号(
;
)分隔多个键值对。例如:<connector name="example-connector">tcp://localhost:61616?tcpNoDelay=true</connector>
配置现在定义了一个连接器,它将
tcpNoDelay
属性的值设置为true
。将此属性的值设置为true
会为连接关闭 Nagle 的算法。Nagle 的算法是一种算法,用于通过延迟小数据包并将其整合到大型数据包来提高 TCP 连接的效率。
其他资源
- 有关接受者和连接器可用配置选项的详情,请参考 附录 A, acceptor 和 Connector 配置参数。
- 要了解如何在 AMQ 核心协议 JMS 客户端中配置代理连接器,请参阅 AMQ Core Protocol JMS 文档中的 配置代理连接器。
2.5. 配置 TCP 连接
AMQ Broker 使用 Netty 提供基本的、未加密的基于 TCP 的连接,它们可以配置为使用阻止 Java IO 或较新的、非阻塞的 Java NIO。对于具有许多并发连接的可扩展性,最好使用 Java NIO。但是,当您在支持数以千计的并发连接时,使用旧的 IO 有时可能会为您提供比 NIO 更高的延迟。
如果您在不受信任的网络中运行连接,您应该注意 TCP 网络连接未加密。如果安全是优先级,您可能希望考虑使用 SSL 或 HTTPS 配置来加密通过此连接发送的消息。详情请查看 第 5.1 节 “安全连接”。
在使用 TCP 连接时,所有连接都由客户端启动。代理不会启动到客户端的任何连接。这适用于强制从一个方向启动连接的防火墙策略。
对于 TCP 连接,主机和连接器 URI 端口定义用于连接的地址。
以下示例演示了如何配置 TCP 连接。
先决条件
您应该熟悉配置接受者和连接器。如需更多信息,请参阅:
流程
-
打开 &
lt;broker_instance_dir> /etc/broker.xml
配置文件。 添加新接受者或修改现有接受者。在连接 URI 中,将
tcp
指定为协议。在代理中包含 IP 地址或主机名和端口。例如:<acceptors> <acceptor name="tcp-acceptor">tcp://10.10.10.1:61617</acceptor> ... </acceptors>
根据前面的示例,代理接受来自客户端通过 IP 地址
10.10.10.1
连接到端口61617
的 TCP 通信。(可选)您可以使用类似的方式配置连接器。例如:
<connectors> <connector name="tcp-connector">tcp://10.10.10.2:61617</connector> ... </connectors>
在对指定的 IP 和端口
10.10.10.2:61617
的 TCP 连接时,上例中的连接器由客户端甚至代理本身引用。
其他资源
- 有关 TCP 连接可用配置选项的详情,请参考 附录 A, acceptor 和 Connector 配置参数。
2.6. 配置 HTTP 连接
HTTP 连接通过 HTTP 协议隧道数据包,在防火墙只允许 HTTP 流量的情况下非常有用。AMQ Broker 会自动检测 HTTP 是否被使用,因此为 HTTP 配置网络连接与为 TCP 配置连接相同。
先决条件
您应该熟悉配置接受者和连接器。如需更多信息,请参阅:
流程
-
打开 &
lt;broker_instance_dir> /etc/broker.xml
配置文件。 添加新接受者或修改现有接受者。在连接 URI 中,将
tcp
指定为协议。在代理中包含 IP 地址或主机名和端口。例如:<acceptors> <acceptor name="http-acceptor">tcp://10.10.10.1:80</acceptor> ... </acceptors>
根据上例,代理接受来自连接到 IP 地址
10.10.10.1
的端口80
的 HTTP 通信。代理自动检测 HTTP 协议正在使用,并相应地与客户端通信。(可选)您可以使用类似的方式配置连接器。例如:
<connectors> <connector name="http-connector">tcp://10.10.10.2:80</connector> ... </connectors>
使用上例中显示的连接器,代理会在 IP 地址
10.10.10.2
的端口80
上创建一个出站 HTTP 连接。
其他资源
- HTTP 连接使用与 TCP 相同的配置参数,但它也具有自己的一些配置参数。有关 HTTP 连接的所有可用配置选项的详情,请参考 附录 A, acceptor 和 Connector 配置参数。
-
有关显示如何使用 HTTP 的完整工作示例,请参阅位于代理安装的 <
install_dir>/examples/features/standard/
目录中的http-transport
示例。
2.7. 配置安全连接
您可以使用 TLS/SSL 保护网络连接。更多信息请参阅 第 5.1 节 “安全连接”。
2.8. 配置 in-VM 连接
当多个代理位于同一虚拟机上时,您可以使用 in-VM 连接,例如,作为高可用性(HA)配置的一部分。在与代理相同的 JVM 中运行的本地客户端也可以使用 in-VM 连接。
先决条件
您应该熟悉配置接受者和连接器。如需更多信息,请参阅:
流程
-
打开 &
lt;broker_instance_dir> /etc/broker.xml
配置文件。 添加新接受者或修改现有接受者。在连接 URI 中,将
vm
指定为协议。例如:<acceptors> <acceptor name="in-vm-acceptor">vm://0</acceptor> ... </acceptors>
根据上例中的 acceptor,代理接受来自 ID 为
0
的代理的连接。其他代理必须在同一虚拟机上运行。(可选)您可以使用类似的方式配置连接器。例如:
<connectors> <connector name="in-vm-connector">vm://0</connector> ... </connectors>
上例中的连接器定义了客户端如何建立到 ID 为
0
的代理,该代理在与客户端在同一虚拟机上运行。客户端可以是应用程序或其他代理。
第 3 章 在网络连接中配置消息传递协议
AMQ Broker 具有可插拔协议架构,以便您可以轻松为网络连接启用一个或多个协议。
代理支持以下协议:
除了上述协议外,代理还支持自己的原生协议,称为"Core"。以前,这个协议的版本被称为"HornetQ",供 Red Hat JBoss Enterprise Application Platform 使用。
3.1. 配置网络连接以使用消息传递协议
在使用前,您必须将协议与网络连接关联。(请参阅 第 2 章 在网络连接中配置接受器和连接器 来了解如何创建和配置网络连接。)位于文件 < broker_instance_dir>/etc/broker.xml
的默认配置包括已定义的多个连接。为方便起见,AMQ Broker 包括每个支持的协议的接受者,以及支持所有协议的默认接受者。
默认接受器概述
以下是 broker.xml
配置文件默认包括的 acceptors。
<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 上接收消息的接受者,请按照以下步骤操作:
-
打开 &
lt;broker_instance_dir> /etc/broker.xml
配置文件。 -
在 <
acceptors&
gt; 小节中添加以下行:
<acceptor name="ampq">tcp://0.0.0.0:3232?protocols=AMQP</acceptor>
默认接受器中的其他参数
在最小的 acceptor 配置中,您可以将协议指定为连接 URI 的一部分。但是,broker.xml
配置文件中的默认 acceptors 配置了一些额外的参数。下表详细介绍了为默认 acceptors 配置的额外参数。
acceptor (s) | 参数 | 描述 |
---|---|---|
all-protocols acceptor AMQP STOMP | tcpSendBufferSize |
TCP 发送缓冲区的大小(以字节为单位)。默认值为 |
tcpReceiveBufferSize |
TCP 接收缓冲区的大小(以字节为单位)。默认值为 TCP 缓冲区大小应该根据您的网络的带宽和延迟调整。 在概述 TCP 发送/接收缓冲区大小中,应计算为: buffer_size = bandwidth * RTT.
其中带宽是每秒的字节,网络往返时间(RTT)以秒为单位。可使用 对于快速网络,您可能希望从默认值中增加缓冲区大小。 | |
all-protocols acceptor AMQP STOMP HornetQ MQTT | useEpoll |
如果使用支持它的系统(Linux),请使用 Netty epoll。Netty 原生传输比 NIO 传输提供更好的性能。此选项的默认值为 |
all-protocols acceptor AMQP | amqpCredits |
AMQP 生成者可以发送的最大消息数,无论消息总大小如何。默认值为 要了解有关如何使用信用卡阻止 AMQP 信息的更多信息,请参阅 第 7.3.2 节 “阻塞 AMQP 生成者”。 |
all-protocols acceptor AMQP | amqpLowCredits |
代理 replenishes producer 信信的较低阈值。默认值为 要了解有关如何使用信用卡阻止 AMQP 信息的更多信息,请参阅 第 7.3.2 节 “阻塞 AMQP 生成者”。 |
HornetQ 兼容性接受器 | anycastPrefix |
当连接到一个使用 有关配置前缀以便客户端在连接到地址时指定路由类型的更多信息,请参阅 第 4.6 节 “在接受器配置中添加路由类型”。 |
multicastPrefix |
当连接到一个使用 有关配置前缀以便客户端在连接到地址时指定路由类型的更多信息,请参阅 第 4.6 节 “在接受器配置中添加路由类型”。 |
其他资源
- 有关您可以为 Netty 网络连接配置的其他参数的详情,请参考 附录 A, acceptor 和 Connector 配置参数。
3.2. 使用带有网络连接的 AMQP
代理支持 AMQP 1.0 规格。AMQP 链接是源和目标之间的消息的单向协议,即客户端和代理。
流程
-
打开 &
lt;broker_instance_dir> /etc/broker.xml
配置文件。 -
添加或配置一个
acceptor
来接收 AMQP 客户端,方法是包括一个值为AMQP
的protocols
参数作为 URI 的一部分。如下例所示:
<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.1. 使用 AMQP 链接作为主题
与 JMS 不同,AMQP 协议不包括主题。但是,仍然可以将 AMQP 使用者或接收器视为订阅,而不只是队列上的消费者。默认情况下,任何附加到前缀 jms.topic.
地址的链接被视为订阅,并且创建了订阅队列。根据如何配置 Terminus Durability 的方式,订阅队列具有危险或易失性,如下表中捕获:
为只使用多播队列创建此类订阅… | 将 Terminus Durability 设置为这个… |
---|---|
durable |
|
non-durable |
|
可写队列的名称由容器 ID 和链接名称组成,如 my-container-id:my-link-name
。
AMQ Broker 还支持 qpid-jms 客户端,无论用于地址的前缀是什么,都将遵守其主题的使用。
3.2.2. 配置 AMQP 安全性
代理支持 AMQP SASL 身份验证。有关如何在代理上配置基于 SASL 的身份验证的更多信息,请参阅 安全性。
3.3. 使用带有网络连接的 mq
代理支持 mq v3.1.1 和 v5.0 (以及旧的 v3.1 代码消息格式)。MQTT 是服务器的轻量级客户端,发布/订阅消息传递协议。MQTT 减少了消息传递开销和网络流量,以及客户端的代码占用。因此,MQTT 更适用于受限制的设备,如传感器和行为器,并快速成为面向互联网(IoT)的标准通信协议。
流程
-
打开 &
lt;broker_instance_dir> /etc/broker.xml
配置文件。 - 添加启用了 mq 协议的 acceptor。例如:
<acceptors> <acceptor name="mqtt">tcp://localhost:1883?protocols=MQTT</acceptor> ... </acceptors>
MQTT 带有一些有用的功能,其中包括:
- 服务质量
- 每个消息都可以定义与其关联的服务质量。代理会尝试在定义的最高服务质量级别向订阅者发送信息。
- 保留的消息
可以为特定地址保留消息。该地址的新订阅者会在任何其他消息之前接收最后的保留消息,即使在客户端连接前发送保留的消息。
保留的消息存储在名为
sys.mqtt.<topic name>
; 的队列中,并保留在队列中,直到客户端删除保留的消息,或者如果配置了到期,直到消息过期为止。当队列为空时,队列不会被删除,直到您明确删除队列。例如,以下配置删除队列:<address-setting match="$sys.mqtt.retain.#"> <auto-delete-queues>true</auto-delete-queues> <auto-delete-addresses>true</auto-delete-addresses> </address-setting>
- 通配符订阅
- MQTT 地址是分层的,类似于文件系统的层次结构。客户端可以订阅特定的主题或层次结构的整个分支。
- 将消息
- 客户端可以将"will 消息"设置为连接数据包的一部分。如果客户端通常断开连接,代理会将消息发布到指定的地址。其他订阅者会收到消息,并可相应地做出反应。
有关 mq 协议的更多信息,请参阅规格。
3.3.1. 配置 mq 属性
您可以将键值对附加到 MQTT acceptor 中,以配置连接属性。例如:
<acceptors> <acceptor name="mqtt">tcp://localhost:1883?protocols=MQTT;receiveMaximum=50000;topicAliasMaximum=50000;maximumPacketSize;134217728; serverKeepAlive=30;closeMqttConnectionOnPublishAuthorizationFailure=false</acceptor> ... </acceptors>
- receiveMaximum
-
通过指定代理在需要确认前可以从客户端接收的最大 QoS 1 和 2 个消息启用 flow-control。默认值为
65535
。-1
代表禁用客户端到代理的 flow-control。这与将值设为 0 的影响相同,但减少了 CONNACK 数据包的大小。 - topicAliasMaximum
-
为客户端指定代理支持的最大别名数。默认值为
65535
。-1 代表代理通知客户端主题别名限制。这与将值设为 0 的效果相同,但减少了 CONNACK 数据包的大小。 - maximumPacketSize
-
指定代理可以从客户端接受的最大数据包大小。默认值为
268435455
。值 -1 可防止代理通知客户端最大数据包大小,这意味着对传入的数据包的大小不会强制实施任何限制。 - serverKeepAlive
-
指定代理保持打开不活跃的客户端连接的持续时间。只有在为客户端配置的 keep-alive 值或客户端配置的值为 0 时,配置的值才会应用到连接。默认值为
60
秒。-1
表示代理总是接受客户端的 keep alive 值(即使该值为 0)。 - closeMqttConnectionOnPublishAuthorizationFailure
-
默认情况下,如果因为缺少授权而 PUBLISH 数据包失败,代理会关闭网络连接。如果您希望代理发送正确认而不是关闭网络连接,请将
closeMqttConnectionAuthorizationFailure
设置为false
。
3.4. 使用带有网络连接的 OpenWire
代理支持 OpenWire 协议,它允许 JMS 客户端直接与代理通信。使用此协议与旧版本的 AMQ Broker 通信。
目前,AMQ Broker 仅支持仅使用标准 JMS API 的 OpenWire 客户端。
流程
-
打开 &
lt;broker_instance_dir> /etc/broker.xml
配置文件。 添加或修改接受
器
,使其包含OPENWIRE
作为protocol
参数的一部分,如下例所示:<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 客户端可用于多种语言和平台,使其成为互操作性的最佳选择。
流程
-
打开 &
lt;broker_instance_dir> /etc/broker.xml
配置文件。 -
配置现有的
acceptor
或创建一个新的,其中包含值为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 时,会有以下限制:
-
代理目前不支持虚拟主机,这意味着
CONNECT
帧中的host
标头被忽略。 -
消息确认不是事务的。
ACK
帧不能是事务的一部分,如果设置了其事务
标头,它将会被忽略。
3.5.2. 为 STOMP 消息提供 ID
当通过 JMS consumer 或 QueueBrowser 接收 STOMP 消息时,消息默认不包含任何 JMS 属性,如 JMSMessageID
。但是,您可以使用代理参数在每个传入 STOMP 消息上设置消息 ID。
流程
-
打开 &
lt;broker_instance_dir> /etc/broker.xml
配置文件。 -
对于用于 STOMP 连接的
acceptor
,将stompEnableMessageId
参数设置为true
,如下例所示:
<acceptors> <acceptor name="stomp-acceptor">tcp://localhost:61613?protocols=STOMP;stompEnableMessageId=true</acceptor> ... </acceptors>
通过使用 stompEnableMessageId
参数,使用这个 acceptor 发送的每个 stomp 消息都添加了额外的属性。属性键是 amq-message-id
,值是前缀为 "STOMP" 的内部消息 ID 的 String 表示,如下例所示:
amq-message-id : STOMP12345
如果配置中没有指定 stompEnableMessageId
,则默认值为 false
。
3.5.3. 将连接时间设置为 live
在关闭连接前,STOMP 客户端必须发送 DISCONNECT
帧。这允许代理关闭任何服务器端资源,如会话和消费者。但是,如果 STOMP 客户端在没有发送 DISCONNECT 帧的情况下退出,或者它们失败,则代理不会立即知道客户端是否仍然处于活动状态。因此,STOMP 连接被配置为将 "Time to Live" (TTL)设置为 1 分钟。这意味着,如果代理闲置超过 1 分钟,代理会停止与 STOMP 客户端的连接。
流程
-
打开 &
lt;broker_instance_dir> /etc/broker.xml
配置文件。 -
将
connectionTTL
参数添加到用于 STOMP 连接的acceptor
的 URI 中,如下例所示:
<acceptors> <acceptor name="stomp-acceptor">tcp://localhost:61613?protocols=STOMP;connectionTTL=20000</acceptor> ... </acceptors>
在上例中,任何使用 stomp-acceptor
的 stomp 连接都会将其 TTL 设置为 20 秒。
STOMP 协议的版本 1.0 不包含任何心跳帧。因此,用户负责确保数据在 connection-ttl 中发送,或者代理将假定客户端被死并清理服务器端资源。通过版本 1.1,您可以使用 core-beats 来维护 stomp 连接的生命周期。
覆盖代理默认时间
如上所述,STOMP 连接的默认 TTL 为一分钟。您可以通过在代理配置中添加 connection-ttl-override
属性来覆盖这个值。
流程
-
打开 &
lt;broker_instance_dir> /etc/broker.xml
配置文件。 -
添加
connection-ttl-override
属性,并为新的默认值提供一个毫秒的值。它属于 <core>
; 小节,如下所示。
<configuration ...> ... <core ...> ... <connection-ttl-override>30000</connection-ttl-override> ... </core> <configuration>
在前面的示例中,STOMP 连接的默认生存时间(TTL)被设置为 30 秒,30000
毫秒。
3.5.4. 从 JMS 发送和使用 STOMP 消息
STOMP 主要是一个文本导向的协议。为了更轻松地与 JMS 进行交互,STOMP 实现会检查是否有 content-length
标头,以确定如何将 STOMP 消息映射到 JMS。
如果您希望 STOMP 消息映射到 … | 消息应该…。 |
---|---|
JMS TextMessage |
不包含 |
JMS BytesMessage |
包括一个 |
在将 JMS 消息映射到 STOMP 时,会应用同样的逻辑。STOMP 客户端可以确认存在 content-length
标头来确定消息正文的类型(字符串或字节)。
有关消息标头的更多信息,请参阅 STOMP 规格。
3.5.5. 将 STOMP 目的地映射到 AMQ Broker 地址和队列
在发送消息和订阅时,STOMP 客户端通常包含 一个目标
标头。目的地名称是字符串值,映射到代理上的目的地。在 AMQ Broker 中,这些目的地映射到 addresses 和 queues。有关目标帧的更多信息,请参阅 STOMP 规格。
取一个发送以下信息的 STOMP 客户端示例(包括标题和正文):
SEND destination:/my/stomp/queue hello queue a ^@
在这种情况下,代理会将消息转发到与 /my/stomp/queue
关联的任何队列。
例如,当 STOMP 客户端发送一条消息(通过使用 SEND
帧)时,指定的目的地映射到一个地址。
当客户端发送 SUBSCRIBE
或 UNSUBSCRIBE
帧时,它的工作方式相同,但在这种情况下,AMQ Broker 会将 目的地
映射到队列。
SUBSCRIBE destination: /other/stomp/queue ack: client ^@
在上例中,代理会将 目的地
映射到队列 /other/stomp/queue
。
将 STOMP 目的地映射到 JMS 目的地
JMS 目的地也映射到代理地址和队列。如果要使用 STOMP 发送消息到 JMS 目的地,STOMP 目的地必须遵循相同的约定:
通过
jms.queue
添加队列名称来发送或订阅 JMS Queue。例如,要将信息发送到orders
JMS Queue,STOMP 客户端需要发送帧:SEND destination:jms.queue.orders hello queue orders ^@
通过将 主题名称 加上
jms.topic
来发送或订阅 JMS 主题。例如,要订阅库存的
JMS 主题,STOMP 客户端必须发送类似如下的帧:SUBSCRIBE destination:jms.topic.stocks ^@
第 4 章 配置地址和队列
4.1. 地址、队列和路由类型
在 AMQ Broker 中,寻址模型包含三个主要概念: 地址、队列和 路由类型。
一个地址 代表消息传递端点。在配置中,提供一个唯一名称、一个或多个队列以及路由类型的典型地址。
队列与 地址关联。每个地址可以有多个队列。传入的消息与地址匹配后,根据配置的路由类型,消息将发送到一个或多个队列。队列可以被配置为自动创建和删除。您还可以配置一个地址(以及其关联队列)作为 durable。持久队列中的消息可能会崩溃或重启代理,只要队列中的消息也持久。相反,不可配置队列中的消息不会崩溃或重启代理,即使消息本身是持久的。
路由类型 决定了如何将消息发送到与地址关联的队列。在 AMQ Broker 中,您可以使用两种不同路由类型配置地址,如表所示。
如果您希望消息路由到… | 使用此路由类型… |
---|---|
匹配地址中的单个队列,以点对点的方式 |
|
匹配地址中的每个队列,以发布订阅方式 |
|
地址必须至少有一个定义的路由类型。
每个地址可以定义多个路由类型,但不推荐这样做。
如果一个地址同时定义了两个路由类型,并且客户端没有其首选项,则代理会默认使用 multicast
类型。
其他资源
有关配置的更多信息:
-
点到点的消息使用
anycast
路由类型,请参阅 第 4.3 节 “为点到点消息配置地址” -
使用
multicast
路由类型发布订阅消息传递,请参阅 第 4.4 节 “为发布订阅消息传递配置地址”
-
点到点的消息使用
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 使用特定的语法来代表地址设置中的通配符。通配符也可用于安全设置,也可以在创建消费者时使用。
-
通配符表达式包含以句点(
.
)分隔的词语。 数字符号 (
#
) 和星号 (*
) 字符还有特殊的用处,可以替代一个词,例如:- 数字符号字符表示"匹配任何 0 个或更多连续的词"。在您的表达式末尾使用它。
- 星号表示"匹配单个单词"。在您的表达式中的任何位置使用它。
匹配不是按照字符进行的,而是根据分割的字符段进行的。例如,一个 address-setting
项被配置为匹配名称中带有 my
的队列将不匹配名为 myqueue
的队列。
当多个 address-setting
元素与地址匹配时,代理会使用最特定匹配项的配置作为基准进行覆盖。表达式中的字面字符比通配符更具体,星号 (*
) 比数字符号更具体 (#
)。例如,my.destination
和 my.*
都会匹配地址 my.destination
。在这种情况下,代理首先应用 my
ö 下发现的配置,因为通配符表达式不具体于字面数。接下来,代理覆盖 my.destination
地址设置元素的配置,它覆盖与 my the 共享的任何配置
。例如,如果以下配置,与 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>
下表中的示例说明了如何使用通配符来匹配一组地址。
示例 | 描述 |
---|---|
|
|
|
匹配 |
|
匹配 |
|
匹配 |
4.2.2. 配置代理通配符语法
以下步骤演示了如何自定义用于通配符地址的语法。
流程
-
打开 &
lt;broker_instance_dir> /etc/broker.xml
配置文件。 在配置中添加 <
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
的值提供的字符代表“匹配 0 个或更多个序列”,并将替换默认的#
。在您的表达式末尾使用此字符。 single-word
-
作为
single-word
的值提供的字符代表“匹配一个词”,并将替换默认的*
。在您的表达式中的任何位置使用此字符。
4.3. 为点到点消息配置地址
点对点消息传递是制作者发送的消息只有一个消费者的常见场景。AMQP 和 JMS 消息制作者和消费者可以使用点对点消息传递队列,例如:为确保在点到点的方式中队列与一个接收消息的地址相关联,在您的代理配置中为给定的 address
项定义一个 anycast
路由类型。
当消息在一个使用 anycast
的地址上接收时,代理会找到与地址关联的队列,并将消息路由到它。然后,消费者可能会请求使用来自该队列的消息。如果多个使用者连接到同一队列,则消息会在消费者之间平均分发,只要消费者可以平等地处理它们。
下图显示了点对点消息的示例。
4.3.1. 配置基本点到点的消息
以下流程演示了如何为点到点消息配置带有单一队列的地址。
流程
-
打开 &
lt;broker_instance_dir> /etc/broker.xml
配置文件。 使用一个
address
所选的queue
项环绕一个anycast
配置项。确保address
和queue
元素的name
属性的值相同。例如:<configuration ...> <core ...> ... <address name="my.anycast.destination"> <anycast> <queue name="my.anycast.destination"/> </anycast> </address> </core> </configuration>
4.3.2. 为多个队列配置点到点的消息
您可以在使用 anycast
路由类型的地址上定义多个队列。代理会在所有相关队列中平均分发发送到 anycast
地址的消息。通过指定 完全限定域名 (FQQN),您可以将客户端连接到特定的队列。如果多个消费者连接到同一队列,代理会在消费者间平均分发消息。
下图显示了使用两个队列的点对点消息传递的示例。
以下流程演示了如何为具有多个队列的地址配置点到点消息。
流程
-
打开 &
lt;broker_instance_dir> /etc/broker.xml
配置文件。 使用在
address
项中的queue
项环绕一个anycast
配置项。例如:<configuration ...> <core ...> ... <address name="my.anycast.destination"> <anycast> <queue name="q1"/> <queue name="q2"/> </anycast> </address> </core> </configuration>
如果您在集群中的多个代理间显示上述配置,集群就可以以不透明到生产者和消费者的方式进行负载平衡点到点消息。具体的行为取决于如何为集群配置消息负载平衡策略。
其他资源
有关以下内容的更多信息:
- 指定完全限定域名,请参阅 第 4.9 节 “指定完全限定队列名称”。
- 如何为代理集群配置消息负载均衡,请参阅 第 14.1.1 节 “代理集群如何平衡消息负载”。
4.4. 为发布订阅消息传递配置地址
在发布订阅场景中,消息会发送到订阅地址的每个消费者。JMS 主题和 MQTT 订阅是发布订阅消息传递的两个示例。为确保以发布订阅的方式与地址接收消息关联的队列,您可以在代理配置中为给定 address
元素定义一个 multicast
路由类型。
当在带有 multicast
路由类型的地址上收到消息时,代理会将消息的副本路由到与地址关联的每个队列。为减少复制开销,每个队列仅发送对消息 的引用,而不是完整副本。
下图显示了发布订阅消息传递的示例。
以下流程演示了如何为发布订阅消息配置地址。
流程
-
打开 &
lt;broker_instance_dir> /etc/broker.xml
配置文件。 向地址添加一个空的
multicast
配置元素。<configuration ...> <core ...> ... <address name="my.multicast.destination"> <multicast/> </address> </core> </configuration>
(可选)将一个或多个
queue
项添加到地址中,并在它们间环绕multicas
项。通常不需要这一步,因为代理会自动为客户端请求的每个订阅创建一个队列。<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. 为点到点和发布订阅消息传递配置地址
您还可以使用点对点 和发布 订阅语义配置地址。
通常不建议将地址配置为同时使用点到点和发布订阅模式。但是,如果需要,它可能会有用。例如,一个名为 orders
的 JMS 队列,以及名为 order
的 JMS 主题。不同的路由类型使地址似乎与客户端连接不同。在这种情况下,由 JMS 队列生成者发送的消息使用 anycast
路由类型。JMS 主题制作者发送的消息使用 multicast
路由类型。当 JMS 主题消费者连接到代理时,它将附加到自己的订阅队列。但是,JMS 队列消费者附加到 anycast
队列。
下图显示了组合使用的时间对点和发布订阅消息传递的示例。
以下流程演示了如何为点到点和发布订阅消息配置地址。
这种情境的行为取决于所使用的协议。对于 JMS,主题和队列制作者与消费者之间存在明显的区别,这使得逻辑变得简单。AMQP 等其他协议不会实现这种差异。通过 AMQP 发送的消息以 anycast
和 multicast
路由,消费者默认为 anycast
。更多信息请参阅 第 3 章 在网络连接中配置消息传递协议。
流程
-
打开 &
lt;broker_instance_dir> /etc/broker.xml
配置文件。 使用在
address
项中的queue
项环绕一个anycast
配置项。例如:<configuration ...> <core ...> ... <address name="orders"> <anycast> <queue name="orders"/> </anycast> </address> </core> </configuration>
向地址添加一个空的
multicast
配置元素。<configuration ...> <core ...> ... <address name="orders"> <anycast> <queue name="orders"/> </anycast> <multicast/> </address> </core> </configuration>
注意通常,代理根据需要创建订阅队列,因此不需要列出
multicast
元素中的特定 queue 元素。
4.6. 在接受器配置中添加路由类型
通常,如果一个消息由同时使用 anycast
和 multicast
的地址接收,一个 anycast
队列会接收消息,以及所有 multicast
队列。但是,当连接到地址时,客户端可以指定一个特定的前缀,以指定是否使用 anycast
或 multicast
连接。前缀是自定义值,使用代理配置中 acceptor 的 URL 中的 anycastPrefix
和 multicastPrefix
参数指定。
以下流程演示了如何为给定接受器配置前缀。
流程
-
打开 &
lt;broker_instance_dir> /etc/broker.xml
配置文件。 对于给定的接收器,若要配置
anycast
前缀,将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>
根据前面的配置,acceptor 被配置为使用
anycast://
(anycast
前缀)。如果客户端需要将信息只发送到anycast
队列,客户端可以指定anycast://<my.destination>/
。对于给定的接受者,若要配置
多播
前缀,请在配置的 URL 中添加multicastPrefix
。设置自定义值。例如:<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>
根据前面的配置,接受器被配置为使用
multicast://
作为multicast
前缀。如果客户端只需要发送到多播队列的消息,客户端代码可以指定multicast://<my.destination
>
;/。
4.7. 配置订阅队列
在大多数情况下,不需要手动创建订阅队列,因为当客户端第一次请求订阅地址时,协议管理器会自动创建订阅队列。请参阅 第 4.8.3 节 “协议管理器和地址” 了解更多信息。对于 durable 订阅,生成的队列名称通常是客户端 ID 和地址的连接。
以下小节演示了如何根据需要手动创建订阅队列。
4.7.1. 配置持久订阅队列
当队列配置为可激活的订阅时,代理会为任何不活跃订阅者保存消息,并在用户重新连接时将它们传送到订阅者。因此,客户端保证在订阅队列后接收发送到队列的每个消息。
流程
-
打开 &
lt;broker_instance_dir> /etc/broker.xml
配置文件。 将
durable
配置元素添加到所选队列中。设置true
值。<configuration ...> <core ...> ... <address name="my.durable.address"> <multicast> <queue name="q1"> <durable>true</durable> </queue> </multicast> </address> </core> </configuration>
注意由于队列默认为 durable,因此包括
durable
元素并将值设为true
并不是创建持久队列的严格要求。但是,显式包含元素可让您稍后将队列的行为改为不可写入的(如果需要)。
4.7.3. 配置不可激活的订阅队列
不可强化的订阅通常由相关的协议管理器管理,后者创建和删除临时队列。
但是,如果要手动创建行为类似于不可配置订阅队列的队列,您可以在队列中使用 purge-on-no-consumers
属性。当 purge-on-no-consumers
设为 true
时,队列不会开始接收消息,直到消费者连接为止。另外,当最后一个消费者与队列断开连接时,队列将被清除(即,其消息会被删除)。在新的消费者连接到队列前,队列不会接收任何进一步的消息。
流程
-
打开 &
lt;broker_instance_dir> /etc/broker.xml
配置文件。 将
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 变为… | 添加此配置… |
---|---|
当客户端向或尝试使用映射到不存在的地址的队列的消息时,创建地址。 |
|
当客户端向队列发送消息或尝试使用队列的消息时,创建队列。 |
|
当它不再有任何队列时,删除自动创建的地址。 |
|
当队列有 0 个消费者和 0 消息时,删除自动创建的队列。 |
|
如果客户端没有指定,使用一个特定的路由类型。 |
|
4.8.2. 配置自动创建和删除地址和队列
以下流程演示了如何配置自动创建和删除地址和队列。
流程
-
打开 &
lt;broker_instance_dir> /etc/broker.xml
配置文件。 配置用于
自动创建和删除的地址设置
。以下示例使用上表中提到的所有配置元素。<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.
rhcs 匹配的任何地址或队列。 auto-create-addresses
- 当客户端请求连接到尚不存在的地址时,代理会创建该地址。
auto-delete-addresses
- 当自动创建的地址不再关联任何队列时,会删除自动创建的地址。
auto-create-queues
- 当客户端请求连接到尚不存在的队列时,代理会创建队列。
auto-delete-queues
- 当不再有任何消费者或消息时,自动创建的队列会被删除。
default-address-routing-type
-
如果客户端在连接时没有指定路由类型,代理会在向地址发送消息时使用
ANYCAST
。默认值为MULTICAST
。
其他资源
有关以下内容的更多信息:
- 配置地址时可以使用的通配符语法,请参阅 第 4.2 节 “将地址设置应用到一组地址”。
- 路由类型,请参阅 第 4.1 节 “地址、队列和路由类型”。
4.8.3. 协议管理器和地址
名为 协议管理器 的组件将特定于协议的概念映射到 AMQ Broker 地址模型中使用的概念;队列和路由类型。在某些情况下,协议管理器可能会在代理上自动创建队列。
例如,当客户端发送一个带有地址 /house/ room1/lights
和 /house/ room2/lights
的 MQTT 订阅数据包时,MQTT 协议管理器理解两个地址需要 多播
语义。因此,协议管理器首先会查找为这两个地址 启用多播
。如果没有,它将尝试动态创建它们。如果成功,协议管理器会为客户端请求的每个订阅创建特殊的订阅队列。
每个协议的行为稍有不同。下表描述了在请求对各种类型的 队列
订阅帧时通常会发生的情况。
如果队列是此类型… | 协议管理器的典型操作是 … |
---|---|
可配置订阅队列 |
查找适当的地址并确保启用了 特殊名称允许协议管理器快速识别客户端订阅队列,以便客户端稍后断开连接和重新连接。 当客户端取消订阅队列时,会删除队列。 |
临时订阅队列 |
查找适当的地址并确保启用了 当客户端断开队列被删除时。 |
点到点队列 |
查找适当的地址,并确保启用了 如果队列自动创建,则当没有消费者且没有消息后,它会被自动删除。 |
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. 配置分片队列
在队列间处理消息的通用模式,其中只需要部分排序是使用 队列分片。这意味着您可以定义一个作为单一逻辑队列的 anycast
地址,但它由多个底层物理队列支持。
流程
-
打开 &
lt;broker_instance_dir> /etc/broker.xml
配置文件。 添加
address
元素并设置name
属性。例如:<configuration ...> <core ...> ... <addresses> <address name="my.sharded.address"></address> </addresses> </core> </configuration>
添加
anycast
路由类型,并包含所需的分片队列数量。在以下示例中,队列q1
,q2
, 和q3
添加为anycast
的目的地。<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
和 q3
之间均匀分布。当使用完全限定域名(FQQN)时,客户端可以直接连接到特定的物理队列,并仅接收发送到该特定队列的消息。
要将特定消息绑定到特定的队列,客户端可以为每个消息指定一个消息组。代理将消息链接到同一队列,一个消费者都处理它们。
其他资源
有关以下内容的更多信息:
- 完全限定队列名称,请参阅 第 4.9 节 “指定完全限定队列名称”
- 消息分组,请参阅 AMQ Core Protocol JMS 文档中的使用消息组。https://access.redhat.com/documentation/zh-cn/red_hat_amq_clients/2023.q4/html-single/using_the_amq_core_protocol_jms_client/index.html#using_message_groups
4.11. 配置最后的值队列
最后的值 queue 是队列类型,当将具有相同最后一个值键值的更新消息放在队列中时,丢弃队列中的消息。通过此行为,最后一个值队列只保留同一键消息的最后一个值。
最后的值队列的一个简单用例是监控库存价格,其中只有特定库存的最新值是值得关注的。
如果消息没有配置的最后一个值键发送到最后一个值队列,代理会将这个消息作为 "normal" 消息处理。当带有配置的最后值键的新消息到达时,此类消息不会从队列清除。
您可以单独配置最后的值队列,或针对与一组地址关联的所有队列。
以下流程演示了如何以这些方式配置最后一个值队列。
4.11.1. 单独配置最后的值队列
以下流程显示单独配置最后一个值队列。
-
打开 &
lt;broker_instance_dir> /etc/broker.xml
配置文件。 对于给定队列,添加
last-value-key
键并指定自定义值。例如:<address name="my.address"> <multicast> <queue name="prices1" last-value-key="stock_ticker"/> </multicast> </address>
或者,您可以配置使用默认值最后一个值键键
_AMQ_LVQ_NAME
的最后值队列。为此,请将last-value
键添加到给定队列中。将值设为true
。例如:<address name="my.address"> <multicast> <queue name="prices1" last-value="true"/> </multicast> </address>
4.11.2. 为地址配置最后的值队列
以下流程演示了如何为地址 或一组 地址配置最后一个值队列。
-
打开 &
lt;broker_instance_dir> /etc/broker.xml
配置文件。 在
address-setting
元素中,对于匹配的地址,添加default-last-value-key
。指定自定义值。例如:<address-setting match="lastValue"> <default-last-value-key>stock_ticker</default-last-value-key> </address-setting>
根据前面的配置,与
lastValue
地址关联的所有队列都使用 final_ticker
的最后一个值键。默认情况下,不会设置default-last-value-key
的值。要为 一组 地址配置最后的值队列,您可以指定一个地址通配符。例如:
<address-setting match="lastValue.*"> <default-last-value-key>stock_ticker</default-last-value-key> </address-setting>
或者,您可以配置与一个地址 或一组 地址关联的所有队列,以使用默认的最后一个值键名称
_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.2 节 “将地址设置应用到一组地址”。
4.11.3. 最后一个值队列行为示例
本例演示了最后一个值队列的行为。
在 broker.xml
配置文件中,假设您添加了类似如下的配置:
<address name="my.address"> <multicast> <queue name="prices1" last-value-key="stock_ticker"/> </multicast> </address>
前面的配置会创建一个名为 prices1
的队列,其最后一个值为 leader _ticker
。
现在,假设客户端发送两个消息。每个信息对于属性 stock_ticker
有相同的 ATN
值。每个消息都有一个不同的属性,名为 roll _price
。每个消息都发送到同一队列 prices1
。
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
最后值键(这里是 ATN
)具有相同值的信息到达 prices1 queue
时,最有最后的信息会保留在队列中,第一个信息会被删除。在命令行中,您可以输入以下行来验证此行为:
TextMessage messageReceived = (TextMessage)messageConsumer.receive(5000); System.out.format("Received message: %s\n", messageReceived.getText());
在本例中,您看到的输出是第二个消息,因为两个消息都对最后一个值键和第二条消息都使用相同的值,第二个消息在队列中收到。
4.11.4. 为最后一个值队列强制使用非破坏性消耗
当消费者连接到队列时,通常的行为是发送到该消费者的消息仅由消费者获取。当消费者确认收到消息时,代理会从队列中删除消息。
作为正常消耗的替代选择,您可以将队列配置为强制实施 非破坏性 消耗。在这种情况下,当队列向消费者发送消息时,其他消费者仍然可以接收消息。此外,即使消费者使用了它,该消息仍然保留在队列中。当您强制实施这种非破坏性消耗行为时,消费者称为队列 浏览器。
强制非破坏性消耗是最后一个值队列的有用配置,因为它确保队列始终包含特定最后一个值键的最新值。
以下流程演示了如何为最后一个值队列强制使用非破坏性。
先决条件
您已单独配置了最后值队列,或针对与地址 或一组 地址关联的所有队列。如需更多信息,请参阅:
流程
-
打开 &
lt;broker_instance_dir> /etc/broker.xml
配置文件。 如果您之前单独将队列配置为最后一个值队列,请添加
非破坏性
键。将值设为true
。例如:<address name="my.address"> <multicast> <queue name="orders1" last-value-key="stock_ticker" non-destructive="true" /> </multicast> </address>
如果您之前为最后一个值队列配置了地址 或一组 地址,请添加
default-non-destructive
键。将值设为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. 配置消息到期
以下流程演示了如何配置消息到期。
流程
-
打开 &
lt;broker_instance_dir> /etc/broker.xml
配置文件。 在
core
元素中,设置message-expiry-scan-period
,以指定代理扫描已过期消息的频率。<configuration ...> <core ...> ... <message-expiry-scan-period>1000</message-expiry-scan-period> ...
根据前面的配置,代理每 1000 毫秒扫描队列以获取已过期的消息。
在用于匹配地址 或一组 地址的
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,
这意味着它们不会过期。对于时间大于默认值的消息,expiry-delay
无效。例如,假设您在地址上将
expiry-delay
设置为10
,如上例所示。如果具有默认过期时间为0
的消息在此地址到达队列,那么代理会将消息的过期时间从0
改为10
。但是,如果另一个使用过期时间为20
的时间的消息到达,则其过期时间不会改变。如果将 expiry-delay 设为-1,
则禁用此功能。默认情况下,expiry-delay
设置为-1
。
另外,您还可以指定最小和最大到期延迟值,而不是为
expiry-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
值之间带有过期的消息,代理不会更改消息的过期时间。 -
如果您为
expiry-delay
指定一个值(即与默认值-1
不同的值),这将覆盖您为min-expiry-delay
和max-expiry-delay
指定的值。 -
min-expiry-delay
和max-expiry-delay
的默认值为-1
(即禁用)。
-
对于默认过期时间为
在
配置文件的
address 元素中,配置之前为expiry-address
指定的地址。在此地址上定义一个队列。例如:<addresses> ... <address name="ExpiryAddress"> <anycast> <queue name="ExpiryQueue"/> </anycast> </address> ... </addresses>
前面的示例配置将到期队列
ExpiryQueue
与到期地址ExpiryAddress
关联。
4.12.2. 自动创建过期资源
常见用例是根据其原始地址隔离过期的消息。例如,您可以选择将过期的消息从名为来自名为 stocks
的地址路由到一个名为 EXP.stocks
的过期队列。同样,您可以将过期的消息从名为 order
的地址路由到名为 EXP.orders
的过期队列。
这种类型的路由模式可让您轻松跟踪、检查和管理已过期的消息。但是,这样的模式很难在使用主要自动创建的地址和队列的环境中实现。在这种环境中,管理员不需要手动创建地址和队列来保存过期消息所需的额外工作。
作为临时解决方案,您可以将代理配置为自动创建资源(即地址和队列)来处理给定地址 或一组 地址的过期消息。以下流程显示了一个示例。
先决条件
- 您已为给定地址 或一组 地址配置了到期地址。更多信息请参阅 第 4.12.1 节 “配置消息到期”。
流程
-
打开 &
lt;broker_instance_dir> /etc/broker.xml
配置文件。 找到您之前添加到配置文件的 &
lt;address-setting
> 元素,以便为匹配的地址 或一组 地址定义到期地址。例如:<configuration ...> <core ...> ... <address-settings> ... <address-setting match="stocks"> ... <expiry-address>ExpiryAddress</expiry-address> ... </address-setting> ... <address-settings> <configuration ...>
在 &
lt;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>
; 元素来定义到期地址和关联的过期队列。自动创建的 <address> 元素的
name 值与为<expiry-address>
指定的值匹配。自动创建的过期队列有
multicast
路由类型。默认情况下,代理命名到期队列,以匹配最初发送消息的地址,例如,库存
。代理还定义了使用
_AMQ_ORIG_ADDRESS
属性的过期队列的过滤器。此过滤器可确保到期队列仅接收发送到相应原始地址的消息。expiry-queue-prefix
代理应用到自动创建的过期队列的名称的前缀。默认值为
EXP。
当您定义前缀值或保留默认值时,到期队列的名称是前缀和原始地址的串联,如
EXP.stocks
。expiry-queue-suffix
- 代理应用到自动创建的过期队列名称的后缀。未定义默认值(即代理不会应用后缀)。
您可以自行使用队列名称(例如,使用 AMQ Broker Core Protocol JMS 客户端)或使用完全限定队列名称(例如,使用另一个 JMS 客户端时)直接访问到期队列。
由于自动创建到期地址和队列,因此与删除自动创建的地址和队列的任何地址设置也适用于这些到期资源。
其他资源
- 有关配置自动删除自动创建的地址和队列的地址设置的更多信息,请参阅 第 4.8.2 节 “配置自动创建和删除地址和队列”。
4.13. 将未发送的消息移到死信地址
如果向客户端发送消息失败,您可能不希望代理不断尝试发送消息。为防止无限的尝试,您可以定义一个死信地址,以及一个或多个相关的死信队列。在指定的交付尝试后,代理会从其原始队列中删除未发送的消息,并将消息发送到配置的死信地址。系统管理员稍后可以从死信队列中消耗未发送的消息来检查消息。
如果您没有为给定队列配置死信地址,代理会在指定数量尝试后从队列永久删除未发送的消息。
取消发送从死信队列中消耗的消息具有以下属性:
_AMQ_ORIG_ADDRESS
- 指定消息的原始地址的字符串属性
_AMQ_ORIG_QUEUE
- 指定消息原始队列的字符串属性
4.13.1. 配置死信地址
以下流程演示了如何配置死信地址和相关死信队列。
流程
-
打开 &
lt;broker_instance_dir> /etc/broker.xml
配置文件。 在与
队列名称匹配的 <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 ...>
match
-
代理应用此
address-setting
部分中的配置的地址。您可以为 <address-setting> 元素的
match
属性指定通配符表达式。如果您希望将<address-setting>
项中配置的死信设置与一组地址相匹配,可以使用通配符表达式。 dead-letter-address
- 死信地址的名称。在本例中,代理将未发送的消息从队列 exampleQueue 移到死信地址 DLA。
max-delivery-attempts
-
在将未发送的消息移到配置的死信地址前,代理进行的最大交付尝试数量。在本例中,代理会在 3 次失败发送尝试后将未发送的消息移到死信地址。默认值为
10
。如果您希望代理进行无限数量的重新发送尝试,请指定-1
的值。
在
addresses
部分中,为死信地址 DLA 添加address
元素。要将死信队列与死信地址关联,请为队列
指定名称值。例如:<configuration ...> <core ...> ... <addresses> <address name="DLA"> <anycast> <queue name="DLQ" /> </anycast> </address> ... </addresses> </core> </configuration>
在前面的配置中,您要将名为 DLQ 的死信队列与死信地址 DLA 关联。
其他资源
- 有关在地址设置中使用通配符的详情,请参考 第 4.2 节 “将地址设置应用到一组地址”。
4.13.2. 自动创建死信队列
常见用例是根据其原始地址隔离未发送的消息。例如,您可以选择将来自 stocks
的未被成功发送的消息路由到一个名为 DLA.stocks
的队列,它有一个相关的名为 DLQ.stocks
的死信队列。同样,您可以将未发送的消息从名为 orders
的地址路由到一个名为 DLA.orders
的死信地址。
这种类型的路由模式可让您轻松跟踪、检查和管理未发送的消息。但是,这样的模式很难在使用主要自动创建的地址和队列的环境中实现。这可能不希望手动创建地址和队列来存放未发送的消息所需的额外工作。
作为临时解决方案,您可以将代理配置为自动创建地址和队列来处理未发送的消息,如下所示。
先决条件
- 您已为队列或一组队列配置了死信地址。更多信息请参阅 第 4.13.1 节 “配置死信地址”。
流程
-
打开 &
lt;broker_instance_dir> /etc/broker.xml
配置文件。 找到您之前添加的 <
;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
> 元素中,添加指示代理自动创建死信资源(即地址和队列)的配置项目以及如何命名这些资源。例如:<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
> 元素中定义的死信队列具有multicast
路由类型。默认情况下,代理命名死信队列以匹配未发送消息的原始地址,例如库存
。代理还定义了使用
_AMQ_ORIG_ADDRESS
属性的死信队列的过滤器。此过滤器可确保死信队列仅接收发送到相应原始地址的消息。dead-letter-queue-prefix
代理应用到自动创建的死信队列的名称的前缀。默认值为
DLQ。
当您定义前缀值或保留默认值时,死信队列的名称是前缀和原始地址的串联,如
DLQ.stocks
。dead-letter-queue-suffix
- 代理应用到自动创建的死信队列的后缀。未定义默认值(即代理不会应用后缀)。
4.14. 过期或未发送 AMQP 消息的注解和属性
在代理将过期或未发送的 AMQP 消息移到您配置的过期或死信队列前,代理会将注解和属性应用到消息。客户端可以根据这些属性或注解创建过滤器,以从到期或死信队列中选择要使用的特定消息。
代理应用的属性是 内部 属性,这些属性不会向客户端公开以供常规使用,但 可以由 过滤器中的客户端指定。
下表显示了代理应用到过期或未发送的 AMQP 消息的注解和内部属性。
注解名称 | 内部属性名称 | 描述 |
---|---|---|
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 | 过期或未发送消息的原始地址名称。 |
其他资源
- 有关配置 AMQP 客户端以根据注解过滤 AMQP 消息的示例,请参考 第 13.3 节 “根据注释的属性过滤 AMQP 消息”。
4.15. 禁用队列
如果在代理配置中手动定义队列,则默认启用队列。
但是,在有些情况下您可能需要定义一个队列,以便客户端可以订阅它,但未就绪使用队列进行消息路由。或者,在有些情况下,您要停止消息流到队列,但仍保持客户端绑定到队列。在这些情况下,您可以禁用队列。
以下示例演示了如何禁用您在代理配置中定义的队列。
先决条件
- 您应该熟悉如何在代理配置中定义地址和相关队列。更多信息请参阅 第 4 章 配置地址和队列。
流程
-
打开 &
lt;broker_instance_dir> /etc/broker.xml
配置文件。 对于您之前定义的队列,添加
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,
它设定无限数量的消费者。
以下流程演示了如何对可以连接到队列的用户数量设置限制。
流程
-
打开 &
lt;broker_instance_dir> /etc/broker.xml
配置文件。 对于给定队列,添加
max-consumers
键并设置值。<configuration ...> <core ...> ... <addresses> <address name="my.address"> <anycast> <queue name="q3" max-consumers="20"/> </anycast> </address> </addresses> </core> </configuration>
根据前面的配置,只有 20 个使用者可以同时连接到队列
q3
。要创建独占消费者,请将
max-consumers
设置为1
。<configuration ...> <core ...> ... <address name="my.address"> <anycast> <queue name="q3" max-consumers="1"/> </anycast> </address> </core> </configuration>
要允许无限数量的消费者,请将
max-consumers
设置为-1
。<configuration ...> <core ...> ... <address name="my.address"> <anycast> <queue name="q3" max-consumers="-1"/> </anycast> </address> </core> </configuration>
4.17. 配置专用队列
专用队列是特殊的队列,可一次将所有消息路由到一个消费者。当您希望所有消息由同一消费者按顺序处理时,此配置很有用。如果队列有多个消费者,则只有一个消费者将接收消息。如果该使用者断开了与队列的连接,则会选择另一个消费者。
4.17.1. 单独配置专用队列
以下流程演示了如何将给定队列单独配置为 exclusive。
流程
-
打开 &
lt;broker_instance_dir> /etc/broker.xml
配置文件。 对于给定队列,添加
exclusive
键。将值设为true
。<configuration ...> <core ...> ... <address name="my.address"> <multicast> <queue name="orders1" exclusive="true"/> </multicast> </address> </core> </configuration>
4.17.2. 为地址配置专用队列
以下流程演示了如何配置地址 或一组 地址,以便所有关联的队列都是独占的。
-
打开 &
lt;broker_instance_dir> /etc/broker.xml
配置文件。 在
address-setting
元素中,对于匹配的地址,添加default-exclusive-queue
键。将值设为true
。<address-setting match="myAddress"> <default-exclusive-queue>true</default-exclusive-queue> </address-setting>
根据前面的配置,与
myAddress
地址关联的所有队列都是独占的。默认情况下,default-exclusive-queue
的值为false
。要为 一组 地址配置专用队列,您可以指定地址通配符。例如:
<address-setting match="myAddress.*"> <default-exclusive-queue>true</default-exclusive-queue> </address-setting>
其他资源
- 有关您可以在配置地址时使用的通配符语法的更多信息,请参阅 第 4.2 节 “将地址设置应用到一组地址”。
4.18. 将特定地址设置应用到临时队列
例如,在使用 JMS 时,代理通过将通用唯一标识符(UUID)分配为地址名称和队列名称来创建 临时队列。
默认的 <address-setting match="#">
会将配置的地址设置应用到所有队列,包括临时队列。如果您只想将特定的地址设置应用到临时队列,您可以选择指定一个 temporary-queue-namespace
,如下所述。然后,您可以指定与命名空间匹配的地址设置,代理会将这些设置应用到所有临时队列。
创建临时队列并且存在临时队列命名空间时,代理会将 temporary-queue-namespace
值和配置的分隔符(默认 .
)添加到地址名称。它用于引用匹配的地址设置。
流程
-
打开 &
lt;broker_instance_dir> /etc/broker.xml
配置文件。 添加
temporary-queue-namespace
值。例如:<temporary-queue-namespace>temp-example</temporary-queue-namespace>
添加一个
address-setting
元素,其match
值与临时队列命名空间对应。例如:<address-settings> <address-setting match="temp-example.#"> <enable-metrics>false</enable-metrics> </address-setting> </address-settings>
这个示例禁用代理创建的所有临时队列中的指标。
注意指定临时队列命名空间不会影响临时队列。例如,命名空间不会更改临时队列的名称。命名空间用于引用临时队列。
其他资源
- 有关在地址设置中使用通配符的详情,请参考 第 4.2 节 “将地址设置应用到一组地址”。
4.19. 配置环队列
通常,AMQ Broker 中的队列使用第一个、第一个(FIFO)语义。这意味着代理将消息添加到队列的末尾,并将它们从头中删除。环环队列是一种特殊的队列类型,其中包含指定的、固定消息的数量。当新消息到达但队列包含指定数量的消息时,代理通过删除队列头的消息来维护固定队列大小。
例如,假设配置了大小为 3
的环队列,以及按顺序发送消息 A
、B
、C
和 D
的制作者。消息 C
到达队列后,队列中的消息数量就达到配置的环大小。此时,消息 A
位于队列的头,而消息 C
则位于尾部。当消息 D
到达队列时,代理会将消息添加到队列的尾部。为了保持固定队列大小,代理会在队列头删除消息(即消息 A
)。消息 B
现在位于队列的头。
4.19.1. 配置环队列
以下流程演示了如何配置环队列。
流程
-
打开 &
lt;broker_instance_dir> /etc/broker.xml
配置文件。 要在未设置显式环大小的匹配地址上定义默认环大小,请在
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
(即没有大小限制)。要在特定队列上定义环环大小,请将
ring-size
密钥添加到queue
元素中。指定一个值。例如:<addresses> <address name="myRing"> <anycast> <queue name="myRing" ring-size="5" /> </anycast> </address> </addresses>
您可以在代理运行时更新 ring-size
的值。代理会动态应用更新。如果新 ring-size
值低于先前值,代理不会立即从队列头删除消息来强制实施新大小。发送到队列的新消息仍会强制删除旧消息,但队列不会达到新的、缩小的大小,直到客户端通过正常消耗消息为止。
4.19.2. 对环队列进行故障排除
这部分论述了环队列的行为与其配置不同的情况。
发送消息和回滚
当消息发送到消费者时,消息处于"in-between"状态,其中消息不再在队列中,但还没有确认。在被消费者确认之前,消息会一直处于 in-delivery 状态。处于 in-delivery 状态的消息无法从环队列中删除。
由于代理无法删除 in-delivery 消息,因此客户端可以将比环队列所允许的更多消息发送到环队列。例如,请考虑这种情况:
-
生产者向配置了
ring-size="3"
的环队列发送三个消息。 所有消息都会立即分配给消费者。
At this point,
messageCount
=3
anddeliveringCount
=3
.生产者向队列发送另一个消息。然后,消息会被分配给消费者。
现在,
messageCount
=4
和deliveryCount
=4
。消息数为4
大于配置的环大小3
。但是,代理被认为是允许这种情况,因为它无法从队列中删除消息。现在,假设消费者在不确认任何消息的情况下关闭。
在这种情况下,四个 in-delivery,未确认的消息将取消回代理,并根据它们使用的相反顺序添加到队列的标头中。此操作会使队列置于其配置的环大小上。由于环队列首选通过头的消息在队列的尾部消息,因此队列丢弃生成者发送的第一个消息,因为这是最后一个消息,将添加回队列头。事务或核心会话回滚的方式相同。
如果您直接使用核心客户端,或使用 AMQ Core Protocol JMS 客户端,您可以通过减少 consumerWindowSize
参数的值(默认为 1024 * 1024 字节)来最小化传输的消息数量。
调度的消息
当调度的消息发送到队列时,消息不会立即添加到队列的尾部,如普通消息。相反,代理将调度的消息保存在中间缓冲区中,并根据消息的详细信息将消息发送到队列头。但是,调度的消息仍然反映在队列的消息数中。与 in-delivery 消息一样,此行为可能会使其显示代理没有强制实施环队列大小。例如,请考虑这种情况:
在 12:00 时,生产者将消息
A
发送到配置了ring-size="3"
的环队列。该消息调度到 12:05。此时,
messageCount
=1
和scheduledCount
=1
。在 12:01 中,生成者将消息
B
发送到同一环队列。现在,
messageCount
=2
和scheduledCount
=1
。在 12:02 中,生成者将消息
C
发送到同一环队列。现在,
messageCount
=3
和scheduledCount
=1
。在 12:03 时,生成者将消息
D
发送到同一环队列。现在,
messageCount
=4
和scheduledCount
=1
。队列的消息数现在是
4
,一个大于 配置的环大小为3
。但是,调度的消息还没有在队列中(即,它位于代理中,并计划放置到队列中)。在 12:05 调度的发送时,代理会将消息放置在队列的标头中。但是,由于环队列已达到其配置的大小,因此调度的消息A
会立即被删除。
页面的信息
与发送中调度的消息和消息类似,页的消息不会计算到代理强制的环队列大小,因为消息实际上是在地址级别进行分页,而不是队列级别。页面的消息不是技术在队列中,尽管它反映在队列的 messageCount
值中。
建议您不要将分页用于带环队列的地址。相反,请确保整个地址可以容纳内存。或者,将 address-full-policy
参数配置为 DROP
, BLOCK
或 FAIL
。
其他资源
- 当您配置重新引入地址时,代理会创建环队列的内部实例。如需更多信息,请参阅 第 4.20 节 “配置被动地址”。
4.20. 配置被动地址
通过将地址配置为 retroactive,您可以保留发送到该地址的消息,包括在没有队列仍绑定到该地址时。当队列稍后创建并绑定到地址时,代理会重新将消息分发到这些队列。如果地址 没有配置为 retroactive,且还没有与其绑定队列,代理会丢弃发送到该地址的消息。
当您配置重新引入地址时,代理会创建一个内部实例,称为 环队列。环环队列是一种特殊的队列类型,其中包含指定的、固定消息的数量。队列达到指定大小后,到达队列的下一个消息会强制从队列中强制最旧的消息。当您配置重新主动地址时,您间接指定内部环队列的大小。默认情况下,内部队列使用 multicast
路由类型。
被动地址使用的内部环队列通过管理 API 公开。您可以检查指标并执行其他通用管理操作,如空队列。环队列还贡献地址的总内存用量,这会影响消息分页等行为。
以下流程演示了如何将地址配置为 retroactive。
流程
-
打开 &
lt;broker_instance_dir> /etc/broker.xml
配置文件。 为
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
参数的环队列不会自动从队列中删除消息,以实现新的ring-size
值。这个行为是防止意外消息丢失的情况。在这种情况下,您需要使用管理 API 来手动减少环队列中的消息数量。
其他资源
- 有关环队列的详情,请参考 第 4.19 节 “配置环队列”。
4.21. 为内部管理的地址和队列禁用公告消息
默认情况下,当 OpenWire 客户端连接到代理时,AMQ Broker 会创建有关地址和队列的公告信息。公告消息发送到代理创建的内部管理的地址。这些地址会出现在与用户部署的地址和队列相同的显示中的 AMQ 管理控制台中。虽然它们提供有用的信息,但公告的信息可能会在代理管理大量目的地时造成不必要的后果。例如,消息可能会增加内存用量或激增的连接资源。另外,当尝试显示为发送公告消息创建的所有地址时,AMQ 管理控制台可能会变得明确。要避免这种情况,您可以使用以下参数配置代理上公告消息的行为。
supportAdvisory
-
将这个选项设置为
true
以启用创建公告消息,或设置为false
来禁用它们。默认值为true
。 suppressInternalManagementObjects
-
将这个选项设置为
true
,将公告消息公开给管理服务,如 JMX registry 和 AMQ 管理控制台,或设置为false
以不公开它们。默认值为true
。
以下流程演示了如何在代理中禁用公告信息。
流程
-
打开 &
lt;broker_instance_dir> /etc/broker.xml
配置文件。 对于 OpenWire 连接器,将
supportAdvisory
和suppressInternalManagementObjects
参数添加到配置的 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 中,两个主要的联邦选项是 address federation 和 queue federation。这些选项在后续小节中进行了描述。
代理可以包含联邦 和本地 组件的配置。也就是说,如果您在代理中配置联邦,则不需要协调该代理上的所有内容。
4.22.1. 关于地址联邦
地址联邦类似于连接的代理之间的完整多播分布模式。例如,发送到 BrokerA
上地址的每个消息都会被传送到该代理上的每个队列。另外,每个消息都传送到 BrokerB
,所有附加队列都在其中发送。
地址联邦动态将代理链接到远程代理中的地址。例如,如果本地代理希望从远程代理上的地址获取消息,则会在远程地址上自动创建队列。然后,远程代理上的消息会被消耗给此队列。最后,消息被复制到本地代理的对应地址,就像最初被直接发布到本地地址一样。
不需要重新配置远程代理来允许联邦在其上创建地址。但是,本地 代理需要被授予远程地址的权限。
4.22.2. 地址联邦的常见拓扑
下面介绍了一些使用地址联邦的拓扑。
- 对称拓扑
在对称拓扑中,生成者和消费者连接到每个代理。队列及其消费者可以接收由任一制作者发布的消息。下方显示了一个对称拓扑示例。
图 4.1. 对称拓扑中的地址联邦
为对称拓扑配置地址联邦时,必须将地址策略的
max-hops
属性的值设置为1
。这样可确保消息 仅复制一次,避免了 cyclic 复制。如果此属性设置为较大的值,则消费者会收到同一消息的多个副本。- 完整网格拓扑
完整的网格拓扑与对称设置类似。三个或更多代理相互对称,创建一个完整的网格。在这个设置中,生产者和消费者连接到每个代理。队列及其消费者可以接收任何制作者发布的消息。此拓扑的示例如下所示。
图 4.2. 完整网格拓扑中的地址联邦
与对称设置一样,当为完整网格拓扑配置地址联邦时,必须将地址策略的
max-hops
属性的值设置为1
。这样可确保消息 仅复制一次,避免了 cyclic 复制。- 环环拓扑
在代理环中,每个联邦地址都是上游的。此拓扑的示例如下所示。
图 4.3. 环拓扑中的地址联邦
当您为环拓扑配置联邦时,为了避免 cyclic 复制,必须将地址策略的
max-hops
属性设置为n-1
,其中 n 是环中的节点数。例如,在上面显示的环拓扑中,max-hops
的值设置为5
。这样可确保环中的每个地址都 完全看到一次 消息。环环拓扑的优点是,根据您需要进行的物理连接数量,设置更便宜。但是,这种类型的拓扑缺陷是,如果单个代理失败,整个环会失败。
- fan-out 拓扑
在 fan-out 拓扑中,单个 master 地址被联邦地址的树链接到。发布到 master 地址的任何消息都可以被连接到树中任何代理的消费者接收。树可以配置为任何深度。树也可以扩展,而无需在树中重新配置现有代理。此拓扑的示例如下所示。
图 4.4. fan-out 拓扑中的地址联邦
当您为 fan-out 拓扑配置联邦时,请确保将地址策略的
max-hops
属性设置为n-1
,其中 n 是树中的级别数。例如,在上面显示的 fan-out 拓扑中,max-hops
的值设置为2
。这样可确保树中的每个地址都 完全看到一次 消息。
4.22.3. 支持在地址联邦配置中有 disrt 绑定
在配置地址联邦时,您可以在地址策略配置中添加对 disrt 绑定的支持。添加此支持可让联邦响应在远程代理上为给定地址创建联邦消费者。
例如,假设地址策略中包含了一个名为 test.federation.source
的地址,另一个名为 test.federation.target
的地址。通常,当一个队列在 test.federation.target
上创建,不会导致创建联邦消费者,因为地址不是地址策略的一部分。但是,如果您创建了一个离散的绑定,以便 test.federation.source
是源地址,test.federation.target
是转发地址,那么会在转发地址中创建具有危险的消费者。源地址仍然必须使用 multicast
路由类型,但目标地址可以使用 multicast
或 anycast
。
示例用例是将 JMS 主题(多播地址
)重定向到 JMS 队列(anycast
地址)。这启用了在主题上对不支持 JMS 2.0 和共享订阅的传统消费者进行负载平衡。
4.22.4. 为代理配置联邦
以下章节中的示例演示了如何配置 独立 本地和远程代理间的地址和队列联邦。对于独立代理、联邦配置的名称以及任何地址和队列策略的名称,在本地和远程代理之间必须是唯一的。
但是,如果您要在集群中为代理配置联邦,则需要额外的要求。对于集群代理,联邦配置的名称以及该配置中任何地址和队列策略的名称 对于该集群中的每个代理都必须相同。
确保同一集群中的代理使用相同的联邦配置和地址和队列策略名称,避免消息重复。例如,如果同一集群中的代理 有不同的 联邦配置名称,这可能会导致为同一地址创建多个命名的转发队列,从而导致下游用户的消息重复。相反,如果同一集群中的代理 使用相同的 联邦配置名称,这基本上会创建复制到下游消费者的复制的集群转发队列。这可避免消息重复。
4.22.5. 配置上游地址联邦
以下示例演示了如何配置独立代理间的上游地址联邦。在本例中,您可以将一个本地的联邦(即 下游)代理配置为一些远程(即 上游)代理。
先决条件
- 以下示例演示了如何配置独立代理间的地址联邦。但是,您还应熟悉为代理配置联邦 的要求。更多信息请参阅 第 4.22.4 节 “为代理配置联邦”。
流程
-
打开 &
lt;broker_instance_dir> /etc/broker.xml
配置文件。 添加新的 <
federations>
元素,其中包含 <federation>
元素。例如:<federations> <federation name="eu-north-1" user="federation_username" password="32a10275cf4ab4e9"> </federation> </federations>
name
- 联邦配置的名称。在本例中,名称对应于本地代理的名称。
user
- 用于连接到上游代理的共享用户名。
password
- 用于连接到上游代理的共享密码。
注意如果远程代理的用户和密码凭证不同,您可以在将这些代理添加到配置中时单独为这些代理指定凭证。此流程稍后将进行描述。
在
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
可让 disrt 绑定根据需要侦听。如果存在与地址策略包含的地址匹配的地址绑定,则任何与 divert 转发地址匹配的队列绑定都会满足需求。默认值为false
。 max-hops
- 消息可以在联邦期间进行的最大跃点数。特定的拓扑需要此属性的特定值。要了解更多有关这些要求的信息,请参阅 第 4.22.2 节 “地址联邦的常见拓扑”。
transformer-ref
- 转换程序配置的名称。如果要在联邦消息传输过程中转换消息,您可以添加转换器配置。此流程稍后会描述转换器配置。
在 <
;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
属性的值指定要包含在地址策略中的地址。您可以指定一个准确的地址,例如queue.bbc.new
或queue.usatoday
。或者,您可以使用通配符表达式来指定匹配的地址 集合。在上例中,地址策略还包含以字符串queue.news
开头的所有 地址名称。 exclude
-
此元素的
address-match
属性的值指定要从地址策略中排除的地址。您可以指定准确的地址名称,或使用通配符表达式来指定匹配的地址 集合。在上例中,地址策略排除以字符串queue.news.sport
开头的所有 地址名称。
(可选)使用
federation
元素,添加一个transformer
元素来引用自定义转换器实施。例如:<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.myorg.NewsTransformer</class-name> <property key="key1" value="value1"/> <property key="key2" value="value2"/> </transformer> </federation> </federations>
name
-
转换程序配置的名称。此名称在本地代理中必须是唯一的。这是您指定为地址策略的
transformer-ref
属性的值的名称。 class-name
实现
org.apache.activemq.artemis.core.server.transformer.Transformer
接口的用户定义的类的名称。转换程序的 convert ()
方法在传输消息之前通过消息调用。这可让您在联邦前转换消息标头或正文。属性
- 用于为特定转换器配置保存键值对。
在
federation
元素中,添加一个或多个upstream
元素。每个upstream
元素都定义了到远程代理的连接以及要应用到该连接的策略。例如:<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.myorg.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
和eu-west-1
的上游代理。 user
-
创建与上游代理连接时使用的用户名。如果没有指定,则使用在
federation
元素配置中指定的共享用户名。 password
-
创建与上游代理连接时使用的密码。如果没有指定,则使用在
federation
元素配置中指定的共享密码。 call-failover-timeout
-
与
call-timeout
类似,但在故障转移尝试期间进行调用时使用。默认值为-1,
这意味着超时被禁用。 call-timeout
-
当联邦连接传输阻塞调用的数据包时,联邦连接会等待来自远程代理的回复。如果这段时间过,连接会抛出异常。默认值为
30000
。 check-period
-
本地代理发送到远程代理的连续"keep-alive"消息之间,以毫秒为单位,以检查联邦连接的健康状态。如果联邦连接健康,远程代理会响应每个 keep-alive 信息。如果连接不健康,当下游代理无法从上游代理接收响应时,会使用一个名为 断路器 的机制阻止联邦用户。如需更多信息,请参阅
breaker-breaker-timeout
参数的描述。check-period
参数的默认值为30000
。 circuit-breaker-timeout
- 下游和上游代理之间的单个连接可能由多个联邦队列和地址用户共享。如果代理之间的连接丢失,每个联邦消费者可能会尝试同时重新连接。为避免这种情况,称为 断路器 的机制会阻止消费者。当指定的超时值超过时,断路器会重新尝试连接。如果成功,则消费者将被取消阻塞。否则,断路器会再次应用。
connection-ttl
-
如果联邦连接停止从远程代理接收消息,则联邦连接会保持活动状态。默认值为
60000
。 discovery-group-ref
-
作为为到上游代理连接定义静态连接器的替代选择,这个元素可以用来指定在
broker.xml
配置文件中已经配置的发现组。特别是,您可以将现有的发现组指定为此元素的discovery-group-name
属性的值。有关发现组的详情,请参考 第 14.1.6 节 “代理发现方法”。 ha
-
指定是否为到上游代理的连接启用高可用性。如果此参数的值设为
true
,则本地代理可以连接到上游集群中的任何可用代理,并在 live 上游代理关闭时自动切换到备份代理。默认值为false
。 initial-connect-attempts
-
下游代理将连接到上游代理的初始尝试次数。如果在没有建立连接的情况下达到这个值,则上游代理会被视为永久离线。downstream 代理不再将信息路由到上游代理。默认值为
-1,
这意味着没有限制。 max-retry-interval
-
当连接到远程代理失败时,后续的重新连接尝试之间以毫秒为单位。默认值为
2000
。 reconnect-attempts
-
如果连接失败,下游代理会尝试重新连接到上游代理的次数。如果在没有重新建立连接的情况下达到这个值,则上游代理将被视为永久离线。downstream 代理不再将信息路由到上游代理。默认值为
-1,
这意味着没有限制。 retry-interval
-
如果连接到远程代理的连接失败,则在后续重新连接尝试之间以毫秒为单位。默认值为
500
。 retry-interval-multiplier
-
应用到
retry-interval
参数的值的多次因素。默认值为:1
。 share-connection
-
如果同一代理同时配置了下游和上游连接,则相同的连接将共享,只要下游和上游配置都将此参数的值设置为
true
。默认值为false
。
在本地代理中,将连接器添加到远程代理中。这些是联邦地址配置的
static-connectors
元素中引用的连接器。例如:<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. 配置下游地址联邦
以下示例演示了如何为独立代理配置下游地址联邦。
下游地址联邦允许您在一个或多个远程代理用来连接到本地代理的本地代理中添加配置。这种方法的优点是您可以在单个代理上保留所有联邦配置。这可能是 hub 和 spoke 拓扑的一个有用方法,例如:
下游地址联邦将联邦连接方向与上游地址配置相反。因此,当您在配置中添加远程代理时,它们被视为 下游 代理。下游代理使用配置中的连接信息来连接本地代理,现在被视为上游。本例稍后会演示,当您为远程代理添加配置时。
先决条件
- 您应该熟悉上游地址联邦的配置。请参阅 第 4.22.5 节 “配置上游地址联邦”。
- 以下示例演示了如何配置独立代理间的地址联邦。但是,您还应熟悉为代理配置联邦 的要求。更多信息请参阅 第 4.22.4 节 “为代理配置联邦”。
流程
-
在本地代理中,打开 <
broker_instance_dir> /etc/broker.xml
配置文件。 添加包括
<federation>
项的<federations>
项。例如:<federations> <federation name="eu-north-1" user="federation_username" password="32a10275cf4ab4e9"> </federation> </federations>
添加地址策略配置。例如:
<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>
如果要在传输前转换消息,请添加转换器配置。例如:
<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.myorg.NewsTransformer</class-name> <property key="key1" value="value1"/> <property key="key2" value="value2"/> </transformer> </federation> ... </federations>
为每个远程代理添加
downstream
项。例如:<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> <upstream-connector-ref>netty-connector</upstream-connector-ref> <policy ref="news-address-federation"/> </downstream> <downstream name="eu-west-1" > <static-connectors> <connector-ref>eu-west-connector1</connector-ref> </static-connectors> <upstream-connector-ref>netty-connector</upstream-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.myorg.NewsTransformer</class-name> <property key="key1" value="value1"/> <property key="key2" value="value2"/> </transformer> </federation> ... </federations>
如前面的配置所示,远程代理现在被视为本地代理的下游。下游代理使用配置中的连接信息来连接本地(即 上游)代理。
在本地代理中添加连接器和接受器,供本地和远程代理建立联邦连接。例如:
<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"
- 本地代理发送到远程代理的连接器配置。远程代理使用此配置回本地代理。
连接器名称="eu-west-1-connector"
,connector name="eu-east-1-connector"
- 连接器到远程代理。本地代理使用这些连接器连接到远程代理,并共享远程代理连接回本地代理所需的配置。
acceptor name="netty-acceptor"
- 与远程代理用来连接到本地代理的连接器对应的本地代理上的 acceptor。
4.22.7. 关于队列联邦
队列联邦提供了一种在其他远程代理的本地代理上平衡单个队列负载的方法。
为了实现负载平衡,本地代理从远程队列检索消息,以满足来自本地消费者的消息需求。下面是一个示例。
图 4.5. 对称队列联邦
远程队列不需要重新配置,且不必在同一代理或同一集群中。建立远程链接和联邦队列所需的所有配置都位于本地代理上。
4.22.7.1. 队列联邦的优点
以下是您可能选择配置队列联邦的一些原因。
- 增加容量
- 队列联邦可以创建在多个代理上分发的"逻辑"队列。这个逻辑分布式队列的容量比单个代理中有一个队列要高。在这个设置中,尽可能多的信息会从最初发布到的代理中消耗。只有在需要负载平衡时,系统才会将消息移到联邦中。
- 部署多区域设置
在多区域设置中,您可能有一个消息制作者(region)或 venue,另一个地区(consumer)中有一个消息制作者。但是,您理想情况下,将生成者和消费者连接保留在给定区域。在这种情况下,您可以在生产者和消费者所在的每个区域中部署代理,并使用队列联邦在区域间移动消息。下面是一个示例。
图 4.6. 多区域队列联邦
- 安全企业 LAN 和 DMZ 之间的通信
在网络安全中,非企业化区域 (DMZ)是一个物理或逻辑公司,其中包含并公开面向企业的外部服务到不受信任的网络,通常是互联网等。企业局域网(LAN)的剩余部分在防火墙后仍与这个外部网络隔离。
如果很多消息制作者位于 DMZ 中,以及安全企业 LAN 中的多个消费者,则可能无法允许制作者连接到安全企业 LAN 中的代理。在这种情况下,您可以在 DMZ 中部署代理,供制作者发布消息。然后,企业 LAN 中的代理可以连接到 DMZ 中的代理,并使用联邦队列从 DMZ 中的代理接收信息。
4.22.8. 配置上游队列联邦
以下示例演示了如何为独立代理配置上游队列联邦。在本例中,您可以将一个本地的联邦(即 下游)代理配置为一些远程(即 上游)代理。
先决条件
- 以下示例演示了如何配置独立代理间的队列联邦。但是,您还应熟悉为代理配置联邦 的要求。更多信息请参阅 第 4.22.4 节 “为代理配置联邦”。
流程
-
打开 &
lt;broker_instance_dir> /etc/broker.xml
配置文件。 在新的 <
federations> 元素中
,添加一个 <federation>
元素。例如:<federations> <federation name="eu-north-1" user="federation_username" password="32a10275cf4ab4e9"> </federation> </federations>
name
- 联邦配置的名称。在本例中,名称对应于下游代理的名称。
user
- 用于连接到上游代理的共享用户名。
password
- 用于连接到上游代理的共享密码。
注意- 如果上游代理的用户和密码凭证不同,您可以在将这些代理添加到配置中时单独为这些代理指定凭证。此流程稍后将进行描述。
在
federation
元素中,添加一个 <queue-policy>
元素。为 <queue-policy&
gt; 元素的属性指定值。例如:<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
、BrokerB
和BrokerC
的链,以及BrokerA
的生成者以及BrokerC
的消费者。在这种情况下,您将希望BrokerB
重新联邦消费者到BrokerA
。priority-adjustment
-
当消费者连接到队列时,在创建上游( 联邦)消费者时使用其优先级。联邦消费者的优先级根据
priority-adjustment
属性的值调整。此属性的默认值为-1,
这样可确保本地消费者在负载平衡期间优先于联邦消费者。但是,您可以根据需要更改优先级调整的值。
如果只为本地消费者提供优先权,联邦消费者使用消息的速度导致太多消息被移到联邦消费者,但您可以限制联邦消费者消耗消息的速率。要限制消息消耗率,请在联邦用户的客户端连接 URI 中配置 consumerMaxRate
流控制选项。如需更多信息,请参阅 AMQ Core Protocol JMS Client 文档中的流控制选项。
transformer-ref
转换程序配置的名称。如果要在联邦消息传输过程中转换消息,您可以添加转换器配置。此流程稍后会描述转换器配置。
在 <
;queue-policy&
gt; 元素中,添加 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.new
或queue.usatoday
。或者,您可以使用通配符表达式来指定匹配的地址 集合。在上例中,队列策略还包含以字符串queue.news
开头的所有 地址名称。与
address-match
属性结合使用,您可以使用queue-match
属性将这些地址上的特定队列包含在队列策略中。与address-match
属性一样,您可以指定准确的队列名称,或者您可以使用通配符表达式来指定 一组 队列。在前面的示例中,数字符号 (#
) 通配符代表在每个地址或包括在队列策略中的一组地址中的所有队列。exclude
此元素的
address-match
属性的值指定为从队列策略中排除的地址。您可以指定准确的地址,或使用通配符表达式来指定匹配的地址 集合。在前面的示例中,数字符号(#
)通配符表示排除任何匹配跨越 所有地址中的queue-match
属性的队列。在这种情况下,任何以字符串.local
结尾的队列都会被排除。这表示某些队列被保留为本地队列,而不是联邦。在
federation
元素中,添加一个transformer
元素来引用自定义转换器实施。例如:<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.myorg.NewsTransformer</class-name> <property key="key1" value="value1"/> <property key="key2" value="value2"/> </transformer> </federation> </federations>
name
-
转换程序配置的名称。这个名称在问题中的代理中必须是唯一的。您可以将这个名称指定为地址策略的
transformer-ref
属性的值。 class-name
实现
org.apache.activemq.artemis.core.server.transformer.Transformer
接口的用户定义的类的名称。转换程序的 convert ()
方法在传输消息之前通过消息调用。这可让您在联邦前转换消息标头或正文。属性
用于为特定转换器配置保存键值对。
在
federation
元素中,添加一个或多个upstream
元素。每个upstream
元素都定义了上游代理连接以及要应用到该连接的策略。例如:<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.myorg.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
和eu-west-1
的上游代理。 user
-
创建与上游代理连接时使用的用户名。如果没有指定,则使用在
federation
元素配置中指定的共享用户名。 password
-
创建与上游代理连接时使用的密码。如果没有指定,则使用在
federation
元素配置中指定的共享密码。 call-failover-timeout
-
与
call-timeout
类似,但在故障转移尝试期间进行调用时使用。默认值为-1,
这意味着超时被禁用。 call-timeout
-
当联邦连接传输阻塞调用的数据包时,联邦连接会等待来自远程代理的回复。如果这段时间过,连接会抛出异常。默认值为
30000
。 check-period
-
本地代理发送到远程代理的连续"keep-alive"消息之间,以毫秒为单位,以检查联邦连接的健康状态。如果联邦连接健康,远程代理会响应每个 keep-alive 信息。如果连接不健康,当下游代理无法从上游代理接收响应时,会使用一个名为 断路器 的机制阻止联邦用户。如需更多信息,请参阅
breaker-breaker-timeout
参数的描述。check-period
参数的默认值为30000
。 circuit-breaker-timeout
- 下游和上游代理之间的单个连接可能由多个联邦队列和地址用户共享。如果代理之间的连接丢失,每个联邦消费者可能会尝试同时重新连接。为避免这种情况,称为 断路器 的机制会阻止消费者。当指定的超时值超过时,断路器会重新尝试连接。如果成功,则消费者将被取消阻塞。否则,断路器会再次应用。
connection-ttl
-
如果联邦连接停止从远程代理接收消息,则联邦连接会保持活动状态。默认值为
60000
。 discovery-group-ref
-
作为为到上游代理连接定义静态连接器的替代选择,这个元素可以用来指定在
broker.xml
配置文件中已经配置的发现组。特别是,您可以将现有的发现组指定为此元素的discovery-group-name
属性的值。有关发现组的详情,请参考 第 14.1.6 节 “代理发现方法”。 ha
-
指定是否为到上游代理的连接启用高可用性。如果此参数的值设为
true
,则本地代理可以连接到上游集群中的任何可用代理,并在 live 上游代理关闭时自动切换到备份代理。默认值为false
。 initial-connect-attempts
-
下游代理将连接到上游代理的初始尝试次数。如果在没有建立连接的情况下达到这个值,则上游代理会被视为永久离线。downstream 代理不再将信息路由到上游代理。默认值为
-1,
这意味着没有限制。 max-retry-interval
-
当连接到远程代理失败时,后续的重新连接尝试之间以毫秒为单位。默认值为
2000
。 reconnect-attempts
-
如果连接失败,下游代理会尝试重新连接到上游代理的次数。如果在没有重新建立连接的情况下达到这个值,则上游代理将被视为永久离线。downstream 代理不再将信息路由到上游代理。默认值为
-1,
这意味着没有限制。 retry-interval
-
如果连接到远程代理的连接失败,则在后续重新连接尝试之间以毫秒为单位。默认值为
500
。 retry-interval-multiplier
-
应用到
retry-interval
参数的值的多次因素。默认值为:1
。 share-connection
如果同一代理同时配置了下游和上游连接,则相同的连接将共享,只要下游和上游配置都将此参数的值设置为
true
。默认值为false
。在本地代理中,将连接器添加到远程代理中。这些是联邦地址配置的
static-connectors
元素中引用的连接器。例如:<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. 配置下游队列联邦
以下示例演示了如何配置下游队列联邦。
下游队列联邦允许您在一个或多个远程代理用来连接本地代理的本地代理中添加配置。这种方法的优点是您可以在单个代理上保留所有联邦配置。这可能是 hub 和 spoke 拓扑的一个有用方法,例如:
下游队列联邦将联邦连接方向与上游队列配置相反。因此,当您在配置中添加远程代理时,它们被视为 下游 代理。下游代理使用配置中的连接信息来连接本地代理,现在被视为上游。本例稍后会演示,当您为远程代理添加配置时。
先决条件
- 您应该熟悉上游队列联邦的配置。请参阅 第 4.22.8 节 “配置上游队列联邦”。
- 以下示例演示了如何配置独立代理间的队列联邦。但是,您还应熟悉为代理配置联邦 的要求。更多信息请参阅 第 4.22.4 节 “为代理配置联邦”。
流程
-
打开 &
lt;broker_instance_dir> /etc/broker.xml
配置文件。 添加包括
<federation>
项的<federations>
项。例如:<federations> <federation name="eu-north-1" user="federation_username" password="32a10275cf4ab4e9"> </federation> </federations>
添加队列策略配置。例如:
<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>
如果要在传输前转换消息,请添加转换器配置。例如:
<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.myorg.NewsTransformer</class-name> <property key="key1" value="value1"/> <property key="key2" value="value2"/> </transformer> </federation> ... </federations>
为每个远程代理添加
downstream
项。例如:<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> <upstream-connector-ref>netty-connector</upstream-connector-ref> <policy ref="news-address-federation"/> </downstream> <downstream name="eu-west-1" > <static-connectors> <connector-ref>eu-west-connector1</connector-ref> </static-connectors> <upstream-connector-ref>netty-connector</upstream-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.myorg.NewsTransformer</class-name> <property key="key1" value="value1"/> <property key="key2" value="value2"/> </transformer> </federation> ... </federations>
如前面的配置所示,远程代理现在被视为本地代理的下游。下游代理使用配置中的连接信息来连接本地(即 上游)代理。
在本地代理中添加连接器和接受器,供本地和远程代理建立联邦连接。例如:
<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"
- 与远程代理用来连接到本地代理的连接器对应的本地代理上的 acceptor。
第 5 章 保护代理
5.1. 安全连接
当代理连接到消息传递客户端或代理连接到其他代理时,您可以使用传输层安全(TLS)来保护这些连接。
您可以使用两个 TLS 配置:
- 单向 TLS,其中只有代理提供证书。这是最常见的配置。
- 双向(或 mutual)TLS,其中代理和客户端(或其他代理)都存在证书。
5.1.1. 配置单向 TLS
以下流程演示了如何为单向 TLS 配置给定接受者。
-
打开 &
lt;broker_instance_dir> /etc/broker.xml
配置文件。 对于给定的接受者,添加
sslEnabled
键并将值设为true
。另外,添加keyStorePath
和keyStorePassword
密钥。设置与代理密钥存储对应的值。例如:<acceptor name="artemis">tcp://0.0.0.0:61616?sslEnabled=true;keyStorePath=../etc/broker.keystore;keyStorePassword=1234!</acceptor>
5.1.2. 配置双向 TLS
以下流程演示了如何配置双向 TLS。
先决条件
- 您必须已经为单向 TLS 配置给定接受者。更多信息请参阅 第 5.1.1 节 “配置单向 TLS”。
流程
-
打开 &
lt;broker_instance_dir> /etc/broker.xml
配置文件。 对于您之前为单向 TLS 配置的 acceptor,请添加
needClientAuth
密钥。将值设为true
。例如:<acceptor name="artemis">tcp://0.0.0.0:61616?sslEnabled=true;keyStorePath=../etc/broker.keystore;keyStorePassword=1234!;needClientAuth=true</acceptor>
上一步中的配置假定客户端的证书由可信提供者签名。如果客户端证书 不是由 可信供应商(例如自签名)签名,那么代理需要将客户端证书导入到信任存储中。在这种情况下,添加
trustStorePath
和trustStorePassword
密钥。设置与代理信任存储对应的值。例如:<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 Broker 支持多种协议,每个协议和平台都有不同的方法来指定 TLS 参数。但是,在使用核心协议(a bridge)的客户端时,TLS 参数是在连接器 URL 上配置,就像在代理的 acceptor 上一样。
如果自签名证书在 Java 虚拟机(JVM)信任存储中被列为可信证书,则 JVM 不会验证证书的到期日期。在生产环境中,红帽建议您使用证书颁发机构签名的证书。
5.1.3. TLS 配置选项
下表显示了所有可用的 TLS 配置选项。
选项 | 备注 |
---|---|
|
指定是否为连接启用 SSL。必须设置为 |
| 在接受者上使用时:到包含代理 证书的代理上的 TLS 密钥存储的路径(无论是自签名还是由颁发机构签名)。
在连接器上使用时: 包含客户端证书的客户端上的 TLS 密钥存储的路径。只有在您使用双向 TLS 时,这才与连接器相关。虽然您可以在代理上配置这个值,但它会被下载并使用。如果客户端需要使用与代理上设置的不同路径,它可以使用标准的 |
| 在接受者上使用时: 代理上密钥存储的密码。
在连接器上使用时: 客户端上密钥存储的密码。只有在您使用双向 TLS 时,这才与连接器相关。虽然您可以在代理上配置这个值,但它会被下载并使用。如果客户端需要使用与代理上设置的不同密码,那么它可以使用标准的 |
| 在 接受器上使用时: 代理上 TLS 信任存储的路径,其中包含代理信任的所有客户端的密钥。只有在您使用双向 TLS 时,这才与接受者相关。
在 连接器上使用时: 客户端上 TLS 信任存储的路径,其中包含客户端信任的所有代理的公钥。虽然您可以在代理上配置这个值,但它会被下载并使用。如果客户端需要使用与服务器上设置的不同路径,那么它可以使用标准的 |
| 在 接受者中使用时: 代理上信任存储的密码。只有在您使用双向 TLS 时,这才与接受者相关。
在连接器中使用时: 客户端上信任存储的密码。虽然您可以在代理上配置这个值,但它会被下载并使用。如果客户端需要使用与代理上设置的不同密码,那么它可以使用标准的 |
| 以逗号分隔的密码套件列表,用于接受器或连接器的 TLS 通信。
指定客户端应用程序支持的最安全密码套件。如果您指定了代理和客户端通用的、以逗号分隔的密码套件列表,或者您没有指定任何密码套件、代理和客户端相互协商要使用的密码套件。如果您不知道要指定哪个密码套件,您可以首先与以 debug 模式运行的客户端建立 broker-client 连接,以验证代理和客户端通用的密码套件。然后,在代理上配置
可用的密码套件取决于代理和客户端使用的 TLS 协议版本。如果在升级代理后默认 TLS 协议版本有变化,您可能需要选择早期的 TLS 协议版本,以确保代理和客户端可以使用通用密码套件。如需更多信息,请参阅 |
| 无论在接受者或连接器中使用,这是以逗号分隔的用于 TLS 通信的协议列表。如果没有指定 TLS 协议版本,代理将使用 JVM 的默认版本。
如果代理使用 JVM 的默认 TLS 协议版本,且升级代理后该版本会改变,代理和客户端使用的 TLS 协议版本可能会不兼容。虽然建议您使用更新的 TLS 协议版本,但您可以在 |
|
此属性仅适用于接受者。它指示客户端连接到需要双向 TLS 的接受者。有效值为 |
5.2. 验证客户端
5.2.1. 客户端验证方法
要在代理中配置客户端身份验证,您可以使用以下方法之一:
- 用户名和基于密码的身份验证
使用以下选项之一直接验证用户凭证:
- 根据代理上本地存储的一组属性文件检查凭证。您还可以配置一个 客户机 帐户,允许对代理进行有限的访问,并组合登录模块来支持更复杂的用例。
- 配置 轻量级目录访问协议 (LDAP)登录模块,根据存储在中央 X.500 目录服务器中的用户数据检查客户端凭据。
- 基于证书的验证
- 配置双向 传输层安全 (TLS),以要求代理和客户端都存在用于 mutual 身份验证的证书。管理员还必须配置定义批准的客户端用户和角色的属性文件。这些属性文件存储在代理中。
- 基于 Kerberos 的身份验证
- 配置代理,以使用 简单身份验证和安全层 (SASL)框架中的 GSSAPI 机制为客户端验证 Kerberos 安全凭证。
以下章节描述了如何配置用户和密码的身份验证和基于证书的身份验证。
其他资源
要了解 LDAP 和 Kerberos 的完整身份验证和授权工作流,请参阅:
5.2.2. 根据属性文件配置用户和密码身份验证
AMQ Broker 支持灵活的基于角色的访问控制,以根据其地址将安全性应用到队列。队列绑定到一对一对点消息(用于点到点消息传递)或多对一(用于发布订阅消息传递)的地址。当消息发送到地址时,代理会查找绑定到该地址的队列集合,并将消息路由到该组队列。
当您需要基本用户和密码身份验证时,请使用 PropertiesLoginModule
来定义它。这个登录模块会根据保存在代理中的以下配置文件检查用户凭证:
artemis-users.properties
- 用于定义用户和对应的密码
artemis-roles.properties
- 用于定义角色并将用户分配到这些角色
login.config
- 用于为用户和密码身份验证和客户机访问配置登录模块
artemis-users.properties
文件可以包含哈希密码,以提高安全性。
以下小节演示了如何配置:
5.2.2.1. 配置基本用户和密码身份验证
以下步骤演示了如何配置基本用户和密码身份验证。
流程
打开 &
lt;broker_instance_dir> /etc/login.config
配置文件。默认情况下,新的 AMQ Broker 7.11 实例中这个文件包括以下行: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
- 指定将用户映射到为登录模块实施定义的角色的属性文件。
-
打开 &
lt;broker_instance_dir> /etc/artemis-users.properties
配置文件。 添加用户并为用户分配密码。例如:
user1=secret user2=access user3=myPassword
-
打开 &
lt;broker_instance_dir> /etc/artemis-roles.properties
配置文件。 将角色名称分配给您之前添加到
artemis-users.properties
文件中的用户。例如:admin=user1,user2 developer=user3
-
打开 &
lt;broker_instance_dir> /etc/bootstrap.xml
配置文件。 如有必要,将安全域别名(在这个实例中,activemq)添加到文件中,如下所示:
<jaas-security domain="activemq"/>
5.2.2.2. 配置客户机访问
对于没有登录凭证的用户,或者其凭证失败身份验证的用户,您可以使用客户机帐户授予对代理的有限访问权限。
您可以使用命令行参数创建启用了 guest 访问权限的代理实例;-- allow-anonymous
(即 --require-login
)。
以下流程演示了如何配置客户机访问。
先决条件
- 此流程假设您已经配置了基本用户和密码身份验证。如需更多信息,请参阅 第 5.2.2.1 节 “配置基本用户和密码身份验证”。
流程
-
打开您之前为基本用户和密码身份验证配置的 &
lt;broker_instance_dir> /etc/login.config
配置文件。 在之前添加的属性登录模块配置后,添加客户机登录模块配置。例如:
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. 客户端访问示例
以下示例显示了对用例的客户机访问配置,其中只有没有凭证的用户作为客户机登录。在本例中,观察登录模块的顺序是否已与前面的配置过程相反。此外,附加到属性登录模块的标志将更改为 必要的
。
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 身份验证模块。
对于这个用例,在客户机登录模块配置中必须将 credentialsInvalidate
选项设置为 true
。
如果提供了凭据,则会激活属性登录模块。凭据必须有效。
其他资源
-
有关 Java 身份验证和授权服务 (JAAS)的更多信息,请参阅 Java 供应商中的文档。例如,有关配置
login.config
的 Oracle 指南,请参阅 Oracle Java 文档中的 JAAS 登录 配置文件。 - 要了解如何配置 LDAP 登录模块以验证客户端凭证,请参阅 第 5.4.1 节 “配置 LDAP 以验证客户端”。
- 有关在配置文件中加密密码的详情,请参考 第 5.9.2 节 “在配置文件中加密密码”。
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. 配置代理以使用基于证书的身份验证
以下流程演示了如何将代理配置为使用基于证书的验证。
先决条件
- 您必须将代理配置为使用双向传输层安全(TLS)。更多信息请参阅 第 5.1.2 节 “配置双向 TLS”。
流程
从之前导入到代理密钥存储的用户证书获取 Subject Distinguished Names (DN)。
将密钥存储文件中的证书导出到临时文件中。例如:
keytool -export -file <file_name> -alias broker-localhost -keystore broker.ks -storepass <password>
显示导出的证书的内容:
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
条目是 Subject DN。用于输入 Subject DN 的格式取决于您的平台。以上字符串也可以表示:Owner: `CN=localhost,\ OU=broker,\ O=Unknown,\ L=Unknown,\ ST=Unknown,\ C=Unknown`
配置基于证书的验证。
打开 &
lt;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
- 指定将用户映射到为登录模块实施定义的角色的属性文件。
打开 &
lt;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
Subject DN。打开 &
lt;broker_instance_dir> /etc/artemis-roles.properties
配置文件。此文件中定义了可用的角色和拥有这些角色的用户。例如:admins=system users=system,user guests=guest
在前面的配置中,对于
users
角色,您将以逗号分隔列表列出多个用户。请确保您的安全域别名(在本例中是 activemq)在
bootstrap.xml
中引用,如下所示:<jaas-security domain="activemq"/>
5.2.3.2. 为 AMQP 客户端配置基于证书的身份验证
在 连接到代理时,使用简单身份验证和安全层 (SASL) EXTERNAL 机制配置参数,将 AQMP 客户端配置为基于证书的身份验证。
代理会以验证任何证书的相同方式验证您的 AMQP 客户端的 Transport Layer Security (TLS)/Secure Sockets Layer (SSL) 证书:
- 代理读取客户端的 TLS/SSL 证书,以从证书的主题获取身份。
- 证书主题由证书登录模块映射到代理身份。然后代理会根据用户的角色授权用户。
以下流程演示了如何为 AMQP 客户端配置基于证书的身份验证。要启用 AMQP 客户端使用基于证书的身份验证,您必须在客户端用来连接到代理的 URI 中添加配置参数。
先决条件
您必须已配置了:
- 双向 TLS。更多信息请参阅 第 5.1.2 节 “配置双向 TLS”。
- 使用基于证书的身份验证的代理。更多信息请参阅 第 5.2.3.1 节 “配置代理以使用基于证书的身份验证”。
流程
打开包含 URI 的资源进行编辑:
amqps://localhost:5500
添加参数
sslEnabled=true
来为连接启用 TSL/SSL:amqps://localhost:5500?sslEnabled=true
添加与客户端信任存储和密钥存储相关的参数,以便使用代理启用 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
,以使用其 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
其他资源
- 有关 AMQ Broker 中基于证书的身份验证的更多信息,请参阅 第 5.2.3.1 节 “配置代理以使用基于证书的身份验证”。
- 有关配置 AMQP 客户端的更多信息,请访问红帽客户门户网站 以获取特定于您的客户端的产品文档。
5.3. 授权客户端
5.3.1. 客户端授权方法
要授权客户端对代理执行操作,如创建和删除地址和队列,以及发送和接收消息,您可以使用以下方法:
- 基于用户和角色的授权
- 为经过身份验证的用户和角色配置代理安全设置。
- 配置 LDAP 以授权客户端
- 配置 轻量级目录访问协议( LDAP)登录模块,以处理身份验证和授权。LDAP 登录模块会根据存储在中央 X.500 目录服务器中的用户数据检查传入的凭据,并根据用户角色设置权限。
- 配置 Kerberos 以授权客户端
-
配置 Java 身份验证和授权服务 (JAAS) K
rb5LoginModule
登录模块,将凭证传递给PropertiesLoginModule
或LDAPLoginModule
登录模块,它将 Kerberos 验证的用户映射到 AMQ Broker 角色。
5.3.2. 配置基于用户和角色的授权
5.3.2.1. 设置权限
权限通过 broker.xml
配置文件中的 < security-setting&
gt; 元素根据队列(基于其地址)定义。您可以在配置文件的 <security-settings>
项中定义多个 <security-setting>
实例。您可以指定一个准确的地址匹配,或者使用数字符号(#
)和星号(*
)通配符字符来定义通配符匹配。
可将不同的权限提供给与地址匹配的队列集合。这些权限显示在下表中。
允许用户… | 使用此参数… |
---|---|
创建地址 |
|
删除地址 |
|
在匹配地址下创建一个持久队列 |
|
删除匹配地址下的持久队列 |
|
在匹配地址下创建一个不可配置队列 |
|
在匹配地址下删除不可配置队列 |
|
发送消息到匹配的地址 |
|
使用绑定到匹配地址的队列的消息 |
|
通过将管理消息发送到管理地址来调用管理操作 |
|
浏览绑定到匹配地址的队列 |
|
对于每个权限,您可以指定被授予权限的角色列表。如果给定用户有任何角色,则他们被授予该组地址的权限。
以下章节显示了一些权限配置示例。
5.3.2.1.1. 为一个地址配置消息生产
以下流程演示了如何为单个地址配置消息生产权限。
流程
-
打开 &
lt;broker_instance_dir> /etc/broker.xml
配置文件。 在
<security-settings>
项中添加一个单一的<security-setting>
项。对于match
键,指定一个地址。例如:<security-settings> <security-setting match="my.destination"> <permission type="send" roles="producer"/> </security-setting> </security-settings>
根据前面的配置,
制作者
角色的成员具有地址my.destination
的发送
权限。
5.3.2.1.2. 为一个地址配置消息消耗
以下流程演示了如何为单个地址配置消息消耗权限。
流程
-
打开 &
lt;broker_instance_dir> /etc/broker.xml
配置文件。 在
<security-settings>
项中添加一个单一的<security-setting>
项。对于match
键,指定一个地址。例如:<security-settings> <security-setting match="my.destination"> <permission type="consume" roles="consumer"/> </security-setting> </security-settings>
根据上述配置,
consumer
角色的成员具有地址my.destination
的consume
权限。
5.3.2.1.3. 配置所有地址的完整访问权限
以下流程演示了如何配置对所有地址和相关队列的完整访问。
流程
-
打开 &
lt;broker_instance_dir> /etc/broker.xml
配置文件。 在
<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 节 “配置多个安全设置”。
5.3.2.1.4. 配置多个安全设置
以下示例演示了如何为匹配的一组地址单独配置多个安全设置。这与本节中前面的示例相反,它演示了如何为 所有地址授予完全访问权限
-
打开 &
lt;broker_instance_dir> /etc/broker.xml
配置文件。 在
<security-settings>
项中添加一个单一的<security-setting>
项。对于match
键,请包含数字符号(DSL
)通配符字符,以将设置应用到匹配的地址 集合。例如:<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.#
-
数字符号(
DSL
)通配符字符由代理解释为"任何单词序列"。词语用句点(.
)分隔。在本例中,安全设置适用于以字符串 globalqueues.europe开头的任何地址。 permission type="createDurableQueue"
-
只有具有
admin
角色的用户才能创建和删除绑定到以字符串 globalqueues.europe开头的地址的危险队列。 permission type="createNonDurableQueue"
-
具有角色
admin
、guest
或europe-users
的用户都可以创建和删除绑定到以字符串 globalqueues.europe开头的地址的临时队列。 permission type="send"
-
任何角色
admin
或europe-users
的用户都可以发送消息到绑定到以字符串 globalqueues.europe开头的地址。 permission type="consume"
-
具有角色
admin
或europe-users
的任何用户都可以使用绑定到以字符串 globalqueues.europe开头的地址的消息。
(可选)要将不同的安全设置应用到更为严格的地址集合,请添加另一个 <
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
元素中,globalqueues.europe.orders.#
的匹配比第一个security-setting
元素中的globalqueues.europe.#
匹配更加具体。对于与globalqueues.europe.orders.#
匹配的任何地址,权限createDurableQueue
,deleteDurableQueue
,createNonDurableQueue
,deleteNonDurableQueue
不是从文件的第一个security-setting
元素继承的。例如,对于地址globalqueues.europe.orders.plastics
,唯一存在的权限才会为角色europe-users
发送
和使用
。因此,由于在一个
安全设置
块中指定的权限不会被另一个继承,因此您可以通过不指定这些权限来有效地拒绝更具体的安全设置
块的权限。
5.3.2.1.5. 使用用户配置队列
自动创建队列时,队列将被分配连接客户端的用户名。此用户名作为元数据包含在队列中。名称由 JMX 和 AMQ Broker 管理控制台公开。
以下流程演示了如何在代理配置中手动定义的队列中添加用户名。
流程
-
打开 &
lt;broker_instance_dir> /etc/broker.xml
配置文件。 对于给定队列,
添加用户
密钥。分配一个值。例如:<address name="ExampleQueue"> <anycast> <queue name="ExampleQueue" user="admin"/> </anycast> </address>
根据前面的配置,
admin
用户被分配给队列ExampleQueue
。
- 在队列中配置用户不会更改该队列的任何安全语义 - 它仅用于该队列的元数据。
用户之间的映射及其由名为 安全管理器 的组件处理的角色。安全管理器从代理中存储的属性文件中读取用户凭证。默认情况下,AMQ Broker 使用
org.apache.activemq.artemis.spi.core.security.ActiveMQJAASSecurityManager
安全管理器。此默认安全管理器提供与 JAAS 和 Red Hat JBoss Enterprise Application Platform (JBoss EAP)安全性的集成。要了解如何 使用自定义 安全管理器,请参阅 第 5.6.2 节 “指定自定义安全管理器”。
5.3.2.2. 配置基于角色的访问控制
基于角色的访问控制 (RBAC)用于限制对 MBeans 属性和方法的访问。RBAC 可让管理员根据角色为所有用户授予正确的访问权限,如 Web 控制台、管理界面和核心信息等。
5.3.2.2.1. 配置基于角色的访问控制
以下示例演示了如何将角色映射到特定的 MBeans 及其属性和方法。
先决条件
- 您必须首先定义用户和角色。更多信息请参阅 第 5.2.2.1 节 “配置基本用户和密码身份验证”。
流程
-
打开 &
lt;broker_instance_dir> /etc/management.xml
配置文件。 搜索
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 属性。 -
访问
view
,update
, 或amq
角色来匹配 MBean 属性由您添加到角色的list*
,get*
,set*
,is*
, 和*
访问方法控制。method="*"
(通配符) 语法作为一个 catch-all 的方式,适用于没有在配置中列出的所有其他方法。配置中的每个访问方法都转换为 MBean 方法调用。 -
调用的 MBean 方法与配置中列出的方法匹配。例如,如果您在带有
org.apache.activemq.artemis
域的 MBean 上调用名为listMessages
的方法,那么代理会将访问权限与list
方法配置中定义的角色匹配。 您还可以使用完整的 MBean 方法名称来配置访问。例如:
<access method="listMessages" roles="view,update,amq"/>
-
在本例中,匹配项应用于具有域名
启动或重启代理。
-
On Linux:
<broker_instance_dir>/bin/artemis run
-
在 Windows 上:
<broker_instance_dir> \bin\artemis-service.exe start
-
On Linux:
您还可以通过添加与 MBean 属性匹配的 key
属性来匹配域中的特定 MBeans。
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
属性将角色映射到名为 queue 的特定角色。在本例中,命名的 queue 是 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&
gt; 元素,如下所示:
<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
的队列与两个通配符密钥表达式匹配。因此,代理需要一个优先方案来决定哪组角色映射到队列;在第一个 match
项中指定的角色,或在第二个 match
项中指定的角色。
当同一域中有多个匹配项时,代理会在映射角色时使用以下优先级方案:
- 完全匹配的优先级高于通配符匹配
- 较长的通配符匹配优先于较短的通配符匹配
在本例中,由于较长的通配符表达式与 example.sub.queue
的队列名称匹配,因此代理会应用第二个 < match
> 元素中配置的 role-mapping。
default-access
元素是每种方法调用的 catch-all 元素,这些调用没有使用 role-access
或 whitelist
配置进行处理。default-access
和 role-access
元素具有相同的 match
元素语义。
5.3.2.2.3. 配置 whitelist 元素
白名单是一组预先批准的域或 MBeans,不需要用户身份验证。您可以提供必须绕过身份验证的域列表或 MBeans 列表。例如,您可以使用白名单来指定 AMQ Broker 管理控制台要运行的任何 MBeans。
以下示例演示了如何配置 whitelist
元素。
流程
-
打开 &
lt;broker_instance_dir> /etc/management.xml
配置文件。 搜索
whitelist
元素并编辑配置:<whitelist> <entry domain="hawtio"/> </whitelist>
在本例中,任何具有域
hawtio
的 MBean 都被允许访问,而无需身份验证。您也可以使用 <entry domain="hawtio" key="type=rhacm"/>
形式的通配符条目来匹配 MBean 属性。启动或重启代理。
-
On Linux:
<broker_instance_dir>/bin/artemis run
-
在 Windows 上:
<broker_instance_dir> \bin\artemis-service.exe start
-
On Linux:
5.3.2.3. 设置资源限值
有时,设置特定限制会超过与授权和身份验证相关的普通安全设置。
5.3.2.3.1. 配置连接和队列限制
以下示例流程演示了如何限制用户可以创建的连接和队列数量。
-
打开 &
lt;broker_instance_dir> /etc/broker.xml
配置文件。 添加
resource-limit-settings
元素。为max-connections
和max-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,
这意味着没有限制。如果要限制会话数量,请考虑从 AMQ 核心协议 JMS 客户端到代理的连接会创建两个会话。 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 验证客户端。
流程
-
打开 &
lt;broker_instance_dir> /etc/broker.xml
配置文件。 在
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>
前面的配置 将所有 队列的特定权限
分配给用户
角色的成员。-
打开 &
lt;broker_instance_dir> /etc/login.config
文件。 根据您要使用的目录服务配置 LDAP 登录模块。
如果您使用 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"
。如果您使用 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
)或关闭(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
以毫秒为单位指定代理连接到目录服务器的最长时间。如果代理无法连接到该目录,它会中止连接尝试。如果为此属性指定 0 或更小的值,则会使用底层 TCP 协议的超时值。如果没有指定值,代理会无限期等待建立连接,或者底层网络超时。
当为连接请求连接池时,此属性指定代理达到最大池大小并且池中所有连接都被使用时的最大时间。如果您指定的值为零或更少,代理会无限期等待连接可用。否则,代理会在达到最长等待时间时中止连接尝试。
身份验证
-
指定绑定到 LDAP 服务器时使用的身份验证方法。这个参数可以设置为
simple
(需要用户名和密码)或none
(允许匿名访问)。 userBase
-
选择 DIT 的特定子树来搜索用户条目。子树由 DN 指定,用于指定子树的基本节点。例如,通过将此选项设置为
ou=User,ou=ActiveMQ,ou=system
,对用户条目的搜索仅限于ou=User,ou=ActiveMQ,ou=system
节点下的子树。 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
、roleSearchMatching
、roleSearchSubtree
、roleName
和 roleName )作为指定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 路径,如oid=testuser,dc=example,dc=com
,而您可以在 Microsoft Active Directory 中使用 DN 路径,如cn=testuser,dc=example,dc=com
。
- 启动或重启代理(服务或进程)。
5.4.1.1. 搜索匹配参数
userSearchMatching
在传递给 LDAP 搜索操作前,此配置参数中提供的字符串值受到字符串替换,如
java.text.MessageFormat
类所实现。
这意味着,特殊字符串
{0}
被用户名替代,如从传入的客户端凭证中提取。替换后,字符串被解释为 LDAP 搜索过滤器(语法由 IETF 标准 RFC 2254 定义)。
例如,如果此选项设置为
(uid={0})
,且收到的用户名是jdoe
,搜索过滤器会在字符串替换后变为(uid=jdoe)
。
如果生成的搜索过滤器应用到用户 base
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
,在进行了字符串替换后,搜索过滤器变为(member=uid=jdoe)
(假设使用 ApacheDS 搜索过滤器语法)。
如果生成的搜索过滤器被应用由角色基础 (
ou=Group,ou=ActiveMQ,ou=system
) 所选择的子树,它将匹配具有member
属性等于uid=jdoe
(member
属性的值是一个 DN)。
必须始终设置这个选项,即使角色搜索被禁用,因为它没有默认值。如果使用 OpenLDAP,搜索过滤器的语法为
(member:=uid=jdoe)
。
其他资源
- 有关搜索过滤器语法的简短介绍,请参阅 Oracle JNDI 教程。
5.4.2. 配置 LDAP 授权
LegacyLDAPSecuritySettingPlugin
安全设置插件读取之前在 AMQ 6 中由 LDAPAuthorizationMap
和 cachedLDAPAuthorizationMap
控制的安全信息,并在可能的情况下将这个信息转换为对应的 AMQ 7 安全设置。
AMQ 6 和 AMQ 7 中的代理的安全实现不匹配。因此,插件在两个版本之间执行一些转换,以实现接近等效的功能。
以下示例演示了如何配置插件。
流程
-
打开 &
lt;broker_instance_dir> /etc/broker.xml
配置文件。 在
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
默认值为ou=destinations,o=ActiveMQ,ou=system
。 filter
-
指定 LDAP 搜索过滤器,用于查找任何类型的目的地的权限。search 过滤器尝试匹配队列或主题节点的其中一个子项或后代。默认值为
(cn=*)
。 roleAttribute
-
指定节点的一个属性,它匹配其值是一个角色的 DN 的
filter
。默认值为uniqueMember
。 adminPermissionValue
-
指定与
admin
权限匹配的值。默认值为admin
。 readPermissionValue
-
指定匹配
read
权限的值。默认值为read
。 writePermissionValue
-
指定匹配
write
权限的值。默认值为write
。 enableListener
-
指定是否启用在 LDAP 服务器中自动接收更新的监听程序,并实时更新代理的授权配置。默认值为
true
。 mapAdminToManage
指定是否将传统(即 AMQ 6)
admin
的权限映射到 AMQ 7manage
权限。请查看下表中映射语义的详情。默认值为false
。LDAP 中定义的队列或主题的名称充当安全设置的"match",权限值从 AMQ 6 类型映射到 AMQ 7 类型,并且角色映射为原样。由于 LDAP 中定义的队列或主题的名称充当安全设置的匹配项,因此可能无法将安全设置应用到 JMS 目的地。这是因为 AMQ 7 始终根据需要使用 "jms.queue." 或 "jms.topic." 前缀 JMS 目的地。
AMQ 6 有三种权限类型 -
读
、写
和admin
。这些权限类型在 ActiveMQ 网站上描述; 安全。AMQ 7 具有以下权限类型:
-
createAddress
-
deleteAddress
-
createDurableQueue
-
deleteDurableQueue
-
createNonDurableQueue
-
deleteNonDurableQueue
-
send
-
消耗
-
管理
浏览
下表显示了安全设置插件如何将 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 6admin
权限映射到 AMQ 7管理权限
。 -
AMQ 6 中的
admin
权限类型决定代理是否在目的地不存在时自动创建目的地,用户会向它发送一条消息。如果用户有权发送消息到目的地,AMQ 7 会自动创建目的地。因此,插件将旧的admin
权限映射到上面显示的 AMQ 7 权限。如果mapAdminToManage
设为true
,则该插件也会将 AMQ 6admin
权限映射到 AMQ 7manage
权限。
-
映射默认不包括 AMQ 7
-
allowQueueAdminOnRead
是否要将旧的读取权限映射到 createDurableQueue、createNonDurableQueue 和 deleteDurableQueue 权限,以便 JMS 客户端能否创建不可变且不可激活的订阅,而无需 admin 权限。这在 AMQ 6 中允许。默认值为 false。
下表显示了当
allowQueueAdminOnRead
为true
时,安全设置插件如何将 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 服务器的密码,因此此密码需要加密。
先决条件
-
确保您已修改了
login.config
文件以添加所需属性,如 第 5.4.2 节 “配置 LDAP 授权” 所述。
流程
以下流程演示了如何屏蔽 < broker_instance_dir> /etc/login.config
文件中的 connectionPassword
参数的值。
在命令提示符中,使用
mask
工具加密密码:$ <broker_instance_dir>/bin/artemis mask <password>
result: 3a34fd21b82bf2a822fa49a8d8fa115d
打开 &
lt;broker_instance_dir> /etc/login.config
文件。找到connectionPassword
参数:connectionPassword = <password>
将纯文本密码替换为加密值:
connectionPassword = 3a34fd21b82bf2a822fa49a8d8fa115d
使用标识符
"ENC ()"
嵌套加密值:connectionPassword = "ENC(3a34fd21b82bf2a822fa49a8d8fa115d)"
login.config
文件现在包含屏蔽的密码。由于密码使用 "ENC ()"
标识符嵌套,所以 AMQ Broker 在使用前会对其进行解密。
其他资源
- 有关 AMQ Broker 中包含的配置文件的更多信息,请参阅 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 协议发送和接收消息时,客户端可以使用 Simple Authentication and Security Layer (SASL)框架中的 GSSAPI 机制发送 Kerberos 安全凭证。Kerberos 凭据可用于授权,方法是将经过身份验证的用户映射到在 LDAP 目录或基于文本的属性文件中配置分配的角色。
您可以将 SASL 与 传输层安全 (TLS)搭配使用来保护您的消息传递应用程序。SASL 提供用户身份验证,TLS 提供数据完整性。
您必须在 AMQ Broker 验证和授权 Kerberos 凭证前部署和配置 Kerberos 基础架构。有关部署 Kerberos 的更多信息,请参阅您的操作系统文档。
- 对于 RHEL 7,请参阅使用 Kerberos。
- 对于 Windows,请参阅 Kerberos 身份验证概述。
- Oracle 或 IBM JDK 的用户应该安装 Java Cryptography 扩展(JCE)。如需更多信息,请参阅 Oracle version of the JCE 或 IBM version of the JCE。
以下流程演示了如何为身份验证和授权配置 Kerberos。
5.5.1. 配置网络连接以使用 Kerberos
AMQ Broker 使用 简单身份验证和安全层 (SASL)框架中的 GSSAPI 机制与 Kerberos 安全凭证集成。要在 AMQ Broker 中使用 Kerberos,每个接受者身份验证或授权使用 Kerberos 凭证的客户端都必须配置为使用 GSSAPI 机制。
以下流程演示了如何配置接受者以使用 Kerberos。
先决条件
- 您必须在 AMQ Broker 验证和授权 Kerberos 凭证前部署和配置 Kerberos 基础架构。
流程
停止代理。
对于 Linux:
<broker_instance_dir>/bin/artemis stop
对于 Windows:
<broker_instance_dir>\bin\artemis-service.exe stop
-
打开 &
lt;broker_instance_dir> /etc/broker.xml
配置文件。 将 name-value 对
saslMechanisms=GSSAPI
添加到acceptor
的 URL 的查询字符串中。<acceptor name="amqp"> tcp://0.0.0.0:5672?protocols=AMQP;saslMechanisms=GSSAPI </acceptor>
前面的配置意味着 acceptor 在验证 Kerberos 凭证时使用 GSSAPI 机制。
(可选)另外还支持
PLAIN
和ANONYMOUS
SASL 机制。要指定多个机制,请使用逗号分隔的列表。例如:<acceptor name="amqp"> tcp://0.0.0.0:5672?protocols=AMQP;saslMechanisms=GSSAPI,PLAIN </acceptor>
结果是一个接受者,它使用
GSSAPI
和PLAIN
SASL 机制。启动代理。
对于 Linux:
<broker_instance_dir>/bin/artemis run
对于 Windows:
<broker_instance_dir>\bin\artemis-service.exe start
其他资源
- 有关接受器的详情,请参考 第 2.1 节 “关于接受者”。
5.5.2. 使用 Kerberos 凭证验证客户端
AMQ Broker 支持使用 简单身份验证和安全层 (SASL)框架中的 GSSAPI 机制的 AMQP 连接的 Kerberos 身份验证。
代理使用 Java 身份验证和授权服务 (JAAS)获取其 Kerberos 接受器凭证。Java 安装中包含的 JAAS 库与登录模块 Krb5LoginModule
打包,用于验证 Kerberos 凭证。有关 Krb5LoginModule
的更多信息,请参阅 Java 供应商中的文档。例如,Oracle 提供有关其 Krb5LoginModule
登录模块的信息,作为其 Java 8 文档 的一部分。
先决条件
- 您必须启用 acceptor 的 GSSAPI 机制,然后才能使用 Kerberos 安全凭证验证 AMQP 连接。更多信息请参阅 第 5.5.1 节 “配置网络连接以使用 Kerberos”。
流程
停止代理。
对于 Linux:
<broker_instance_dir>/bin/artemis stop
对于 Windows:
<broker_instance_dir>\bin\artemis-service.exe stop
-
打开 &
lt;broker_instance_dir> /etc/login.config
配置文件。 添加名为
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 acceptor 凭证。 Krb5LoginModule
-
此版本的
Krb5LoginModule
由 JDK 的 Oracle 和 OpenJDK 版本提供。通过引用 Java 供应商中的文档来验证Krb5LoginModule
及其可用选项的完全限定类名称。 useKeyTab
-
Krb5LoginModule
配置为在验证主体时使用 Kerberos keytab。keytab 使用 Kerberos 环境中的工具生成。有关生成 Kerberos keytab 的详细信息,请参阅厂商中的文档。 主体
-
Principal 设置为
amqp/my_broker_host@example.com
。这个值必须与在 Kerberos 环境中创建的服务主体对应。有关创建服务主体的详情,请查看厂商中的文档。
启动代理。
对于 Linux:
<broker_instance_dir>/bin/artemis run
对于 Windows:
<broker_instance_dir>\bin\artemis-service.exe start
5.5.2.1. 使用其他配置范围
您可以通过将参数 saslLoginConfigScope
添加到 AMQP acceptor 的 URL 来指定备选配置范围。在以下配置中,参数 saslLoginConfigScope
被赋予值 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 添加到 Subject 的主体中,设置为 AMQ Broker UserPrincipal。然后,可以将凭证传递给 PropertiesLoginModule
或 LDAPLoginModule
模块,该模块将 Kerberos 验证的 Peer Principal 传递给 AMQ Broker 角色。
Kerberos Peer Principal 不存在为代理用户,仅作为角色成员。
先决条件
- 您必须启用 acceptor 的 GSSAPI 机制,然后才能使用 Kerberos 安全凭证授权 AMQP 连接。
流程
停止代理。
对于 Linux:
<broker_instance_dir>/bin/artemis stop
对于 Windows:
<broker_instance_dir>\bin\artemis-service.exe stop
-
打开 &
lt;broker_instance_dir> /etc/login.config
配置文件。 添加 AMQ Broker
Krb5LoginModule
和LDAPLoginModule
的配置。通过引用 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 模块用于角色映射。启动代理。
对于 Linux:
<broker_instance_dir>/bin/artemis run
对于 Windows:
<broker_instance_dir>\bin\artemis-service.exe start
其他资源
- 有关在 AMQ Broker 中启用 GSSAPI 机制的更多信息,请参阅 第 5.5.1 节 “配置网络连接以使用 Kerberos”。
-
有关
PropertiesLoginModule
的更多信息,请参阅 第 5.2.2.1 节 “配置基本用户和密码身份验证”。 -
有关
LDAPLoginModule
的更多信息,请参阅 第 5.4.1 节 “配置 LDAP 以验证客户端”。
5.6. 指定安全管理器
代理使用一个名为安全管理器的组件来处理身份验证和授权。
AMQ Broker 包括两个安全管理器:
-
ActiveMQJAASSecurityManager
安全管理器。此安全管理器提供与 JAAS 和 Red Hat JBoss Enterprise Application Platform (JBoss EAP)安全性的集成。这是 AMQ Broker 使用的默认安全管理器。 -
ActiveMQBasicSecurityManager
安全管理器。这个基本安全管理器不支持 JAAS。相反,它支持通过用户名和密码凭证进行身份验证和授权。此安全管理器支持使用管理 API 添加、删除和更新用户。所有用户和角色数据都存储在代理绑定日志中。这意味着,对实时代理所做的任何更改都可用于其备份代理。
作为包含的安全管理器的替代选择,系统管理员可能需要更好地控制代理安全性的实施。在这种情况下,也可以在代理配置中指定 自定义 安全管理器。自定义安全管理器是一个用户定义的类,它实现了 org.apache.activemq.artemis.spi.core.security.ActiveMQSecurityManager5
接口。
以下子部分中的示例演示了如何配置代理来使用:
- 基本安全管理器而不是默认的 JAAS 安全管理器
- 自定义安全管理器
5.6.1. 使用基本安全管理器
除了默认的 ActiveMQJAASSecurityManager
安全管理器外,AMQ Broker 还包含 ActiveMQBasicSecurityManager
安全管理器。
当您使用基本安全管理器时,所有用户和角色数据存储在绑定日志中(如果使用 JDBC 持久性,则绑定 表 )。因此,如果您配置了 live-backup 代理组,您在实时代理上执行的任何用户管理都会在故障切换时自动反映在备份代理中。这可避免单独管理 LDAP 服务器,这是实现此行为的替代方法。
在配置和使用基本安全管理器前,请注意以下几点:
- 基本安全管理器不像默认的 JAAS 安全管理器一样可插拔。
- 基本安全管理器不支持 JAAS。相反,它只支持通过用户名和密码凭证进行身份验证和授权。
-
AMQ 管理控制台需要 JAAS。因此,如果您使用基本的安全管理器并希望使用控制台,您还需要配置
login.config
配置文件以进行用户和密码身份验证。有关配置用户和密码验证的详情,请参考 第 5.2.2.1 节 “配置基本用户和密码身份验证”。 - 在 AMQ Broker 中,用户管理由代理管理 API 提供。此管理包括添加、列出、更新和删除用户及角色。您可以使用 JMX、管理消息、HTTP (使用 Jolokia 或 AMQ 管理控制台)和 AMQ Broker 命令行界面来执行这些功能。由于代理直接存储此数据,因此代理必须正在运行才能管理用户。无法手动修改绑定数据。
- 任何通过 HTTP 的管理访问(例如,使用 Jolokia 或 AMQ 管理控制台)都由 console JAAS 登录模块处理。通过 JConsole 或其他远程 JMX 工具进行 MBean 访问是由基本安全管理器处理的。管理消息由基本安全管理器处理。
5.6.1.1. 配置基本安全管理器
以下流程演示了如何将代理配置为使用基本安全管理器。
流程
-
打开 &
lt;broker-instance-dir> /etc/boostrap.xml
配置文件。 在
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>
因为您无法手动修改包含用户和角色数据的绑定数据,并且由于代理必须正在运行来管理用户,因此建议在第一次引导时保护代理的安全。要达到此目的,请定义一个 bootstrap 用户,其凭据可用于添加其他用户。
在
security-manager
元素中,添加bootstrapUser
、bootstrapPassword
和bootstrapRole
属性并指定值。例如:<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
- boostrap 用户的 Passsword。您还可以指定加密的密码。
bootstrapRole
boostrap 用户的角色。
注意如果您在配置中为 bootstrap 用户定义前面的属性,则每次启动代理时都会设置这些凭证,无论代理运行时所做的任何更改是什么。
-
打开 &
lt;broker_instance_dir> /etc/broker.xml
配置文件。 在
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>
在为
activemq.management#
地址匹配的地址设置中,对于您在此流程前面指定的 bootstrap 角色名称,添加以下所需的权限:-
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>
-
其他资源
-
如需有关
ActiveMQBasicSecurityManager
类的更多信息,请参阅 ActiveMQ Artemis Core API 文档中的 Class ActiveMQBasicSecurityManager。 - 要了解如何在配置文件中加密密码,请参阅 第 5.9 节 “在配置文件中加密密码”。
5.6.2. 指定自定义安全管理器
以下流程演示了如何在代理配置中指定自定义安全管理器。
流程
-
打开 &
lt;broker_instance_dir> /etc/boostrap.xml
配置文件。 在
security-manager
元素中,对于class-name
属性,指定org.apache.activemq.artemis.spi.core.security.security.ActiveMQSecurityManager5
接口的用户定义的实现。例如:<broker xmlns="http://activemq.org/schema"> ... <security-manager class-name="com.myclass.MySecurityManager"> <property key="myKey1" value="myValue1"/> <property key="myKey2" value="myValue2"/> </security-manager> ... </broker>
其他资源
-
有关
ActiveMQSecurityManager5
接口的更多信息,请参阅 ActiveMQ Artemis Core API 文档中的 Interface ActiveMQSecurityManager5。
5.6.3. 运行自定义安全管理器示例程序
AMQ Broker 包括一个示例程序,演示了如何实现自定义安全管理器。在示例中,自定义安全管理器记录身份验证和授权的详细信息,然后将详细信息传递给 ActiveMQJAASSecurityManager
实例(即默认安全管理器)。
以下流程演示了如何运行自定义安全管理器示例程序。
先决条件
- 必须设置您的机器才能运行 AMQ Broker 示例程序。如需更多信息,请参阅 运行 AMQ Broker 示例。
流程
导航到包含自定义安全管理器示例的目录。
$ cd <install_dir>/examples/features/standard/security-manager
运行示例。
$ mvn verify
如果您希望在运行示例程序时手动创建并启动代理实例,请将上一步中的命令替换为 mvn -PnoServer verify
。
其他资源
-
如需有关
ActiveMQJAASSecurityManager
类的更多信息,请参阅 ActiveMQ Artemis Core API 文档中的 Class ActiveMQJAASSecurityManager。
5.7. 禁用安全性
默认启用 安全性。以下流程演示了如何禁用代理安全性。
流程
-
打开 &
lt;broker_instance_dir> /etc/broker.xml
配置文件。 在
core
元素中,将启用了security-enabled
的值设置为false
。<security-enabled>false</security-enabled>
-
如有必要,为
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
为 false
,并且 populate-validated-user
为 true
,则代理会填充客户端提供的任何用户名。populate-validated-user
选项默认为 false
。
您可以将代理配置为拒绝客户端没有用户名(即 JMSXUserID
密钥)的消息在发送消息时已被填充。您可以发现此选项对 AMQP 客户端有用,因为代理无法为这些客户端发送的消息填充验证的用户名本身。
要将代理配置为拒绝客户端设置 JMSXUserID
的信息,请在 broker.xml
配置文件中添加以下配置:
<reject-empty-validated-user>true</reject-empty-validated-user>
默认情况下,deny-empty-validated-user
设置为 false
。
5.9. 在配置文件中加密密码
默认情况下,AMQ Broker 将所有密码以纯文本形式存储在配置文件中。务必保护所有具有正确权限的配置文件,以防止未经授权的访问。您还可以加密或 掩码 纯文本密码,以防止不需要的查看者读取它们。
5.9.1. 关于加密密码
加密或 屏蔽 的、密码是纯文本密码的加密版本。加密的版本由 AMQ Broker 提供的 mask
命令行工具生成。有关 mask
工具的更多信息,请参阅命令行帮助文档:
$ <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
仅支持已屏蔽的密码。在创建代理时创建用户时,artemis-users.properties
默认包含哈希密码。默认 PropertiesLoginModule
不会解码 artemis-users.properties
文件中的密码,而是哈希输入并比较密码验证的两个散列值。将哈希密码改为屏蔽的密码不允许访问 AMQ Broker 管理控制台。
broker.xml
、bootstrap.xml
、management.xml
和 login.config
支持屏蔽但未哈希的密码。
5.9.2. 在配置文件中加密密码
以下示例演示了如何在 broker.xml
配置文件中屏蔽 cluster-password
的值。
流程
在命令提示符中,使用
mask
工具加密密码:$ <broker_instance_dir>/bin/artemis mask <password>
result: 3a34fd21b82bf2a822fa49a8d8fa115d
打开 &
lt;broker_instance_dir> /etc/broker.xml
配置文件,其中包含您要屏蔽的纯文本密码:<cluster-password> <password> </cluster-password>
将纯文本密码替换为加密值:
<cluster-password> 3a34fd21b82bf2a822fa49a8d8fa115d </cluster-password>
使用标识符
ENC ()
嵌套加密值:<cluster-password> ENC(3a34fd21b82bf2a822fa49a8d8fa115d) </cluster-password>
配置文件现在包含加密的密码。由于密码附带 ENC ()
标识符,所以 AMQ Broker 在使用前会对其进行解密。
其他资源
- 有关 AMQ Broker 中包含的配置文件的更多信息,请参阅 第 1.1 节 “AMQ Broker 配置文件和位置”。
5.9.3. 设置 codec 密钥以加密和解密密码
需要使用 codec 来加密和解密密码。如果没有配置自定义 codec,则 mask
工具使用默认的 codec 来加密密码,AMQ Broker 使用相同的默认 codec 来解密密码。codec 使用默认密钥进行配置,它提供给底层加密算法来加密和解密密码。使用默认密钥可能会带来一个恶意的攻击者可能会使用的风险来解密您的密码。
当使用 mask
实用程序加密密码时,您可以指定自己的密钥字符串以避免使用默认的 codec 密钥。然后,您必须在 ARTEMIS_DEFAULT_SENSITIVE_STRING_CODEC_KEY
环境变量中设置相同的密钥字符串,以便代理可以解密密码。在环境变量中设置密钥使其更安全,因为它不会在配置文件中保留。另外,您可以在启动代理前立即设置密钥,并在代理启动后立即取消设置它。
流程
使用
mask
实用程序加密配置文件中的每个密码。对于key
参数,指定用于加密密码的字符串。使用相同的密钥字符串来加密每个密码。$ <broker_instance_dir>/bin/artemis mask --key <key> <password>
警告确保您保留在运行
mask
实用程序以加密密码时指定的密钥字符串记录。您必须在环境变量中配置相同的键值,以允许代理解密密码。有关在配置文件中加密密码的详情,请参考 第 5.9.2 节 “在配置文件中加密密码”。
在命令提示符中,将
ARTEMIS_DEFAULT_SENSITIVE_STRING_CODEC_KEY
环境变量设置为您在加密每个密码时指定的密钥字符串。$ export ARTEMIS_DEFAULT_SENSITIVE_STRING_CODEC_KEY= <key>
启动代理。
$ ./artemis run
取消设置
ARTEMIS_DEFAULT_SENSITIVE_STRING_CODEC_KEY
环境变量。$ unset ARTEMIS_DEFAULT_SENSITIVE_STRING_CODEC_KEY
注意如果在启动代理后取消设置
ARTEMIS_DEFAULT_SENSITIVE_STRING_CODEC_KEY
环境变量,您必须在每次后续时间启动代理前再次将其设置为相同的密钥字符串。
5.10. 配置身份验证和授权缓存
默认情况下,AMQ Broker 将成功身份验证和授权响应的信息存储在单独的缓存中。您可以更改每个缓存中允许的默认条目数,以及缓存条目的持续时间。
-
打开 &
lt;broker-instance-dir>/etc/broker.xml
配置文件。 要更改默认条目数
1000
个,在每个缓存中允许,设置authentication-cache-size
和authorization-cache-size
参数。例如:<configuration> ... <core> ... <authentication-cache-size>2000</authentication-cache-size> <authorization-cache-size>1500</authorization-cache-size> ... </core> ... </configuration>
注意如果缓存达到限制集,则最早使用的条目将从缓存中移除。
要更改默认持续时间
10000
毫秒,哪个条目被缓存,请设置security-invalidation-interval
参数。例如:<configuration> ... <core> ... <security-invalidation-interval>20000</security-invalidation-interval> ... </core> ... </configuration>
注意如果将
security-invalidation-interval
参数设置为0,
则禁用身份验证和授权缓存。
第 6 章 持久性消息数据
对于持久性( storing)消息数据,AMQ Broker 有两个选项。
或者,您还可以将代理配置为 不保留 任何消息数据。更多信息请参阅 第 6.3 节 “禁用持久性”。
代理使用不同的解决方案来保留消息日志之外的大量消息。请参阅 第 8 章 处理大量消息 了解更多信息。
代理也可以配置为在内存不足的情况下将信息记录到磁盘。请参阅 第 7.1 节 “配置消息分页” 了解更多信息。
有关 AMQ Broker 支持哪些数据库和网络文件系统的当前信息,请参阅红帽客户门户网站中的 Red Hat AMQ 7 支持的配置。
6.1. 在日志中保留消息数据
代理日志是在磁盘上一组 仅附加 的文件。每个文件预先创建到固定大小,最初填充了 padding。当消息传递操作在代理上执行时,记录会附加到日志的末尾。附加记录可让代理最小化磁盘头移动和随机访问操作,这些操作通常是磁盘上最慢的操作。当一个日志文件已满时,代理会创建一个新日志文件。
日志文件大小可以配置,尽量减小每个文件所使用的磁盘 cylinder 数。但是,现代磁盘拓扑比较复杂,代理无法控制该文件映射到的 cylinder。因此,日志文件大小很难精确控制。
代理使用的其他持久性相关功能有:
- 确定特定日志文件仍在使用中的 垃圾回收 算法。如果日志文件不再使用,代理可以回收该文件以重复使用。
- 从日志中删除死空间的压缩算法,并压缩数据。这会导致日志使用磁盘上较少的文件。
- 支持本地事务。
- 在使用 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)来更好地持久性性能。
无法与其他操作系统或早期版本的 Linux 内核一起使用 AIO 日志。
要使用 AIO 日志,您必须安装 Linux 异步 I/O 库(libaio
)。要安装 libaio
,请使用 yum
命令,如下所示:
yum install libaio
6.1.2. 配置基于日志的持久性
以下流程描述了如何查看代理用于基于日志持久性的默认配置。您可以根据需要使用此描述来调整配置。
打开 &
lt;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 的默认值是 3333333 纳秒(每秒 300 次)。AIO 的默认值为 50000 纳秒(即每秒 2000 次)。
journal-max-io
任意时间点上可以位于 IO 队列的最大写入请求数。如果队列已满,代理会阻止进一步写入,直到空间可用为止。
如果您使用 NIO,则该值应始终为
1
。如果您使用 AIO,并且此参数没有在配置中明确指定,则默认值为500
。
- 根据前面的描述,根据需要根据您的存储设备调整持久性配置。
其他资源
- 要了解可用于配置基于日志的持久性的所有参数,请参阅 附录 E, 消息传递日志配置元素。
6.1.3. 关于绑定日志
绑定日志用于存储与绑定相关的数据,如代理及其属性上部署的队列集合。它还存储数据,如 ID 序列计数器。
绑定日志始终使用 NIO,因为它通常是与消息日志相比的吞吐量。此日志上的文件前缀为 activemq-bindings
。每个文件也具有 .bindings
扩展,默认大小为 1048576 字节。
要配置绑定日志,请在 < broker_instance_dir> /etc/broker.xml
配置文件的 core
元素中包含以下参数。
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.3 节 “关于绑定日志”。
6.1.5. 配置日志保留
您可以配置 AMQ Broker,以保留创建的每个日志文件的副本。配置日志保留后,您可以在日志文件副本中重播消息,以将消息发送到代理。
6.1.5.1. 配置日志保留
您可以将 AMQ Broker 配置为在特定时间段内或达到存储限制或全部保留日志文件副本。
流程
-
打开 &
lt;broker_instance_dir> /etc/broker.xml
配置文件。 -
在
core
元素中,添加journal-retention-directory
属性。指定句点
或storage-limit
或两者来控制日志文件的保留。另外,为日志文件副本指定文件系统位置。以下示例将 AMQ Broker 配置为将日志文件副本保存在data/retention
目录中(7
天),或直到文件使用10GB
存储。
<configuration> <core> ... <journal-retention-directory period="7" unit="DAYS" storage-limit="10G">data/retention</journal-retention-directory> ... </core> </configuration>
周期
- 保留日志文件副本的时间周期。当时间段过期时,AMQ Broker 会删除任何超过指定时间的文件。
unit
-
要应用到保留周期的测量单元。默认值为
DAYS
。其他有效值为HOURS
、MINUTES
和SECONDS
。 目录
- 日志文件复制的文件系统位置。指定的目录相对于 < broker_instance_dir> 目录。
storage-limit
- 所有日志文件副本可以使用的最大存储。如果达到存储限制,代理会删除最旧的日志文件,以便为新的日志文件复制提供空间。设置存储限制是确保日志文件保留不会导致代理耗尽磁盘空间并关闭的有效方法。
6.1.5.2. 在日志文件复制中重播代理中存在的地址
如果要从日志文件副本重新显示的信息地址存在于 AMQ Broker 上,请使用以下步骤重新显示信息。您可以将消息重播到代理的原始地址或不同的地址。
流程
- 登录 AMQ 管理控制台。如需更多信息,请参阅 访问 AMQ 管理控制台。
- 在主菜单中,单击 Artemis。
- 在文件夹树中,单击 addresses 以显示地址列表。
- 单击 地址 选项卡。
- 在您要重播消息的地址的 Action 列中,单击 操作。
选择重播操作。
- 如果您希望重播操作搜索在所有日志文件中重播的消息,请点 replay (String,String) 操作。
- 如果您希望重播操作仅在特定时间段内创建的日志文件副本中搜索信息,请选择 replay (String,String, String,String) 操作。在 startScanDate 和 endScanDate 字段中,指定时间段。
指定 replay 选项。
- 在 target 字段中,指定要发送重播消息的代理上的地址。如果将此字段留空,则会将消息重新显示到代理的原始地址。
-
(可选)在 filter 字段中,指定一个字符串来重播与过滤器字符串匹配的消息。例如,如果消息具有 storeID 属性,您可以使用
storeID="1000"
的过滤器来重播存储 ID 值为 1000 的所有消息。如果没有指定过滤器,则扫描的日志文件副本中的所有信息都会重新显示到 AMQ Broker。
- 点 Execute。
其他资源
- 有关使用 AMQ 管理控制台的更多信息,请参阅使用 AMQ 管理控制台。
6.1.5.3. 在日志文件复制中重播从代理中删除的地址
如果要从日志文件副本中重播的信息地址已从 AMQ Broker 中删除,请使用以下步骤将信息重新显示到代理的不同地址。
流程
- 登录 AMQ 管理控制台。如需更多信息,请参阅 访问 AMQ 管理控制台。
- 在主菜单中,单击 Artemis。
- 在文件夹树中,点顶级服务器。
- 点 Operations 选项卡。
选择重播操作。
- 如果您希望重播操作搜索在所有日志文件中重播的消息,请点 replay (String,String,String) 操作。
- 如果您希望重播操作仅在特定时间段内创建的日志文件副本中搜索信息,请选择 replay (String,String,String,String) 操作。在 startScanDate 和 endScanDate 字段中,指定时间段。
指定 replay 选项。
- 在 address 字段中,指定要重播的消息地址。
- 在 target 字段中,指定要发送重播消息的代理上的地址。
-
(可选)在 filter 字段中,指定一个字符串来重播与过滤器字符串匹配的消息。例如,如果消息具有 storeID 属性,您可以使用
storeID="1000"
的过滤器来重播存储 ID 值为 1000 的所有消息。如果没有指定过滤器,则扫描的日志文件副本中的所有信息都会重新显示到 AMQ Broker。
- 点 Execute。
其他资源
- 有关使用 AMQ 管理控制台的更多信息,请参阅使用 AMQ 管理控制台。
6.1.6. 紧凑日志文件
AMQ Broker 包含一个压缩算法,它从日志中删除死空间并压缩数据,使其占用较少的磁盘空间。
以下子章节演示了如何:
6.1.6.1. 配置日志文件压缩
代理使用以下标准来确定何时开始压缩:
- 为日志创建的文件数量。
- 日志文件中的实时数据的百分比。
达到这两个条件的配置值后,压缩过程会解析日志并删除所有死记录。因此,日志包含较少的文件。
以下流程演示了如何为日志文件压缩配置代理。
流程
-
打开 &
lt;broker_instance_dir> /etc/broker.xml
配置文件。 在
core
元素中,添加journal-compact-min-files
和journal-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.6.2. 使用命令行界面运行压缩
以下流程演示了如何使用命令行界面(CLI)来压缩日志文件。
流程
作为 <
broker_instance_dir>
目录的所有者,停止代理。以下示例显示了用户amq-broker
。su - amq-broker cd <broker_instance_dir>/bin $ ./artemis stop
(可选)运行以下 CLI 命令以获取 data 工具的完整参数列表。默认情况下,该工具使用 <
broker_instance_dir> /etc/broker.xml 中的设置
。$ ./artemis help data compact.
运行以下 CLI 命令以压缩数据。
$ ./artemis data compact.
工具成功压缩数据后,重启代理。
$ ./artemis run
其他资源
- AMQ Broker 包括多个 CLI 命令来管理您的日志文件。如需更多信息,请参阅附录中的命令行工具。
6.1.7. 禁用磁盘写缓存
大多数磁盘都包含硬件写缓存。写缓存可以提高磁盘的明显性能,因为写入稍后写入磁盘。默认情况下,很多系统都启用了磁盘写缓存。这意味着,即使从操作系统同步后,数据也不能保证它实际已变为磁盘。因此,如果发生故障,则可能会丢失关键数据。
有些更昂贵的磁盘具有非易失性或电池支持的写缓存,这些缓存不一定在出现故障时丢失数据,但您应该对其进行测试。如果您的磁盘没有这样的功能,您应该确保禁用写缓存。请注意,禁用磁盘写缓存可能会对性能造成负面影响。
以下流程演示了如何在 Windows 上的 Linux 中禁用磁盘写缓存。
流程
-
在 Linux 上,要管理磁盘写入缓存设置,请使用
hdparm
(用于 IDE 磁盘)或sdparm
或sginfo
(用于 slirpSI/SATA 磁盘)。 - 在 Windows 上,要管理磁盘写入器缓存设置,请右键点击磁盘。选择 Properties。
6.2. 在数据库中保留消息数据
当您将消息数据存储在数据库中时,代理使用 Java 数据库连接 (DSL)连接将消息和绑定数据存储在数据库表中。表中的数据使用 AMQ Broker 日志编码进行编码。有关支持的数据库的详情,请查看红帽客户门户网站中的 Red Hat AMQ 7 支持的配置。
管理员可以根据机构更广泛的 IT 基础架构的要求,选择将消息数据存储在数据库中。但是,使用数据库可能会对消息传递系统性能造成负面影响。具体来说,通过 JDBC 将消息传递数据写入数据库表会为代理产生显著的性能开销。
6.2.1. 配置 JDBC 持久性
以下流程演示了如何配置代理,以将消息和绑定数据存储在数据库表中。
流程
-
将适当的 JDBC 客户端库添加到代理运行时。要做到这一点,将相关的
.jar
文件添加到 <broker_instance_dir>/lib
目录中。 -
打开 &
lt;broker_instance_dir> /etc/broker.xml
配置文件。 在
core
元素中,添加一个包含database-store
元素的store
元素。<configuration> <core> <store> <database-store> </database-store> </store> </core> </configuration>
在
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>BIND_TABLE</bindings-table-name> <message-table-name>MSG_TABLE</message-table-name> <large-message-table-name>LGE_TABLE</large-message-table-name> <page-store-table-name>PAGE_TABLE</page-store-table-name> <node-manager-store-table-name>NODE_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> <jdbc-max-page-size-bytes>100K</jdbc-max-page-size-bytes> </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 毫秒。
- jdbc-max-page-size-bytes
-
当 AMQ Broker 将消息保留到 JDBC 数据库时,每个页文件的最大大小(以字节为单位)。默认值为
102400
,其值为 100KB。您指定的值也支持字节表示法,如 "K" "MB" 和 "GB"。
6.2.2. 配置 JDBC 连接池
如果您已经为 JDBC 持久性配置了代理,代理使用 JDBC 连接将消息和绑定数据存储在数据库表中。
如果 JDBC 连接失败,并且提供在出现故障时没有活动连接活动(如数据库读取或写入),代理将保持运行并尝试重新建立数据库连接。为达到此目的,AMQ Broker 使用 JDBC 连接池。
通常,连接池 提供一组到指定数据库的打开连接,这些数据库可以在多个应用程序间共享。对于代理,如果代理和数据库之间的连接失败,代理会尝试使用与池不同的连接重新连接到数据库。池在代理接收前测试新连接。
以下示例演示了如何配置 JDBC 连接池。
如果您没有明确配置 JDBC 连接池,代理使用带有默认配置的连接池。默认配置使用现有 JDBC 配置中的值。如需更多信息,请参阅 默认连接池配置。
先决条件
- 这个示例基于配置 JDBC 持久性的示例构建。请查看 第 6.2.1 节 “配置 JDBC 持久性”
要启用连接池,AMQ Broker 使用 Apache Commons DBCP 软件包。在为代理配置 JDBC 连接池前,您应熟悉此软件包提供的内容。如需更多信息,请参阅:
流程
-
打开 &
lt;broker-instance-dir> /etc/broker.xml
配置文件。 在您之前为 JDBC 配置添加的
database-store
元素中,删除jdbc-driver-class-name
,jdbc-connection-url
,jdbc-user
,jdbc-password
, 参数。之后,您将把它们替换为对应的 DBCP 配置参数。注意如果您没有明确删除前面的参数,则在此流程中添加的对应 DBCP 参数将具有优先权。
在
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>
在新的
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 连接池,代理使用带有默认配置的连接池。表中描述了默认配置。
DBCP 配置参数 | 默认值 |
---|---|
|
现有 |
|
现有 |
|
现有 |
|
现有 |
|
|
|
|
只有在 没有客户端主动向代理发送信息时,重新连接才可以正常工作。如果尝试在重新连接过程中写入数据库表,代理会失败并关闭。
其他资源
- 有关 AMQ Broker 支持的数据库的详情,请查看红帽客户门户网站中的 Red Hat AMQ 7 支持的配置。
- 要了解 Apache Commons DBCP 软件包中所有可用的配置选项,请参阅 Apache Commons DBCP 配置参数。
6.3. 禁用持久性
在某些情况下,可能要求消息传递系统 不存储 任何数据。在这些情况下,您可以在代理中禁用持久性。
以下流程演示了如何禁用持久性。
流程
-
打开 &
lt;broker_instance_dir> /etc/broker.xml
配置文件。 在
core
元素中,将persistence-enabled
参数的值设置为false
。<configuration> <core> ... <persistence-enabled>false</persistence-enabled> ... </core> </configuration>
没有保留消息数据、绑定数据、大消息数据、重复 ID 缓存或分页数据。
第 7 章 为地址配置内存用量
AMQ Broker 透明支持包含数百万消息的大型队列,即使托管代理的机器使用有限的内存运行。
在这些情况下,可以随时将所有队列存储在内存中。为防止过量内存用量,您可以配置代理上每个地址允许的最大内存用量。另外,您可以将代理配置为在地址的内存用量达到配置的限制时执行以下操作之一:
- 页面信息
- 静默丢弃信息
- 丢弃消息并通知发送的客户端
- 阻止客户端发送消息
如果您在达到地址的最大内存用量时将代理配置为页面信息,您可以将特定地址的限值配置为:
- 限制用于页面传入消息的磁盘空间
- 限制代理在客户端就绪使用消息时代理从磁盘传输回内存的内存。
您还可以设置磁盘用量阈值,该阈值会覆盖所有配置的分页限制。如果达到磁盘用量阈值,代理会停止分页并阻止所有传入的信息。
使用事务时,代理可能会分配额外的内存来确保事务一致性。在这种情况下,代理报告的内存用量可能没有反映内存中使用的字节数。因此,如果您根据指定的最大内存用量将代理配置为页面、丢弃或阻止消息,则您不应该使用事务。
7.1. 配置消息分页
对于指定最大内存用量限制的任何地址,您还可以指定代理达到该用量限制时执行的操作。您可以配置的一个选项是 分页。
如果您配置分页选项,当达到地址的最大大小时,代理开始将该地址的消息存储在磁盘上,称为 页面文件。每个页面文件都有您可以配置的最大大小。您以这种方式配置的每个地址在文件系统中都有一个专用文件夹来存储页的信息。
在检查队列中的消息时,队列浏览器和消费者都可以通过页面文件进行导航。但是,使用非常特定过滤器的消费者可能无法消耗存储在页面文件中的消息,直到队列中的现有消息被首先被消耗。例如,假设消费者过滤器包含一个字符串表达式,如 "color='red'
"。如果满足此条件的消息遵循 100 万带有属性为 "color='blue'"
的属性,则消费者将无法消费此消息,直到首先消费了 "color='blue'"
。
当客户端就绪使用时,代理传输(即,depages)消息从磁盘变为内存中。当确认该文件中的所有消息时,代理会从磁盘中删除一个页面文件。
以下过程演示了如何配置消息分页。
7.1.1. 指定分页目录
以下流程演示了如何指定分页目录的位置。
流程
-
打开 &
lt;broker_instance_dir> /etc/broker.xml
配置文件。 在
core
元素中,添加paging-directory
元素。指定文件系统中分页目录的位置。<configuration ...> <core ...> ... <paging-directory>/path/to/paging-directory</paging-directory> ... </core> </configuration>
对于以后为分页配置的每个地址,代理会在您指定的分页目录中添加一个专用目录。
7.1.2. 为分页配置地址
以下流程演示了如何为分页配置地址。
先决条件
- 您应该熟悉如何配置地址和地址设置。更多信息请参阅 第 4 章 配置地址和队列。
流程
-
打开 &
lt;broker_instance_dir> /etc/broker.xml
配置文件。 对于您为匹配地址 或一组 地址配置的
address-setting
元素,请添加配置元素来指定最大内存用量并定义分页行为。例如:<address-settings> <address-setting match="my.paged.address"> ... <max-size-bytes>104857600</max-size-bytes> <max-size-messages>20000</max-size-messages> <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"。 max-size-messages
-
代理在为
address-full-policy
属性指定的操作前允许地址的最大消息数。默认值为 -1,这意味着没有消息限制。 page-size-bytes
-
分页系统上使用的每个页面文件的大小(以字节为单位)。默认值为
10485760
(即 10 MiB)。您指定的值还支持字节表示法,如 "K"、"MB" 和 "GB"。 address-full-policy
代理达到地址的最大大小时执行的操作。默认值为
PAGE
。有效值为:页面
- 代理将任何其他信息记录到磁盘。
DROP
- 代理静默丢弃任何进一步的信息。
FAIL
- 代理丢弃任何进一步的信息,并给客户端消息制作者发出异常。
BLOCK
- 客户端消息制作者在尝试发送进一步消息时阻止。
如果您为
max-size-bytes
和max-size-message
属性设置了限制,代理会在达到任何一个限制时执行为address-full-policy
属性指定的操作。在上例中,当内存中地址的总消息超过 20,000 或使用 104857600 字节时,代理会启动my.paged.address
地址的分页消息。下面介绍了上例中 没有显示 的其他分页配置元素。
page-sync-timeout
-
定期页面同步之间的时间(以纳秒为单位)。如果您使用异步 IO 日志(即
journal-type
在broker.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
属性指定的操作。
以下流程演示了如何配置全局分页大小。
先决条件
- 您应该熟悉如何为分页配置地址。更多信息请参阅 第 7.1.2 节 “为分页配置地址”。
流程
停止代理。
对于 Linux:
<broker_instance_dir>/bin/artemis stop
对于 Windows:
<broker_instance_dir>\bin\artemis-service.exe stop
-
打开 &
lt;broker_instance_dir> /etc/broker.xml
配置文件。 在
core
元素中,添加global-max-size
元素并指定一个值。例如:<configuration> <core> ... <global-max-size>1GB</global-max-size> <global-max-messages>900000</global-max-messages> ... </core> </configuration>
global-max-size
代理可用于所有地址的内存量(以字节为单位)。当达到这个限制时,代理会为与每个传入消息关联的地址执行为
address-full-policy
属性指定的操作。global-max-size
的默认值为托管代理的 Java 虚拟机(JVM)的最大内存的一半。global-max-size
的值以字节为单位,但也支持字节表示法(例如:"K"、"Mb"、"GB")。在前面的示例中,代理配置为在处理消息时使用最多 1GB 可用内存。
global-max-messages
允许所有地址的消息总数。当达到这个限制时,代理会为与每个传入消息关联的地址执行为
address-full-policy
属性指定的操作。默认值为 -1,这意味着没有消息限制。如果您为
global-max-size
和global-max-messages
属性设置了限制,代理会在达到任何一个限制时执行为address-full-policy
属性指定的操作。使用上例中的配置,代理会在内存中消息数量超过 900,000 或使用 1 GB 可用内存时启动分页消息。注意如果为单个地址设置的限制(使用
max-size-bytes
或max-size-message
属性),则在为global-max-size
或global-max-messages
属性设置的限制之前,代理将执行为该地址的address-full-policy
属性指定的操作。
启动代理。
对于 Linux:
<broker_instance_dir>/bin/artemis run
对于 Windows:
<broker_instance_dir>\bin\artemis-service.exe start
7.1.4. 在为特定地址分页过程中限制磁盘用量
您可以在停止为单个地址或一组地址分页传入的消息前限制代理可以使用的磁盘空间量。
流程
停止代理。
对于 Linux:
<broker_instance_dir>/bin/artemis stop
对于 Windows:
<broker_instance_dir>\bin\artemis-service.exe stop
-
打开 &
lt;broker_instance_dir> /etc/broker.xml
配置文件。 在
core
元素中,添加属性来根据磁盘使用情况或消息数量指定分页限制,并在达到任何限制时指定要执行的操作。例如:<address-settings> <address-setting match="match="my.paged.address""> ... <page-limit-bytes>10G</page-limit-bytes> <page-limit-messages>1000000</page-limit-messages> <page-full-policy>FAIL</page-full-policy> ... </address-setting> </address-settings>
page-limit-bytes
-
在代理执行
page-full-policy
属性指定的操作前,允许为地址分页传入的消息的最大大小(以字节为单位)。您指定的值支持字节表示法,如 "K"、"MB" 和 "GB"。默认值为 -1,这意味着没有限制。 page-limit-messages
-
在代理执行为
page-full-policy
属性指定的操作前,地址的最大传入消息数。默认值为 -1,这意味着没有消息限制。 page-full-policy
代理在
page-limit-bytes
或page-limit-messages
属性中设置的限制为地址达到时执行的操作。有效值为:DROP The broker 静默丢弃任何进一步的信息。
FAIL the broker 会丢弃任何进一步的信息并通知发送的客户端
在上例中,代理页面会为
my.paged.address
地址分页信息,直到使用了 10 GB 的磁盘空间或直到所有 100万条消息都被被分页为止。
启动代理。
对于 Linux:
<broker_instance_dir>/bin/artemis run
对于 Windows:
<broker_instance_dir>\bin\artemis-service.exe start
7.1.5. 控制页消息到内存中的流
如果将 AMQ Broker 配置为将信息页到磁盘,代理会读取页面的信息,并在客户端准备好使用消息时将消息传送到内存中。要防止消息消耗过量内存,您可以限制代理从磁盘传输到内存的每个地址所使用的内存。
如果客户端应用程序缺少太多消息待处理确认,代理不会在确认待处理消息前读取页面消息,这会导致代理上出现消息不足。
例如,如果将页面消息传输到内存(默认为 20MB)的限值被访问,则代理会在读取任何更多消息前等待来自客户端的确认。如果同时,客户端在向代理发送确认前等待接收足够消息(由客户端使用的批处理大小决定),代理会耗尽消息。
为避免不足,可以将控制页面消息传输的代理限制增加到内存中,或减少传递消息的数量。您可以通过确保客户端很快提交消息确认,或使用超时和提交确认(不从代理接收更多消息)来减少发送消息的数量。
您可以在 AMQ 管理控制台中看到在队列的 Delivering Count
和 Delivering Bytes
指标中传递消息的编号和大小。
流程
-
打开 &
lt;broker_instance_dir> /etc/broker.xml
配置文件。 -
对于您为匹配地址或一组地址配置的
address-settings
元素,请指定将页消息传送到内存中的限制。例如:
address-settings> <address-setting match="my.paged.address"> ... <max-read-page-messages>104857600</max-read-page-messages> <max-read-page-bytes>20MB</max-read-page-bytes> ... </address-setting> </address-settings>
max-read-page-messages
最大的信息数,代理可以根据地址从磁盘读取到内存中。默认值为 -1,这意味着没有限制。
max-read-page-bytes
最大大小(以字节为单位)代理可以从磁盘读取到每个地址的内存。默认值为 20MB。
如果您同时为 max-read-page-messages
和 max-read-page-bytes
属性指定限制,代理会在达到任何限制时停止读取消息。
7.1.6. 设置磁盘用量阈值
您可以设置磁盘用量阈值,如果达到时,会导致代理停止分页并阻止所有传入的信息。
流程
停止代理。
对于 Linux:
<broker_instance_dir>/bin/artemis stop
对于 Windows:
<broker_instance_dir>\bin\artemis-service.exe stop
-
打开 &
lt;broker_instance_dir> /etc/broker.xml
配置文件。 在
core
元素中,添加max-disk-usage
配置元素并指定一个值。例如:<configuration> <core> ... <max-disk-usage>80</max-disk-usage> ... </core> </configuration>
max-disk-usage
代理可以使用的可用磁盘空间的最大百分比。当达到这个限制时,代理会阻止传入的信息。默认值为
90
。在上例中,代理限制为使用百分之八十的可用磁盘空间。
启动代理。
对于 Linux:
<broker_instance_dir>/bin/artemis run
对于 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. 配置消息阻塞
以下流程演示了如何在给定地址达到您指定的最大大小限制时配置消息阻塞。
您只能为 Core、OpenWire 和 AMQP 协议配置消息阻塞。
7.3.1. 阻止内核和 OpenWire producer
以下流程演示了如何在给定地址达到您指定的最大大小限制时为 Core 和 OpenWire 消息制作者配置消息阻塞。
先决条件
- 您应该熟悉如何配置地址和地址设置。更多信息请参阅 第 4 章 配置地址和队列。
流程
-
打开 &
lt;broker_instance_dir> /etc/broker.xml
配置文件。 对于您为匹配地址 或一组 地址配置的
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 消息制作者配置消息阻塞。
先决条件
- 您应该熟悉如何配置地址和地址设置。更多信息请参阅 第 4 章 配置地址和队列。
流程
-
打开 &
lt;broker_instance_dir> /etc/broker.xml
配置文件。 对于您为匹配地址 或一组 地址配置的
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 producers 的进一步消息。
7.4. 了解多播地址的内存用量
当消息路由到绑定了多播队列的地址时,内存中只有一个消息副本。每个队列仅具有对邮件的引用。因此,只有引用消息 的所有 队列发送了相关的内存后,才会释放相关的内存。
在这种情况下,如果您有一个较慢的消费者,则整个地址可能会遇到负面影响。
例如,请考虑这种情况:
- 地址有十个队列,它使用 multicast 路由类型。
- 由于消费者的速度较慢,其中一个队列不会发送其消息。其他 9 个队列继续传递消息并为空。
- 消息继续到达地址。带有较慢消费者的队列继续累积对消息的引用,从而导致代理在内存中保留消息。
- 当达到地址的最大大小时,代理将开始页面信息。
在这种情况下,由于单一的消费者,所有 队列上的消费者都会强制使用页面系统的消息,需要额外的 IO。
其他资源
- 要了解如何配置流控制,以规范代理和生产者和消费者之间的数据流,请参阅 AMQ 核心协议 JMS 文档中的 流控制。
第 8 章 处理大量消息
客户端可能会发送可能会超过代理内部缓冲区大小的大型消息,从而导致意外错误。要防止这种情况,您可以在消息大于指定最小值时将代理配置为存储消息作为文件。以这种方式处理大型消息意味着代理不会在内存中保存消息。相反,您可以在磁盘或代理存储大型消息文件的数据库表中指定一个目录。
当代理将消息存储为大型消息时,队列会在大型消息目录或数据库表中保留对该文件的引用。
大型消息处理可用于核心协议、AMQP、OpenWire 和 STOMP 协议。
对于核心协议和 OpenWire 协议,客户端在其连接配置中指定最小大消息大小。对于 AMQP 和 STOMP 协议,您可以在代理配置中为每个协议定义的 acceptor 中指定最小大消息大小。
建议您不要使用不同的协议 来生成和使用大量消息。要做到这一点,代理可能需要执行消息的多个转换。例如,假设您想使用 AMQP 协议发送消息,并使用 OpenWire 接收消息。在这种情况下,代理必须首先读取大型消息的整个正文,并将其转换为使用核心协议。然后,代理必须执行另一个转换,这一次到 OpenWire 协议。比如这些信息转换,比如在代理中造成大量处理开销。
您为上述任何协议指定的最少大消息大小会受到系统资源的影响,如可用的磁盘空间量以及消息的大小。建议您使用多个值运行性能测试来确定适当的大小。
本节中的步骤演示了如何:
- 配置代理以存储大型信息
- 为 AMQP 和 STOMP 协议配置接受器,以进行大型消息处理
本节还链接到有关配置 AMQ 核心协议和 AMQ OpenWire JMS 客户端的其他资源,以用于大型消息。
8.1. 为大型消息处理配置代理
以下流程演示了如何在磁盘或代理存储大型消息文件的数据库表上指定目录。
流程
-
打开 &
lt;broker_instance_dir> /etc/broker.xml
配置文件。 指定您希望代理存储大型消息文件的位置。
如果您要在磁盘上存储大量消息,请在
core
元素中添加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
如果您要将大型消息存储在数据库表中,请将
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
。
其他资源
- 有关配置数据库存储的详情,请参考 第 6.2 节 “在数据库中保留消息数据”。
8.2. 为大型消息处理配置 AMQP 接受器
以下流程演示了如何配置 AMQP 接受程序来处理大于指定大小的 AMQP 消息作为大消息。
流程
打开 &
lt;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>
在默认的 AMQP acceptor (或您配置的另一个 AMQP acceptor)中,添加
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
的值,如果 acceptor 收到一个 AMQP 消息,其正文大于或等于 204800 字节(即 200 KB),代理会将消息存储为大消息。如果没有为此属性明确指定值,代理将使用默认值 102400 (即 100 KB)。
-
如果将
amqpMinLargeMessageSize
设置为 -1,则禁用对 AMQP 消息的大型消息处理。 -
如果代理收到一个持久性 AMQP 消息,它没有超过
amqpMinLargeMessageSize
的值,但超出消息传递日志缓冲区的大小(使用journal-buffer-size
配置参数指定),代理会将消息转换为大型核心协议消息,然后再将其存储在日志中。
8.3. 配置 STOMP acceptor 用于处理大量信息
以下流程演示了如何配置 STOMP acceptor 来处理大于指定大小的 STOMP 消息作为大消息。
流程
打开 &
lt;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>
在默认的 STOMP acceptor (或您配置的另一个 STOMP acceptor)中,添加
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 消息。根据 stompMinLargeMessageSize
的值,如果 acceptor 收到 STOMP 消息,其正文大于或等于 204800 字节(即 200 KB),代理会将消息存储为大消息。如果没有为此属性明确指定值,代理将使用默认值 102400 (即 100 KB)。
要为 STOMP 消费者发送大型消息,代理会在将消息发送到客户端前自动将消息从大消息转换为正常消息。如果压缩了大型消息,代理会在将其发送到 STOMP 客户端前解压缩它。
8.4. 大消息和 Java 客户端
Java 开发人员有两个选项,它们正在编写使用大量消息的客户端。
一个选择是使用 InputStream
和 OutputStream
的实例。例如,一个 FileInputStream
可用于发送从物理磁盘中的大文件中获取的消息。然后,接收器可以使用 FileOutputStream
将消息流传输到其本地文件系统中的位置。
另一种选择是直接流传输 JMS BytesMessage
或 StreamMessage
。例如:
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. connection Time-To-Live
因为客户端和服务器之间的网络连接可能会失败,然后重新上线,因此允许客户端重新连接,所以 AMQ Broker 会等待清理不活跃的服务器端资源。此等待周期称为生存时(TTL)。基于网络的连接的默认 TTL 为 60000
毫秒(1 分钟)。in-VM 连接的默认 TTL 是 -1,
这意味着代理永远不会在代理端超时连接。
在代理上配置 Time-To-Live
如果您不希望客户端指定自己的连接 TTL,您可以在代理端设置全局值。这可以通过在代理配置中指定 connection-ttl-override
元素来实现。
检查 TTL 违反情况的连接的逻辑在代理上定期运行,由 connection-ttl-check-interval
元素决定。
流程
通过添加
connection-ttl-override
配置元素并为 time-to-live 提供值来编辑 <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>
9.2. 禁用异步连接执行
代理端收到的大多数数据包都在 remoting
线程上执行。这些数据包代表短暂运行的操作,并且始终在远程
线程上执行,以提高性能。但是,有些数据包类型使用线程池执行,而不是使用远程
线程,这会增加较少的网络延迟。
使用线程池的数据包类型在下面列出的 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>
其他资源
- 要了解如何配置 AMQ Core Protocol JMS 客户端来检测死连接,请参阅 AMQ Core Protocol JMS 文档中的 Detecting dead 连接。
- 要了解如何在 AMQ 核心协议 JMS 客户端中 配置连接时间,请参阅 AMQ 核心协议 JMS 文档中的配置生存时间。
第 10 章 检测重复消息
您可以将代理配置为自动检测和过滤重复的消息。这意味着您不必实施自己的重复检测逻辑。
如果没有重复的检测,当意外连接失败时,客户端无法确定是否收到发送到代理的消息。在这种情况下,客户端可能会假设代理没有收到消息,并重新发送它。这会生成重复的消息。
例如,假设客户端向代理发送一条消息。如果在收到和 由代理处理消息前 代理或连接失败,则消息永远不会到达其地址。由于失败,客户端不会从代理接收响应。如果在收到并由代理处理消息 后 代理或连接失败,则会正确路由消息,但客户端仍然不会收到响应。
此外,使用事务来确定是否成功不一定会在这种情况下帮助。如果在处理事务提交时代理或连接失败,客户端仍无法确定它是否成功发送了消息。
在这些情况下,为了更正假定的失败,客户端会重新发送最新的消息。结果可能是对您的系统有负面影响的重复消息。例如,如果您在订购系统中使用代理,则重复的信息可能意味着处理订购顺序两次。
以下流程演示了如何配置重复的消息检测以防止这些类型的情况。
10.1. 配置重复的 ID 缓存
要启用代理来检测重复的消息,生产者必须在发送每个消息时为消息属性 _AMQ_DUPL_ID
提供唯一值。代理维护 _AMQ_DUPL_ID
属性接收的值的缓存。当代理收到地址上的新消息时,它会检查该地址的缓存,以确保之前还没有处理带有此属性相同值的消息。
每个地址都有自己的缓存。每个缓存的大小都是圆圈的,按大小进行修复。这意味着新条目会替换最旧的作为缓存空间需求。
以下流程演示了如何全局配置代理中的每个地址使用的 ID 缓存。
流程
-
打开 &
lt;broker_instance_dir> /etc/broker.xml
配置文件。 在
core
元素中,添加id-cache-size
和persist-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 Core Protocol JMS 客户端设置重复的 ID 消息属性,请参阅 AMQ Core Protocol JMS 客户端 文档中的使用重复消息检测。
10.2. 为集群连接配置重复的检测
您可以配置集群连接,为集群中移动的每个消息插入重复的 ID 标头。
先决条件
- 您应该已经配置了代理集群。如需更多信息,请参阅 第 14.2 节 “创建代理集群”。
流程
-
打开 &
lt;broker_instance_dir> /etc/broker.xml
配置文件。 在
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
,则消息 packet 继续。如果为 false
,则进程中止,则不会调用其他拦截器,并且消息数据包不会被进一步处理。
11.1. 创建拦截器
您可以创建自己的传入和传出拦截器。所有拦截器都是特定于协议的,分别针对输入或退出服务器的任何数据包调用。这样,您可以创建拦截器来满足审计数据包等业务需求。拦截器可以更改它们拦截器的数据包。这使得它们强大且可能存在危险,因此请务必谨慎使用它们。
拦截器及其依赖项必须放在代理的 Java 类路径中。您可以使用 < ;broker_instance_dir> /lib
目录,因为它默认为 classpath 的一部分。
流程
以下示例演示了如何创建一个拦截器来检查传递给它的每个数据包的大小。请注意,示例为每个协议实施特定的接口。
实施适当的接口并覆盖其拦截器
()
方法。如果使用 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; } }
如果您使用 mq 协议,请实施
org.apache.activemq.artemis.core.protocol.mqtt.mqInterceptor
接口。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. 将代理配置为使用拦截器
创建拦截器后,您必须配置代理以使用它。
先决条件
您必须创建一个拦截器类,并将其(及其依赖项)添加到代理的 Java 类路径中,然后才能进行配置以供代理使用。您可以使用 < ;broker_instance_dir> /lib
目录,因为它默认为 classpath 的一部分。
流程
通过在 <broker
_instance_dir> /etc/broker.xml
中添加配置,将代理配置为使用拦截器如果您的拦截器旨在用于传入消息,请将其
class-name
添加到remoting-incoming-interceptors
列表中。<configuration> <core> ... <remoting-incoming-interceptors> <class-name>org.example.MyIncomingInterceptor</class-name> </remoting-incoming-interceptors> ... </core> </configuration>
如果您的拦截器用于传出消息,请将其
class-name
添加到remoting-outgoing-interceptors
列表中。<configuration> <core> ... <remoting-outgoing-interceptors> <class-name>org.example.MyOutgoingInterceptor</class-name> </remoting-outgoing-interceptors> </core> </configuration>
其他资源
- 要了解如何在 AMQ 核心协议 JMS 客户端中配置 拦截器,请参阅 AMQ Core Protocol JMS 文档中的使用消息拦截器。
第 12 章 解除消息和分割消息流
在 AMQ Broker 中,您可以配置名为 diverts 的对象,以便您可以透明地将消息从一个地址分离到另一个地址,而无需更改任何客户端应用程序逻辑。您还可以配置 divert,将消息 的副本 转发到指定的转发地址,从而有效地分割消息流。
12.1. message diverts 的工作原理
离散的rts 可让您透明地将消息路由到一个地址到其他地址,而无需更改任何客户端应用程序逻辑。将代理服务器上的 disrts 集合视为消息的路由表类型。
breakrt 可以是 独占 的,表示消息被分解到指定的转发地址,而不进入其原始地址。
breakrt 也可以是 非独占 的,这意味着消息继续进入其原始地址,而代理会将消息的副本发送到指定的转发地址。因此,您可以使用非独占的 diverts 进行分割消息流。例如,如果要单独监控发送到订购队列的每个顺序,您可以分割消息流。
可以为单个地址配置多个 diverts。当地址同时配置了 exclusive 和 non-exclusive diverts 时,代理会首先处理 exclusive diverts。如果一个特定的消息已被一个 exclusive divert 解除了,代理不会处理该消息的任何非独占的 disrts。在这种情况下,消息永远不会进入原始地址。
当代理分离消息时,代理会分配一个新的消息 ID,并将消息地址设置为新的转发地址。您可以通过 _AMQ_ORIG_ADDRESS
(字符串类型)和 _AMQ_ORIG_MESSAGE_ID
(更多类型)消息属性来检索原始消息 ID 和地址值。如果您使用 Core API,请使用 Message.HDR_ORIGINAL_ADDRESS
和 Message.HDR_ORIG_MESSAGE_ID
属性。
您只能将消息同步到同一代理服务器上的地址。如果要区分到其他服务器上的地址,则常见的解决方案是首先将消息同步到本地存储和转发队列。然后,设置一个从该队列消耗的网桥,并将消息转发到不同代理上的地址。通过将 diverts 与网桥相结合,您可以在地理分布式代理服务器之间创建分布式路由连接网络。这样,您可以创建一个全局消息传递网格。
12.2. 配置消息 diverts
要在代理实例中配置一个 divert,在 broker.xml
配置文件的 core
元素中添加一个 divert
元素。
<core> ... <divert name= > <address> </address> <forwarding-address> </forwarding-address> <filter string= > <routing-type> </routing-type> <exclusive> </exclusive> </divert> ... </core>
- divert
-
一个 disrt 的命名实例。只要每个
divert
都有唯一的名称,您可以在broker.xml
配置文件中添加多个 divert 元素。 - address
- 从中分离 消息的地址
- forwarding-address
- 信息转发到的地址
- filter
- 可选消息过滤器。如果您配置了过滤器,则只有与过滤器字符串匹配的消息才会被分解。如果没有指定过滤器,则所有消息都会被视为 disrt 的匹配。
- routing-type
分散消息的路由类型。您可以将 divert 配置为:
-
将
anycast
或multicast
路由类型应用到消息 - 条带 (即删除)现有路由类型
- 传递 (即保留)现有路由类型
-
将
当消息已设置了路由类型时,路由类型的控制很有用,但您想要将消息分解成使用不同的路由类型的地址。例如,代理无法将 anycast
路由类型的消息路由到一个使用 multicast
的队列,除非您将 divert 的 routing-type
参数设置为 MULTICAST
。divert 的 routing-type
参数的有效值为 ANYCAST
、MULTICAST
、PASS
和 STRIP
。默认值为 STRIP
。
- exclusive
-
指定 divert 是否为 exclusive (将属性设置为
true
)还是非独占(将属性设置为false
)。
以下小节显示了 exclusive 和 non-clusive diverts 的配置示例。
12.2.1. 排除 divert 示例
下面是一个排除 divert 的示例配置。排除 divert 将原始配置的地址的所有匹配消息复制到新地址。匹配消息不会路由到原始地址。
<divert name="prices-divert"> <address>priceUpdates</address> <forwarding-address>priceForwarding</forwarding-address> <filter string="office='New York'"/> <exclusive>true</exclusive> </divert>
在前面的示例中,您定义了一个名为 price-divert
的 divert,它将发送到 priceUpdates
地址的任何消息转到另外一个本地地址 priceForwarding
。您还指定消息过滤器字符串。只有带有 office
属性以及值为 New York
的消息才会被 divert。所有其他消息都路由到其原始地址。最后,您可以指定 divert 是独占的。
12.2.2. Non-exclusive divert 示例
下面是一个非独占区分器的示例配置。在非独占区分程序中,消息将继续进入其原始地址,代理也会将消息的副本发送到指定的转发地址。因此,非独占区分是分割消息流的方法。
<divert name="order-divert"> <address>orders</address> <forwarding-address>spyTopic</forwarding-address> <exclusive>false</exclusive> </divert>
在上例中,您定义了一个名为 order-divert
的 divert,它会获取发送到地址 orders
的每个消息的副本,并将其发送到名为 spyTopic
的本地地址。您还可以指定 divert 不是排他的。
其他资源
有关使用 exclusive 和 non-clusive diverts 和桥接将消息转发到另一个代理的详细示例,请参阅 Divert Example (external)。
第 13 章 过滤消息
AMQ Broker 根据 SQL 92 表达式语法的子集提供强大的过滤器语言。过滤器语言使用与 JMS 选择器相同的语法,但预定义的标识符有所不同。下表列出了应用到 AMQ Broker 消息的标识符。
identifier | 属性 |
---|---|
AMQPriority |
消息的优先级。消息优先级是值为 |
AMQExpiration | 消息的过期时间。该值是一个长整数。 |
AMQDurable |
消息是否是 durable。该值是一个字符串。有效值为 |
AMQTimestamp | 创建消息的时间戳。该值是一个长整数。 |
AMQSize |
消息的 |
假设核心过滤器表达式中使用的任何其他标识符都假定是消息的属性。有关 JMS 消息选择器语法的文档,请参阅 Java EE API。
13.1. 配置队列以使用过滤器
您可以在 < broker_instance_dir> /etc/broker.xml
中配置的队列中添加过滤器。只有与过滤器表达式匹配的消息才会进入队列。
流程
将
filter
元素添加到所需的队列
,并包含您要应用的作为元素值的过滤器。在以下示例中,filterNEWS='certification'
添加到队列 TechnologyQueue
中。<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
,则 selector age > 18
不得匹配。这个限制限制 STOMP 客户端,因为它们只能使用 String 属性发送消息。
配置过滤器以将字符串转换为数字
要将 String 属性转换为数字类型,请将前缀 convert_string_expressions:
添加到 过滤器
的值。
流程
编辑
<broker_instance_dir>/etc/broker.xml
,为相关的filter
应用前缀convert_string_expressions:
。以下示例将过滤器
值从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.
前缀附加到消息注解中,如上例所示。
其他资源
- 有关代理应用到过期或未发送 AMQP 信息的注解和属性的更多信息,请参阅 第 4.14 节 “过期或未发送 AMQP 消息的注解和属性”。
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 (和 Core JMS)
- STOMP
- AMQP
配置 XML 解析器
默认情况下,Broker 使用的 XML 解析程序是 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
,并将信息发送到 OrderQueue
。Broker1
以轮循方式将信息转发到其他代理。连接到每个代理的 OrderConsumer
客户端会消耗消息。
图 14.1. 消息负载均衡
如果没有消息负载均衡,发送到 Broker1
的信息将保留在 Broker1
上,只有 OrderConsumer1
能够使用它们。
默认情况下,AMQ Broker 会自动加载信息,将第一个消息组分发到第一个代理,并将第二个消息组分发到第二个代理。代理启动的顺序决定了哪个代理为第一个代理,第二个代理,以此类推。
您可以配置:
- 集群,将消息负载均衡到具有匹配队列的代理。
- 集群,将消息负载均衡到具有与活跃消费者匹配的队列的代理。
- 集群不负载均衡,但要从没有消费者的任何消费者对没有消费者的队列进行重新发布消息。
- 从没有消费者的队列自动重新分发消息的地址。
其他资源
-
消息负载均衡策略配置有每个代理的以太网连接中的
message-load-balancing
属性。更多信息请参阅 附录 C, 集群连接配置元素。 - 有关重新发布消息的详情,请参考 第 14.4.2 节 “配置消息重新发布”。
14.1.2. 代理集群如何提高可靠性
代理集群实现高可用性和故障转移,从而比独立代理更可靠。通过配置高可用性,您可以确保客户端应用程序可以继续发送和接收消息,即使代理遇到失败事件。
通过高可用性,集群中的代理被分组到 live-backup 组中。live-backup 组由一个提供客户端请求的实时代理组成,以及等待被动替换 live 代理(如果失败)的一个或多个备份代理。如果发生故障,备份代理会替换 live-backup 组中的 live 代理,客户端重新连接并继续其工作。
14.1.3. 集群限制
当您在集群环境中使用 AMQ 代理时,会应用以下限制。
- 临时队列
- 在故障转移过程中,如果客户端具有使用临时队列的用户,则会自动重新创建这些队列。重新创建的队列名称与原始队列名称不匹配,这会导致消息重新发布失败,并可在现有的临时队列中保留消息。红帽建议您避免在集群中使用临时队列。例如,使用请求/回复模式的应用程序应该将固定队列用于 JMSReplyTo 地址。
14.1.4. 了解节点 ID
当代理实例的日志首次创建和初始化时,代理节点 ID 是一个全局唯一标识符(GUID)。节点 ID 存储在 server.lock
文件中。节点 ID 用于唯一标识代理实例,无论代理是独立实例还是集群的一部分。live-backup 代理对共享相同的节点 ID,因为它们共享相同的日志。
在代理集群中,代理实例(节点)相互连接,并创建网桥和内部 "store-and-forward" 队列。这些内部队列的名称基于其他代理实例的节点 ID。代理实例还监控集群广播,以了解与其自身匹配的节点 ID。如果日志标识了重复的 ID,代理会在日志中生成警告消息。
当您使用复制高可用性(HA)策略时,启动并把 check-for-live-server
设置为 true
的 master 代理会搜索使用节点 ID 的代理。如果 master 代理使用相同的节点 ID 找到另一个代理,则不会启动,或根据 HA 配置启动故障恢复。
节点 ID 是 危险 的,这意味着它在重启代理后保留。但是,如果您删除代理实例(包括其日志),则节点 ID 也会被永久删除。
其他资源
- 有关配置复制 HA 策略的更多信息,请参阅配置复制高可用性。
14.1.5. 常见代理集群拓扑
您可以连接代理来组成 对称 或 链 集群拓扑。您实施的拓扑取决于您的环境和消息传递要求。
对称集群
在对称集群中,每个代理都连接到所有其他代理。这意味着每个代理都没有多于一个来自其他代理的跃点。
图 14.2. 对称集群
对称集群中的每个代理了解集群中所有其他代理以及侦听这些队列的用户上存在的所有队列。因此,对称集群可以比链集群更优化地加载平衡和重新分发消息。
对称集群设置比链集群更容易设置,但它们很难在网络限制的环境中使用,从而防止代理被直接连接。
链集群
在链集群中,集群中的每个代理都不会直接连接到集群中的每个代理。相反,代理在链的每个末尾使用代理形成链,所有其他代理仅连接到链中的上一个和下一个代理。
图 14.3. 链集群
链集群设置比对称集群更困难,但在代理位于单独的网络中且无法直接连接时非常有用。通过使用链集群,中间代理可以间接连接两个代理,使消息可以在它们间流,即使两个代理没有直接连接。
14.1.6. 代理发现方法
Discovery 是集群中的代理将其连接详情传播到的机制。AMQ Broker 支持动态发现 和静态发现。
动态发现
集群中的每个代理都通过 UDP 多播或 JGroups 将其连接设置广播到其他成员。在这个方法中,每个代理都使用:
- 一个 广播组,用于将集群连接的信息推送到集群的其他潜在成员。
- 用于接收和存储集群中其他代理的集群的连接信息的 发现组。
静态发现
如果您无法在网络中使用 UDP 或 JGroups,或者要手动指定集群中的每个成员,您可以使用静态发现。在这个方法中,代理"加入"集群通过连接到第二个代理并发送其连接详情。然后,第二个代理将这些详情传播到集群中的其他代理。
14.1.7. 集群大小注意事项
在创建代理集群前,请考虑您的消息传递吞吐量、拓扑和高可用性要求。这些因素会影响集群中要包括的代理数量。
创建集群时,您可以通过添加和删除代理来调整大小。您可以在不丢失任何信息的情况下添加和删除代理。
消息传递吞吐量
集群应该包含足够的代理来提供您需要的消息吞吐量。集群中的更多代理,吞吐量越大。但是,大型集群可能无法管理。
Topology
您可以创建对称集群或链集群。您选择的拓扑类型会影响您可能需要的代理数量。
更多信息请参阅 第 14.1.5 节 “常见代理集群拓扑”。
高可用性
如果您需要高可用性(HA),请考虑在创建集群前选择 HA 策略。HA 策略会影响集群的大小,因为每个 master 代理应至少有一个从代理。
更多信息请参阅 第 14.3 节 “实现高可用性”。
14.2. 创建代理集群
您可以通过在应该参与集群中的每个代理上配置集群连接来创建代理集群。集群连接定义代理应该如何连接到其他代理。
您可以创建一个使用静态发现或动态发现的代理集群(UDP 多播或 JGroups)。
先决条件
您应该已确定代理集群的大小。
更多信息请参阅 第 14.1.7 节 “集群大小注意事项”。
14.2.1. 使用静态发现创建代理集群
您可以通过指定代理的静态列表来创建代理集群。如果您无法在网络上使用 UDP 多播或 JGroups,请使用这个静态发现方法。
流程
-
打开 &
lt;broker_instance_dir> /etc/broker.xml
配置文件。 在 <
;core&
gt; 元素中添加以下连接器:- 定义其他代理如何连接这个连接器
- 定义此代理如何连接到集群中的其他代理的一个或多个连接器
<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>
有关连接器的详情请参考 第 2.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
- 此代理可用于向集群中的另一个代理进行初始连接的一个或多个连接器。完成此初始连接后,代理将发现集群中的其他代理。只有集群使用静态发现时,您只需要配置此属性。
为集群连接配置任何其他属性。
这些额外的集群连接属性具有适合大多数常见用例的默认值。因此,如果您不希望默认行为,您只需要配置这些属性。更多信息请参阅 附录 C, 集群连接配置元素。
创建集群用户和密码。
AMQ Broker 附带默认集群凭证,但您应该更改它们以防止未授权的远程客户端使用这些默认凭证来连接代理。
重要在集群的每个代理中,集群密码必须相同。
<configuration> <core> ... <cluster-user>cluster_user</cluster-user> <cluster-password>cluster_user_password</cluster-password> ... </core> </configuration>
在每个附加代理上重复此步骤。
您可以将集群配置复制到每个额外代理。但是,不要复制任何其他 AMQ Broker 数据文件(如绑定、日志和大型消息目录)。这些文件在集群节点间必须是唯一的,否则集群不会被正确组成。
其他资源
-
有关使用静态发现的代理集群示例,请参阅 cluster
-static-discovery
AMQ Broker 示例程序。
14.2.2. 使用基于 UDP 的动态发现创建代理集群
您可以创建一个代理集群,代理通过 UDP 多播动态发现它们。
流程
-
打开 &
lt;broker_instance_dir> /etc/broker.xml
配置文件。 在 <
;core>
; 元素中,添加一个连接器。此连接器定义其他代理可用于连接到此连接的连接信息。此信息将在发现过程中发送到集群中的其他代理。
<configuration> <core> ... <connectors> <connector name="netty-connector">tcp://localhost:61617</connector> </connectors> ... </core> </configuration>
添加 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.255
中包含的类 D IP 地址。地址224.0.0.0
被保留,不可用。这是一个特定于 UDP 的属性。 group-port
- 用于广播的 UDP 端口号。这是一个特定于 UDP 的属性。
broadcast-period
(可选)- 连续广播之间的间隔(毫秒)。默认值为 2000 毫秒。
connector-ref
- 之前配置的集群连接器应该广播。
添加 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
属性为 discovery 组指定唯一名称。 local-bind-address
(可选)- 如果运行代理的机器使用多个网络接口,您可以指定发现组应侦听的网络接口。这是一个特定于 UDP 的属性。
group-address
-
要侦听的组多播地址。它应该与您要从中侦听的广播组中的
group-address
匹配。这是一个特定于 UDP 的属性。 group-port
-
多播组的 UDP 端口号。它应该与您要从中侦听的广播组中的
group-port
匹配。这是一个特定于 UDP 的属性。 refresh-timeout
(可选)发现组在从特定代理接收最后一次广播后等待的时间(毫秒),然后再从其列表中删除该代理的连接器对条目。默认值为 10000 毫秒(10 秒)。
把它设置为比广播组中的
broadcast-period
更高的值。否则,代理可能会定期从列表中消失,即使它们仍在广播(由于时间差异)。
创建集群连接并将其配置为使用动态发现。
默认情况下,集群连接将为对称拓扑中的所有地址负载平衡消息。
<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
- 此代理应该用来定位集群其他成员的发现组。只有集群使用动态发现时,您只需要配置此属性。
为集群连接配置任何其他属性。
这些额外的集群连接属性具有适合大多数常见用例的默认值。因此,如果您不希望默认行为,您只需要配置这些属性。更多信息请参阅 附录 C, 集群连接配置元素。
创建集群用户和密码。
AMQ Broker 附带默认集群凭证,但您应该更改它们以防止未授权的远程客户端使用这些默认凭证来连接代理。
重要在集群的每个代理中,集群密码必须相同。
<configuration> <core> ... <cluster-user>cluster_user</cluster-user> <cluster-password>cluster_user_password</cluster-password> ... </core> </configuration>
在每个附加代理上重复此步骤。
您可以将集群配置复制到每个额外代理。但是,不要复制任何其他 AMQ Broker 数据文件(如绑定、日志和大型消息目录)。这些文件在集群节点间必须是唯一的,否则集群不会被正确组成。
其他资源
-
有关使用 UDP 动态发现的代理集群配置示例,请参阅 cluster
-queue
AMQ Broker 示例程序。
14.2.3. 使用基于 JGroups 的动态发现创建代理集群
如果环境中已在环境中使用 JGroups,则可以使用它创建一个代理集群,代理会动态发现它们。
先决条件
必须安装并配置 JGroups。
有关 JGroups 配置文件的示例,请参阅
cluster-jgroups
AMQ Broker 示例程序。
流程
-
打开 &
lt;broker_instance_dir> /etc/broker.xml
配置文件。 在 <
;core>
; 元素中,添加一个连接器。此连接器定义其他代理可用于连接到此连接的连接信息。此信息将在发现过程中发送到集群中的其他代理。
<configuration> <core> ... <connectors> <connector name="netty-connector">tcp://localhost:61617</connector> </connectors> ... </core> </configuration>
在 <
;core&
gt; 元素中,添加一个 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
- 之前配置的集群连接器应该广播。
添加 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
属性为 discovery 组指定唯一名称。 JGroups-file
- 用于初始化 JGroups 频道的 JGroups 配置文件的名称。该文件必须位于 Java 资源路径中,以便代理可以加载它。
jgroups-channel
- 用于接收广播的 JGroups 频道的名称。
refresh-timeout
(可选)发现组在从特定代理接收最后一次广播后等待的时间(毫秒),然后再从其列表中删除该代理的连接器对条目。默认值为 10000 毫秒(10 秒)。
把它设置为比广播组中的
broadcast-period
更高的值。否则,代理可能会定期从列表中消失,即使它们仍在广播(由于时间差异)。
创建集群连接并将其配置为使用动态发现。
默认情况下,集群连接将为对称拓扑中的所有地址负载平衡消息。
<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
- 此代理应该用来定位集群其他成员的发现组。只有集群使用动态发现时,您只需要配置此属性。
为集群连接配置任何其他属性。
这些额外的集群连接属性具有适合大多数常见用例的默认值。因此,如果您不希望默认行为,您只需要配置这些属性。更多信息请参阅 附录 C, 集群连接配置元素。
创建集群用户和密码。
AMQ Broker 附带默认集群凭证,但您应该更改它们以防止未授权的远程客户端使用这些默认凭证来连接代理。
重要在集群的每个代理中,集群密码必须相同。
<configuration> <core> ... <cluster-user>cluster_user</cluster-user> <cluster-password>cluster_user_password</cluster-password> ... </core> </configuration>
在每个附加代理上重复此步骤。
您可以将集群配置复制到每个额外代理。但是,不要复制任何其他 AMQ Broker 数据文件(如绑定、日志和大型消息目录)。这些文件在集群节点间必须是唯一的,否则集群不会被正确组成。
其他资源
-
有关通过 JGroups 使用动态发现的代理集群示例,请参阅
cluster-jgroups
AMQ Broker 示例程序。
14.3. 实现高可用性
您可以通过实施高可用性(HA)来提高其可靠性,使代理集群能够继续运行,即使一个或多个代理离线也是如此。
实施 HA 涉及几个步骤:
- 为您的 HA 实现配置代理集群,如 第 14.2 节 “创建代理集群” 所述。
- 您应该了解什么是实时备份组,然后选择最适合您的要求的 HA 策略。请参阅 了解 HA 如何在 AMQ Broker 中工作。
当您选择了合适的 HA 策略时,在集群的每个代理上配置 HA 策略。请参阅:
- 将您的客户端应用程序配置为使用故障转移。
在稍后需要为高可用性配置代理集群进行故障排除时,建议您为集群中运行的每个 Java 虚拟机(JVM)实例启用 Garbage Collection (GC)日志记录。要了解如何在 JVM 上启用 GC 日志,请参阅 JVM 使用的 Java Development Kit (JDK)版本的官方文档。有关 AMQ Broker 支持的 JVM 版本的更多信息,请参阅 Red Hat AMQ 7 支持的配置。
14.3.1. 了解高可用性
在 AMQ Broker 中,您可以通过将集群中的代理分组到 live-backup 组 来实现高可用性(HA)。在 live-backup 组中,实时代理链接到备份代理,如果失败,它会接管实时代理。AMQ Broker 还为 live-backup 组中的故障转移(称为 HA 策略)提供了几种不同的策略。
14.3.1.1. live-backup 组如何提供高可用性
在 AMQ Broker 中,您可以通过将集群中的代理链接在一起来实现高可用性(HA),以形成 实时备份组。live-backup 组提供 故障转移,这意味着如果一个代理失败,另一个代理可以接管其消息处理。
live-backup 组由一个实时代理(有时也称为 主 代理)组成,链接到一个或多个备份代理(有时称为从代理)。live 代理提供客户端请求,而备份代理则以被动模式等待。如果 live 代理失败,备份代理会替换 live 代理,使客户端能够重新连接并继续其工作。
14.3.1.2. 高可用性策略
高可用性(HA)策略定义了在 live-backup 组中如何进行故障转移。AMQ Broker 提供多个不同的 HA 策略:
- 共享存储(推荐)
实时和备份代理将其消息传递数据存储在共享文件系统的通用目录中;通常是存储区域网络(SAN)或网络文件系统(NFS)服务器。如果您配置了基于 JDBC 的持久性,您还可以将代理数据存储在指定的数据库中。使用共享存储时,如果实时代理失败,备份代理会从共享存储加载消息数据,并接管失败的 live 代理。
在大多数情况下,您应该使用共享存储而不是复制。由于共享存储没有通过网络复制数据,因此它通常比复制提供更好的性能。共享存储还可避免网络隔离(也称为"脑裂")问题,这些问题实时代理及其备份同时变为实时。
- 复制
live 和 backup 代理在网络上持续同步其消息传递数据。如果 live 代理失败,备份代理会加载同步的数据,并接管失败的 live 代理。
live 和 backup 代理之间的数据同步可确保如果 live 代理失败,不会丢失消息传递数据。当 live 和 backup 代理最初接合在一起时,实时代理会通过网络将其所有现有的数据复制到备份代理中。完成此初始阶段后,实时代理会在实时代理接收时将持久数据复制到备份代理中。这意味着,如果 live 代理关闭网络,备份代理具有实时代理接收的所有持久数据。
由于复制通过网络同步数据,因此网络故障可能会导致实时代理及其备份同时变为实时的网络隔离。
- 只读(限制 HA)
当 live 代理安全停止时,它会将消息和事务状态复制到另一个实时代理中,然后关闭。然后,客户端可以重新连接到其他代理以继续发送和接收消息。
其他资源
- 有关 live-backup 组中代理间共享的持久性消息数据的更多信息,请参阅 第 6.1 节 “在日志中保留消息数据”。
14.3.1.3. 复制策略限制
当您使用复制来提供高可用性时,存在实时和备份代理可能会同时变为活跃的风险,这称为"脑裂"。
如果实时代理及其备份丢失其连接,则可能会出现脑裂。在这种情况下,实时代理及其备份可以同时激活。由于在这种情况下,代理之间没有消息复制,所以它们各自为客户端和进程消息提供服务,而无需其他知道它。在这种情况下,每个代理都有一个完全不同的日志。从这种情况中恢复可能比较困难,在某些情况下无法进行。
- 要 消除 脑裂的可能性,请使用 共享存储 HA 策略。
如果使用复制 HA 策略,请执行以下步骤来降低发生脑裂的风险。
如果您希望代理使用 ZooKeeper Coordination Service 来协调代理,请在至少三个节点上部署 ZooKeeper。如果代理丢失一个 ZooKeeper 节点,则至少有三个节点可确保当 live-backup 代理对出现复制中断时,大多数节点都可用协调代理。
如果要使用嵌入式代理协调,它使用集群中的其他可用代理提供仲裁投票,这可以减少(但不会完全消除)遇到脑裂的可能性(最少三个 live-backup 对)。至少使用三个 live-backup 对可确保大多数结果可以在实时备份代理对出现复制中断时在任何仲裁投票中实现。
使用复制 HA 策略时,介绍了一些额外的注意事项:
- 当 live 代理失败且备份转换为 live 时,在新的备份代理附加到 live 之前,不会进行进一步的复制,或者恢复到原始 live 代理。
- 如果 live-backup 组中的备份代理失败,则 live 代理将继续提供信息。但是,在将另一个代理添加为备份或原始备份代理重启前,消息才会复制。在此期间,信息只会保留实时代理。
- 如果代理使用嵌入式代理协调,且关闭 live-backup 对中的两个代理,以避免消息丢失,您必须首先重启最近活跃的代理。如果最近活跃的代理是备份代理,您需要手动将这个代理重新配置为 master 代理,以便首先重启代理。
14.3.3. 配置复制高可用性
您可以使用复制高可用性(HA)策略在代理集群中实现 HA。通过复制,持久性数据会在 live 和 backup 代理之间同步。如果实时代理遇到失败,消息数据会同步到备份代理中,并接管失败的实时代理。
如果您没有共享文件系统,您应该使用复制作为共享存储的替代选择。但是,复制可能会导致实时代理及其备份同时变为实时的场景。
由于实时和备份代理必须通过网络同步其消息传递数据,所以复制会增加性能开销。此同步过程会阻止日志操作,但不阻止客户端。您可以配置日志操作可以被阻止进行数据同步的最长时间。
如果 live-backup 代理对之间的复制连接中断,代理需要一种协调来确定实时代理是否仍然处于活跃状态,或者是否需要对备份代理进行故障转移。要提供此协调,您可以将代理配置为使用以下协调方法之一。
- Apache ZooKeeper 协调服务。
- 嵌入式代理协调,它使用集群中的其他代理来提供仲裁投票。
14.3.3.1. 选择协调方法
红帽建议您使用 Apache ZooKeeper 协调服务来协调代理激活。在选择协调方法时,了解基础架构要求的不同以及两个协调方法之间的数据一致性管理非常有用。
基础架构要求
- 如果使用 ZooKeeper 协调服务,您可以处理单个 live-backup 代理对。但是,您必须将代理连接到至少 3 个 Apache ZooKeeper 节点,以确保如果代理丢失到一个节点,则代理可以继续正常工作。要为代理提供协调的服务,您可以共享其他应用程序使用的现有 ZooKeeper 节点。有关设置 Apache ZooKeeper 的更多信息,请参阅 Apache ZooKeeper 文档。
- 如果要使用嵌入式代理协调,它使用集群中的其他可用代理来提供仲裁投票,您必须至少有三个 live-backup 代理对。至少使用三个 live-backup 对可确保在实时备份代理对遇到复制中断时,可在任何仲裁投票中达到大多数结果。
数据一致性
- 如果您使用 Apache ZooKeeper 协调服务,ZooK 会跟踪每个代理上的数据版本,因此只有具有最新日志数据的代理才能作为实时代理激活,无论代理是否配置为复制目的的主或备份代理。版本跟踪消除了代理可以使用最新日志激活并开始服务客户端的可能性。
- 如果您使用嵌入式代理协调,则不存在机制来跟踪每个代理上数据的版本,以确保只有具有最新日志的代理才能成为实时代理。因此,具有过时日志的代理可能会变为实时并启动服务客户端,这会导致日志中有区别。
14.3.3.2. 在复制中断后代理如何协调
本节介绍在复制连接中断后两个协调方法的工作方式。
使用 ZooKeeper 协调服务
如果您使用 ZooKeeper 协调服务来管理复制中断,则两个代理都必须连接到多个 Apache ZooKeeper 节点。
- 如果有任何时候,实时代理丢失了到大多数 ZooKeeper 节点的连接,它会关闭以避免出现"脑裂"的风险。
- 如果有任何时候,备份代理丢失了到大多数 ZooKeeper 节点的连接,它会停止接收复制数据,并等待它连接到大多数 ZooKeeper 节点,然后再再次作为备份代理。当连接恢复到大多数 ZooKeeper 节点时,备份代理将使用 ZooKeeper 来确定它是否需要丢弃其数据并搜索要复制的实时代理,或者是否可以成为其当前数据的实时代理。
ZooKeeper 使用以下控制机制来管理故障转移过程:
- 共享租期锁定,可以随时归单个实时代理所有。
- 跟踪代理数据的最新版本的激活序列计数器。每个代理都会在其服务器锁定文件中跟踪其日志数据的版本,以及它们的 NodeID。live 代理也在 ZooKeeper 上的协调激活序列计数器中共享其版本。
如果 live 代理和备份代理之间的复制连接丢失,则 live 代理会同时增加其本地激活序列计数器值,并在 ZooKeeper 上增加协调激活序列计数器值(1
)来公告它具有最新数据。备份代理的数据现在被视为过时,代理无法成为实时代理,直到复制连接被恢复并同步最新的数据。
复制连接丢失后,备份代理会检查 ZooKeeper 锁定是否归 live 代理所有,以及 ZooKeeper 上的协调激活序列计数器是否与其本地计数器值匹配。
- 如果锁定由 live 代理所有,备份代理会检测到 ZooKeeper 上的激活序列计数器在复制连接丢失时由 live 代理更新。这表示 live 代理正在运行,因此备份代理不会尝试故障转移。
- 如果锁定不是由 live 代理所有,则 live 代理不是实时的。如果备份代理上的激活序列计数器的值与 ZooKeeper 上的协调激活序列计数器值相同,这表示备份代理具有最新的数据,备份代理会失败。
- 如果锁定不是由 live 代理所有,但备份代理上的激活序列计数器的值小于 ZooKeeper 上的计数器值,则备份代理中的数据不会最新,备份代理无法失败。
使用嵌入式代理协调
如果 live-backup 代理对使用嵌入式代理协调来协调复制中断,则可以启动以下两种类型的仲裁投票。
vote 类型 | 描述 | initiator | 所需的配置 | 参与 | 基于投票结果的操作 |
---|---|---|---|---|---|
备份投票 | 如果备份代理丢失了与 live 代理的复制连接,备份代理会根据此投票结果决定是否启动。 | 备份代理 | 无。当备份代理丢失与其复制合作伙伴的连接时,备份投票会自动进行。 但是,您可以通过为这些参数指定自定义值来控制备份投票的属性:
| 集群中的其他实时代理 | 如果备份代理从集群中的其他实时代理收到大多数(即 仲裁)投票,则备份代理会启动,表示其复制合作伙伴不再可用。 |
实时投票 | 如果实时代理丢失与其复制合作伙伴的连接,则实时代理会根据此投票决定是否继续运行。 | live 代理 |
当实时代理丢失与复制合作伙伴的连接,并且 | 集群中的其他实时代理 | 如果没有从集群中的其他实时代理接收大多数投票,则 live 代理会关闭,这表示其集群连接仍处于活动状态。 |
下面是一些重要事项,请注意代理集群配置如何影响仲裁 voting 的行为。
- 要使仲裁投票成功,集群的大小必须允许大多数结果实现。因此,您的集群应 至少有三个 live-backup 代理对。
- 您添加到集群中的更多 live-backup 代理对,您可以提高集群的整体容错能力。例如,假设您有三个实时备份对。如果您丢失了完整的实时备份对,则剩余的两个 live-backup 对无法达到任何后续仲裁投票。这种情况意味着集群中任何进一步的复制中断都可能会导致实时代理关闭,并防止其备份代理启动。通过配置集群,假设五个代理对,集群至少可能会出现两个故障,同时仍确保大多数来自仲裁投票的结果。
- 如果您意外 减少 集群中的 live-backup 代理对数量,则之前为大多数投票建立的阈值不会自动减少。在此期间,由丢失复制连接触发的任何仲裁投票都无法成功,从而使集群更易受脑裂的影响。要使集群重新计算仲裁投票的最大阈值,首先请关闭您要从集群中删除的实时备份对。然后,重启集群中的剩余的 live-backup 对。当所有剩余的代理重启时,集群会重新计算仲裁投票阈值。
14.3.3.3. 使用 ZooKeeper 协调服务为代理集群配置复制
您必须在使用 Apache ZooKeeper 协调服务的 live-backup 对中为两个代理指定相同的复制配置。然后代理会协调,以确定哪个代理是主代理,它是备份代理。
先决条件
- 至少 3 个 Apache ZooKeeper 节点,以确保代理在丢失到一个节点的连接时可以继续运行。
- 代理机器具有类似的硬件规格,即您没有首选运行实时代理的机器,并在任何时间点上运行备份代理。
- ZooKeeper 必须有足够的资源,以确保暂停时间比 ZooKeeper 服务器选择时间要低。根据代理的预期负载,如果代理和 ZooKeeper 节点可以共享同一节点,请仔细考虑。如需更多信息,请参阅 https://zookeeper.apache.org/。
流程
-
为 live-backup 对中的两个代理打开
<broker_instance_dir> /etc/broker.xml
配置文件。 为对中的两个代理配置配置相同的复制配置。例如:
<configuration> <core> ... <ha-policy> <replication> <primary> <coordination-id>production-001</coordination-id> <manager> <properties> <property key="connect-string" value="192.168.1.10:6666,192.168.2.10:6667,192.168.3.10:6668"/> </properties> </manager> </primary> </replication> </ha-policy> ... </core> </configuration>
primary
- 将复制类型配置为 primary,以指示任一代理可以是主代理,具体取决于代理协调的结果。
coordination-id
-
为 live-backup 对中的两个代理指定一个通用字符串值。具有相同
Coordination-id
字符串的代理协调激活。在协调过程中,两个代理都使用Coordination-id
字符串作为节点 Id,并尝试在 ZooKeeper 中获取锁定。获取锁定且有最新数据的第一个代理作为实时代理启动,另一个代理则变为备份。 属性
指定
property
元素,您可以指定一组键值对来为 ZooKeeper 节点提供连接详情:键 值 connect-string
指定 ZooKeeper 节点的 IP 地址和端口号的逗号分隔列表。例如,
value="192.168.1.10:6666,192.168.2.10:6667,192.168.3.10:6668"。
session-ms
代理在丢失到大多数 ZooKeeper 节点的连接后等待的持续时间。默认值为
18000
ms。有效的值是在 ZooKeeper 服务器选择时间的 2 次和 20 倍之间。注意ZooKeeper 垃圾回收的暂停时间必须小于
session-ms
属性的值的 0.33,以便 ZooKeeper heartbeat 能够可靠地正常工作。如果无法确保暂停时间小于这个限制,请增加每个代理的session-ms
属性的值并接受较慢的故障切换。重要代理复制合作伙伴每 2 秒自动交换"ping"数据包,以确认合作伙伴代理可用。当备份代理没有从 live 代理收到响应时,备份会等待响应,直到代理的连接生存时间(ttl)过期。默认 connection-ttl 为
60000
ms,这意味着备份代理会在 60 秒后尝试失败。建议您将 connection-ttl 值设置为与session-ms
属性值类似的值,以便更快地进行故障转移。要设置新的 connection-ttl,请配置connection-ttl-override
属性。namespace (可选)
如果代理与其他应用程序共享 ZooKeeper 节点,您可以创建一个 ZooKeeper 命名空间来存储向代理提供协调服务的文件。您必须在 live-backup 对中为两个代理指定相同的命名空间。
为代理配置任何其他 HA 属性。
这些额外的 HA 属性具有适合大多数常见用例的默认值。因此,如果您不希望默认行为,您只需要配置这些属性。更多信息请参阅 附录 F, 其他复制高可用性配置元素。
- 重复步骤 1 到 3,在集群中配置每个额外的 live-backup 代理对。
其他资源
- 有关将复制用于 HA 的代理集群示例,请参阅 HA 示例程序。
- 有关节点 ID 的更多信息,请参阅了解节点 ID。
14.3.3.4. 使用嵌入式代理协调为复制高可用性配置代理集群
使用嵌入式代理协调复制至少需要三个实时备份对来减少(但不消除)"脑裂"的风险。
以下流程描述了如何为 6-broker 集群配置复制高可用性(HA)。在此拓扑中,6 个代理被分组到三个 live-backup 对中:三个实时代理都使用专用的备份代理来对。
先决条件
您必须有一个至少 6 个代理的代理集群。
6 个代理被配置为三个实时备份对。有关在集群中添加代理的详情,请参考 第 14 章 设置代理集群。
流程
将集群中的代理分组到 live-backup 组中。
在大多数情况下,live-backup 组应由两个代理组成:一个实时代理和一个备份代理。如果集群中有六个代理,则需要三个 live-backup 组。
创建由一个 live 代理和一个备份代理组成的第一个 live-backup 组。
-
打开 live 代理的 <
broker_instance_dir> /etc/broker.xml
配置文件。 配置 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 代理上将
check-for-live-server
设置为true
,则在上一个故障切换后重启 live 代理时可能会遇到重复的消息传递处理。特别是,如果您重启一个 live 代理,其此属性设为false
,则 live 代理不会将数据与其备份代理同步。在这种情况下,实时代理可能会处理备份代理已经处理的相同信息,从而导致重复。group-name
- 此 live-backup 组的名称(可选)。要形成 live-backup 组,必须使用相同的组名称配置 live 和 backup 代理。如果没有指定 group-name,备份代理可以使用任何 live 代理复制。
vote-on-replication-failure
此属性控制实时代理是否在发生中断复制连接时启动名为 live vote 的仲裁投票。
实时投票是一种实时代理来确定它还是合作伙伴是复制连接中断的原因。根据投票的结果,实时代理将保持运行或关闭。
重要要使仲裁投票成功,集群的大小必须允许大多数结果实现。因此,当您使用复制 HA 策略时,您的集群应 至少有三个 live-backup 代理对。
您在集群中配置的代理对越多,您可以提高集群的整体容错能力。例如,假设您有三个 live-backup 代理对。如果您丢失了到完整的实时备份对的连接,则剩余的两个实时备份对将不再实现仲裁投票。在这种情况下,任何后续复制中断都可能会导致实时代理关闭,并防止其备份代理启动。通过配置集群,假设五个代理对,集群至少可能会出现两个故障,同时仍确保大多数来自仲裁投票的结果。
为 live 代理配置任何其他 HA 属性。
这些额外的 HA 属性具有适合大多数常见用例的默认值。因此,如果您不希望默认行为,您只需要配置这些属性。更多信息请参阅 附录 F, 其他复制高可用性配置元素。
-
打开备份代理的 <
broker_instance_dir> /etc/broker.xml
配置文件。 将备份代理配置为使用复制进行 HA 策略。
<configuration> <core> ... <ha-policy> <replication> <slave> <allow-failback>true</allow-failback> <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 代理重新上线时,它将无法启动故障恢复,因为现在已经有备份的代理。
group-name
- 此 live-backup 组的名称(可选)。要形成 live-backup 组,必须使用相同的组名称配置 live 和 backup 代理。如果没有指定 group-name,备份代理可以使用任何 live 代理复制。
vote-on-replication-failure
此属性控制实时代理是否在发生中断复制连接时启动名为 live vote 的仲裁投票。已激活的备份代理被视为实时代理,并可启动实时投票。
实时投票是一种实时代理来确定它还是合作伙伴是复制连接中断的原因。根据投票的结果,实时代理将保持运行或关闭。
(可选)配置备份代理启动的仲裁投票的属性。
<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
- 此属性控制备份代理在每次仲裁投票重试之间等待的时间(以毫秒为单位)。
为备份代理配置任何其他 HA 属性。
这些额外的 HA 属性具有适合大多数常见用例的默认值。因此,如果您不希望默认行为,您只需要配置这些属性。更多信息请参阅 附录 F, 其他复制高可用性配置元素。
-
打开 live 代理的 <
对集群中的每个额外的 live-backup 组重复步骤 2。
如果集群中存在六个代理,请重复这个过程两次;每个剩余的 live-backup 组都会重复一次。
其他资源
- 有关将复制用于 HA 的代理集群示例,请参阅 HA 示例程序。
- 有关节点 ID 的更多信息,请参阅了解节点 ID。
14.3.4. 使用实时配置有限的高可用性
live-only HA 策略允许您在不丢失任何信息的情况下关闭集群中的代理。使用 live-only 时,当 live 代理安全停止时,它会将消息和事务状态复制到另一个实时代理,然后关闭。然后,客户端可以重新连接到其他代理以继续发送和接收消息。
live-only HA 策略仅在代理安全停止时处理情况。它无法处理意外的代理失败。
虽然实时 HA 会阻止消息丢失,但它可能无法保留消息顺序。如果停止配置了实时 HA 的代理,则其消息将被附加到另一个代理队列的末尾。
当代理准备缩减时,它会在其客户端断开连接前向客户端发送一条消息,然后再通知它们哪个新代理已准备好处理其消息。但是,只有在初始代理完成缩减后,客户端才应重新连接到新代理。这样可确保当客户端重新连接时,其他代理上可以使用任何状态,如队列或事务。客户端重新连接时应用正常的重新连接设置,因此您应该设置这些高功能来处理缩减所需的时间。
这个步骤描述了如何在集群中配置每个代理来缩减。完成此步骤后,每当代理安全停止时,它会将其消息和事务状态复制到集群中的另一个代理。
流程
-
打开第一个代理的 <
broker_instance_dir> /etc/broker.xml
配置文件。 将代理配置为使用 live-only HA 策略。
<configuration> <core> ... <ha-policy> <live-only> </live-only> </ha-policy> ... </core> </configuration>
配置缩减代理集群的方法。
指定此代理应该缩减的代理或代理组。
缩减为… 这些以下操作 集群中的特定代理
指定要缩减的代理的连接器。
<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>
- 对集群中的每个剩余的代理重复此步骤。
其他资源
- 有关使用 live-only 进行缩减集群的代理集群示例,请参阅 缩减示例程序。
14.3.5. 使用并置备份配置高可用性
您可以在与另一个实时代理相同的 JVM 中并置备份代理,而不是配置 live-backup 组。在此配置中,每个 live 代理都配置为请求另一个 live 代理,在其 JVM 中创建并启动备份代理。
图 14.4. 并置实时和备份代理
您可以将与共享存储或复制共存作为高可用性(HA)策略。新的备份代理从创建它的 live 代理继承其配置。备份的名称被设置为 colocated_backup_n
,其中 n
是实时代理创建的备份数。
另外,备份代理会继承其连接器的配置,并从创建它的 live 代理继承接受器。默认情况下,端口偏移 100 会应用到每个端口。例如,如果 live 代理具有端口 61616 的接受者,则创建的第一个备份代理将使用端口 61716,第二个备份将使用 61816 等。
日志、大消息和分页的目录会根据您选择的 HA 策略设置。如果选择共享存储,请求的代理会通知目标代理要使用的目录。如果选择了复制,目录会从创建代理继承,并将新备份的名称附加到它们。
此流程将集群中的每个代理配置为使用共享存储 HA,并请求备份来在集群中创建并与集群中的另一个代理在一起。
流程
-
打开第一个代理的 <
broker_instance_dir> /etc/broker.xml
配置文件。 将代理配置为使用 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
-
用于新备份代理的 acceptors 和 connector 的端口偏移。如果此代理收到为集群中的另一个代理创建备份的请求,它将按这个数量使用端口偏移创建备份代理。默认值为
100
。 excludes
(可选)-
从备份端口偏移中排除连接器。如果您已经为应该从备份端口偏移中排除的外部代理配置了任何连接器,请为每个连接器添加一个 <
;connector-ref
>。 master
- 此代理的共享存储或复制故障转移配置。
slave
- 此代理的备份的共享存储或复制故障转移配置。
- 对集群中的每个剩余的代理重复此步骤。
其他资源
- 有关使用并置备份的代理集群示例,请参阅 HA 示例程序。
14.3.6. 将客户端配置为故障转移
在代理集群中配置了高可用性后,您要将客户端配置为故障转移。客户端故障转移可确保如果代理失败,连接的客户端可以在最少的停机时间的情况下重新连接到集群中的另一个代理。
如果出现临时网络问题,AMQ Broker 会自动重新附加到同一代理的连接。这与故障转移类似,但客户端重新连接到同一代理。
您可以配置两种不同类型的客户端故障转移:
- 自动客户端故障切换
- 客户端在第一次连接时接收代理集群的信息。如果连接失败的代理失败,客户端会自动重新连接到代理的备份,备份代理会在故障切换前重新创建每个连接上存在的会话和消费者。
- 应用程序级别的客户端故障切换
- 作为自动客户端故障转移的替代选择,您可以在失败处理程序中使用您自己的自定义重新连接逻辑来编码客户端应用程序。
流程
使用 AMQ 核心协议 JMS 使用自动或应用程序级故障转移配置客户端应用程序。
如需更多信息,请参阅使用 AMQ 核心协议 JMS 客户端。
14.4. 启用消息重新发布
如果您的代理集群配置了 message-load-balancing
设置为 ON_DEMAND
或 OFF_WITH_REDISTRIBUTION
,您可以配置消息 重新发布 以防止消息在没有使用消息的队列中"stuck"。
本节包含有关以下内容的信息:
14.4.1. 了解重新发布消息
代理集群使用负载均衡来在集群中分发消息负载。在集群连接中配置负载均衡时,您可以使用以下 message-load-balancing
设置启用重新发布:
-
ON_DEMAND
- 启用负载平衡并允许重新发布 -
OFF_WITH_REDISTRIBUTION
- 禁用负载均衡,但允许重新发布
在这两种情况下,代理仅将消息转发到具有匹配消费者的其他代理。此行为可确保消息不会移到没有任何消费者使用消息的队列。但是,如果在消息转发到代理后连接到队列的消费者,这些消息就会在队列中变为"stuck",且没有消耗。这个问题有时被称为 starvation。
通过自动重新分发消息,从没有消费者到具有匹配消费者的集群中代理的队列中,消息重新发布可防止星号。
使用 OFF_WITH_REDISTRIBUTION
时,代理仅将消息转发到具有有效本地消费者的其他代理,允许您在消费者不可用时优先选择代理。
消息重新发布支持使用过滤器(也称为 选择器),即,当消息与可用本地消费者的选择器不匹配时会被重新分发。
其他资源
- 有关集群负载均衡的更多信息,请参阅 第 14.1.1 节 “代理集群如何平衡消息负载”。
14.4.2. 配置消息重新发布
此流程演示了如何通过负载平衡配置消息重新发布。如果您希望在没有负载均衡的情况下重新发布消息,请将 < ;message-load-balancing&
gt; 设置为 OFF_WITH_REDISTRIBUTION
。
流程
-
打开 &
lt;broker_instance_dir> /etc/broker.xml
配置文件。 在 &
lt;cluster-connection&
gt; 元素中,验证<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>
在 <
;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,
则信息将立即重新分发。但是,您应该在重新分发前设置延迟 - 消费者通常会关闭,但在同一个队列中快速创建另一个延迟。
- 对集群中的每个额外代理重复此步骤。
其他资源
-
有关重新分发消息的代理集群配置示例,请参阅
queue-message-redistribution
AMQ Broker 示例程序。
14.5. 配置集群消息分组
消息分组可让客户端发送特定类型的一组消息,以便由同一消费者按顺序处理。通过向集群中的每个代理添加分组处理器,您可以确保客户端可以将分组的消息发送到集群中的任何代理,并且仍以同一消费者正确顺序使用这些消息。
分组和集群技术总结如下:
- 消息分组对消息消耗施加一个顺序。在组中,必须完全消耗和确认每个消息,然后才能继续下一消息。这个方法会导致串行消息处理,其中 concurrency 不是一个选项。
- 集群旨在水平扩展代理,以提高消息吞吐量。通过添加额外的可同时处理消息的消费者来实现水平扩展。
由于这些技术相互冲突,因此请避免将集群和分组一起使用。
有两种分组处理程序:local handlers 和 remote handlers。它们可让代理集群将特定组中的所有消息路由到适当的队列,以便预期的消费者能够以正确顺序使用它们。
先决条件
集群中每个代理应至少有一个使用者。
当消息固定到队列上的消费者时,具有相同组 ID 的所有消息都将路由到该队列。如果删除了使用者,队列将继续接收消息,即使没有消费者。
流程
在集群中的一个代理上配置本地处理程序。
如果您使用高可用性,这应该是 master 代理。
-
打开代理的 <
broker_instance_dir> /etc/broker.xml
配置文件。 在 <
;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 转发到该队列。如果代理的路由提议被拒绝,它会拒绝一个备用路由,重复该过程,直到路由被接受为止。
-
打开代理的 <
如果您使用高可用性,请将本地处理程序配置复制到主代理的从代理中。
将本地处理器配置复制到从代理可防止本地处理器的单一故障点。
在集群的每个其余代理中,配置远程处理器。
-
打开代理的 <
broker_instance_dir> /etc/broker.xml
配置文件。 在 <
;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 毫秒。将此值设置为本地处理程序值的一半。
-
打开代理的 <
其他资源
-
有关为消息分组配置的代理集群示例,请参阅 cluster
-grouping
AMQ Broker 示例程序。
14.6. 将客户端连接到代理集群
您可以使用 AMQ JMS 客户端连接到集群。通过使用 JMS,您可以将消息传递客户端配置为动态或静态发现代理列表。您还可以配置客户端负载均衡,以在集群中的连接分发创建的客户端会话。
流程
使用 AMQ Core Protocol JMS 将您的客户端应用程序配置为连接到代理集群。
如需更多信息,请参阅使用 AMQ 核心协议 JMS 客户端。
14.7. 分区客户端连接
分区客户端连接涉及在每次客户端发起连接时将单个客户端路由到同一代理。
分区客户端连接的两个用例是:
- 对持久订阅的客户端进行分区,以确保订阅者始终连接到持久订阅者队列所在的代理。
- 通过可以将客户端整合到数据的来源(也称为数据 gravity)来最小化数据需求。
可运行的订阅
一个 durable 订阅在代理上以队列表示,并在持久订阅者首先连接到代理时创建。此队列保留在代理中,并接收消息,直到客户端取消订阅为止。因此,您希望客户端重复连接到同一代理,以使用订阅者队列中的消息。
要为危险订阅队列分区客户端,您可以在客户端连接中过滤客户端 ID。
Data gravity
如果您在不考虑数据抓取的情况下扩展环境中的代理数量,则一些性能优势将会丢失,因为需要在代理间移动消息。为了支持日期,您应该对客户端连接进行分区,以便客户端用户连接到生成所需消息的代理。
要对客户端连接进行分区,您可以过滤客户端连接的任何属性:
- 分配给连接用户的角色(ROLE_NAME)
- 用户的用户名(USER_NAME)
- 客户端的主机名(SNI_HOST)
- 客户端的 IP 地址(SOURCE_IP)
14.7.1. 对客户端连接进行分区,以支持永久订阅
要为持久化订阅分区客户端,您可以使用一致的哈希算法或正则表达式来过滤进入连接中的客户端 ID。
先决条件
客户端已配置,以便他们可以连接到集群中的所有代理,例如,使用负载均衡器或连接 URL 中配置的所有代理实例。如果代理拒绝连接,因为客户端详情与代理的分区配置不匹配,客户端必须能够连接到集群中的其他代理,以查找接受来自它连接的代理。
14.7.1.1. 使用一致的哈希算法过滤客户端 ID
您可以将集群中的每个代理配置为使用一致的哈希算法来哈希每个客户端连接中的客户端 ID。代理哈希客户端 ID 后,它会对散列值执行 modulo 操作,以返回一个整数值,用于标识客户端连接的目标代理。代理将返回的整数值与代理中配置的唯一值进行比较。如果存在匹配项,代理会接受连接。如果值不匹配,代理会拒绝连接。这个过程会在集群中的每个代理上重复,直到找到匹配项并且代理接受连接。
流程
-
为第一个代理打开 <
broker_instance_dir> /etc/broker.xml
配置文件。 创建
connection-routers
元素并创建connection-route
,以使用一致的哈希算法过滤客户端 ID。例如:<configuration> <core> ... <connection-routers> <connection-route name=”consistent-hash-routing”> <key>CLIENT_ID</target-key> <local-target-filter>NULL|0</local-target-filter> <policy name="CONSISTENT_HASH_MODULO"> <property key="modulo" value="<number_of_brokers_in_cluster>"> </property> </policy> </connection-route> </connection-routers> ... </core> </configuration>
connection-route
-
对于
connection-route 名称
,请为这个连接路由配置指定一个识别字符串。您必须将此名称添加到要应用一致的哈希过滤器的每个代理接受程序中。 key
-
要将过滤器应用到的键类型。要过滤客户端 ID,请在
key
字段中指定CLIENT_ID
。 local-target-filter
-
代理与 modulo 操作返回的整数值进行比较,以确定是否有匹配项,代理可以接受连接。示例中的
NULL|0
值为没有客户端 ID(NULL)的连接提供了匹配的连接,其中 modulo 操作返回的数量为0
。 policy
接受
modulo
属性键,它对哈希的客户端 ID 执行 modulo 操作,以识别目标代理。modulo
属性键的值必须与集群中的代理数量相同。重要策略名称必须是
CONSISTENT_HASH_MODULO
。
-
为第二个代理打开 <
broker_instance_dir> /etc/broker.xml
配置文件。 创建
connection-routers
元素并创建连接路由
,以使用一致的哈希算法过滤客户端 ID。在以下示例中,
local-target-filter
值NULL|1
为没有客户端 ID (NULL)的连接提供匹配,其中 modulo 操作返回的值为1
。<configuration> <core> ... <connection-routers> <connection-route name=”consistent-hash-routing”> <key>CLIENT_ID</target-key> <local-target-filter>NULL|1</local-target-filter> <policy name="CONSISTENT_HASH_MODULO"> <property key="modulo" value="<number_of_brokers_in_cluster>"> </property> </policy> </connection-route> </connection-routers> ... </core> </configuration>
- 重复此步骤,为集群中的每个附加代理创建一致的 hash 过滤器。
14.7.1.2. 使用正则表达式过滤客户端 ID
您可以通过将代理配置为将正则表达式过滤器应用到客户端连接中的客户端 ID 的一部分来对客户端连接进行分区。只有在正则表达式过滤器的结果与为代理配置的本地目标过滤器匹配时,代理才会接受连接。如果没有找到匹配项,代理会拒绝连接。这个过程会在集群中的每个代理上重复,直到找到匹配项并且代理接受连接。
先决条件
- 每个客户端 ID 中的通用字符串,它们可以通过正则表达式过滤。
流程
-
为第一个代理打开 <
broker_instance_dir> /etc/broker.xml
配置文件。 创建
connection-routers
元素并创建connection-route
来过滤客户端 ID 的一部分。例如:<configuration> <core> ... <connection-routers> <connection-route name=”regex-routing”> <key>CLIENT_ID</target-key> <key-filter>^.{3}</key-filter> <local-target-filter>NULL|CL1</local-target-filter> </connection-route> </connection-routers> ... </core> </configuration>
connection-route
-
对于
connection-route 名称
,请为此路由配置指定一个识别字符串。您必须将此名称添加到要应用正则表达式过滤器的每个代理接收器中。 key
-
要将过滤器应用到的键。要过滤客户端 ID,请在
key
字段中指定CLIENT_ID
。 key-filter
正则表达式应用到的客户端 ID 字符串部分,以提取键值。在上面的第一个代理示例中,代理提取一个键值,它是客户端 ID 的前 3 个字符。例如,如果客户端 ID 字符串为
CL100.consumer
,则代理提取键值CL1
。代理提取键值后,它会将其与local-target-filter
的值进行比较。如果进入的连接没有客户端 ID,或者代理无法使用为
key-filter
指定的正则表达式提取键值,则密钥值设置为 NULL。local-target-filter
-
代理与键值比较的值,以确定是否有匹配项,代理可以接受连接。上面的第一个代理示例中所示
NULL|CL1
的值匹配,匹配客户端 ID (NULL)或客户端 ID 中有 3 个字符前缀CL1
的连接。
-
为第二个代理打开 <
broker_instance_dir> /etc/broker.xml
配置文件。 创建
connection-routers
元素并创建连接路由
,以根据客户端 ID 的一部分过滤连接。在以下过滤器示例中,代理使用正则表达式提取客户端 ID 的前 3 个字符的键值。代理将
NULL
和CL2
的值与键值进行比较,以确定是否存在匹配项,代理是否可以接受连接。<configuration> <core> ... <connection-routers> <connection-route name=”regex-routing”> <key>CLIENT_ID</target-key> <key-filter>^.{3}</key-filter>