本章将介绍理解 Apache ActiveMQ Artemis 传输所需的概念,以及它们在何处以及如何配置。

1. 接受器

Apache ActiveMQ Artemis 传输中最重要概念之一是接受器。让我们直接深入研究并查看在配置文件 broker.xml 中以 XML 定义的接受器。

<acceptor name="netty">tcp://127.0.0.1:61617</acceptor>

接受器始终在 acceptors 元素内定义。可以在 acceptors 元素中定义一个或多个接受器。每个服务器的接受器数量没有上限。

每个接受器都定义了一种与 Apache ActiveMQ Artemis 服务器建立连接的方式。

在上面的示例中,我们正在定义一个使用 Netty 在端口 61617 上监听连接的接受器。

acceptor 元素包含一个 URL,用于定义要创建的接受器类型及其配置。URLschema 部分定义了接受器类型,可以是 tcpvm,分别代表 Netty 或内存内接受器。对于 NettyURL 的主机和端口定义了 acceptor 将绑定到的主机和端口。对于内存内接受器,URLAuthority 部分定义了唯一的服务器 ID。

acceptor 还可以配置为使用一组键值对来配置特定传输,有效键值对集取决于要使用的特定传输,并直接传递到底层传输。这些键值对作为查询的一部分设置在 URL 上,如下所示

<acceptor name="netty">tcp://127.0.0.1:61617?sslEnabled=true;keyStorePath=/path</acceptor>

2. 连接器

接受器用于服务器上定义如何接受连接,而连接器用于定义如何连接到服务器。

让我们看看在 broker.xml 文件中定义的连接器

<connector name="netty">tcp://127.0.0.1:61617</connector>

连接器可以在 connectors 元素内定义。可以在 connectors 元素中定义一个或多个连接器。每个服务器的连接器数量没有上限。

当服务器本身充当客户端时,将使用 connector,例如:

  • 当一个服务器桥接到另一个服务器时

  • 当服务器参与集群时

在这些情况下,服务器需要知道如何连接到其他服务器。这由 connectors 定义。

3. 直接从客户端配置传输

我们如何使用核心 ClientSessionFactory 配置与服务器建立连接所需的信息?

连接器还用于在配置核心 ClientSessionFactory 以直接与服务器通信时间接使用。虽然在这种情况下不需要在服务器端配置中定义此类连接器,但我们只需指定相应的 URI 即可。

以下是如何创建一个 ClientSessionFactory 的示例,该示例将直接连接到本章前面定义的接受器,它使用标准 Netty TCP 传输,并将尝试在端口 61617 上连接到 localhost(默认值)

ServerLocator locator = ActiveMQClient.createServerLocator("tcp://127.0.0.1:61617");

ClientSessionFactory sessionFactory = locator.createSessionFactory();

ClientSession session = sessionFactory.createSession(...);

同样,如果您使用的是 JMS,您可以在客户端直接配置 JMS 连接工厂

ConnectionFactory connectionFactory = new ActiveMQConnectionFactory("tcp://127.0.0.1:61617");

Connection jmsConnection = connectionFactory.createConnection();

4. 配置 Netty 传输

默认情况下,Apache ActiveMQ Artemis 当前使用 Netty,这是一个高性能低级别网络库。

我们的 Netty 传输可以通过多种方式配置;使用简单的 TCP 套接字、SSL,或通过 HTTP 或 HTTPS 建立隧道。

我们相信这可以满足绝大多数传输需求。

4.1. 单端口支持

Apache ActiveMQ Artemis 支持使用单个端口用于所有协议,Apache ActiveMQ Artemis 将自动检测正在使用的协议 CORE、AMQP、STOMP、MQTT 或 OPENWIRE,并使用相应的 Apache ActiveMQ Artemis 处理程序。它还将检测是否正在使用 HTTP 或 Web Sockets 等协议,并使用相应的解码器。Web Sockets 支持 AMQP、STOMP 和 MQTT。

可以使用接受器上的 protocols 参数来限制支持的协议,如下所示

<acceptor name="netty">tcp://127.0.0.1:61617?protocols=CORE,AMQP</acceptor>

4.2. 配置 Netty TCP

Netty TCP 是一种简单的基于未加密 TCP 套接字的传输。如果您在不可信网络上运行连接,请记住此传输未加密。您可能需要查看 SSL 或 HTTPS 配置。

在使用 Netty TCP 传输时,所有连接都从客户端发起(即服务器不会向客户端发起任何连接)。这适用于通常只允许在一个方向上发起连接的防火墙策略。

所有用于 Netty 的 tcp URL 方案的有效键都在类 org.apache.activemq.artemis.core.remoting.impl.netty.TransportConstants 中定义。大多数参数可以与接受器或连接器一起使用,有些参数只能与接受器一起使用。以下参数可用于为简单 TCP 配置 Netty

hostport 参数仅在核心 API 中使用,在 XML 配置中,这些参数在 URI 主机和端口中设置。

host

这指定了要连接到的主机名或 IP 地址(配置连接器时)或要监听的地址(配置接受器时)。此属性的默认值为 localhost。配置接受器时,可以通过逗号分隔来指定多个主机名或 IP 地址。也可以指定 0.0.0.0 以接受来自所有主机网络接口的连接。在指定连接器的主机时,不允许指定多个地址;连接器与一个特定地址建立连接。

不要忘记指定主机名或 IP 地址!如果您希望服务器能够接受来自其他节点的连接,则必须指定一个主机名或 IP 地址,在该地址上接受器将绑定并监听传入的连接。默认值为 localhost,当然这无法从远程节点访问!

port

这指定了要连接到的端口(配置连接器时)或要监听的端口(配置接受器时)。此属性的默认值为 61616

tcpNoDelay

如果这是 true,则将禁用 Nagle 算法。这是一个 Java(客户端)套接字选项。此属性的默认值为 true

tcpSendBufferSize

此参数确定 TCP 发送缓冲区的大小(以字节为单位)。此属性的默认值为 32768 字节(32KiB)。

TCP 缓冲区大小应根据网络的带宽和延迟进行调整。这里有一个很好的链接解释了背后的理论 this.

总之,TCP 发送/接收缓冲区大小应计算为

buffer_size = bandwidth * RTT.

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

对于高速网络,您可能希望将缓冲区大小从默认值增加。

tcpReceiveBufferSize

此参数确定 TCP 接收缓冲区的大小(以字节为单位)。此属性的默认值为 32768 字节(32KiB)。

writeBufferLowWaterMark

此参数确定 Netty 写缓冲区的低水位线。一旦写入缓冲区中排队的字节数超过高水位线,然后降至该值以下,Netty 的通道将再次开始可写。此属性的默认值为 32768 字节(32KiB)。

writeBufferHighWaterMark

此参数确定 Netty 写缓冲区的高水位线。如果写入缓冲区中排队的字节数超过此值,Netty 的通道将开始不可写。此属性的默认值为 131072 字节(128KiB)。

batchDelay

在将数据包写入传输之前,可以将 Apache ActiveMQ Artemis 配置为最多将写入批处理 batchDelay 毫秒。这可以提高非常小的消息的整体吞吐量。这样做是以增加消息传输的平均延迟为代价的。此属性的默认值为 0 毫秒。

directDeliver

当消息到达服务器并传递给等待的消费者时,默认情况下,传递在与消息到达的线程相同的线程上完成。这在具有相对较小的消息和少量消费者的环境中提供了良好的延迟,但以整体吞吐量和可扩展性为代价 - 特别是在多核机器上。如果您希望延迟最低,并且可能降低吞吐量,那么可以使用 directDeliver 的默认值(即 true)。如果您愿意在延迟方面接受一些额外的小损失,但希望获得最高的吞吐量,请将 directDeliver 设置为 false

nioRemotingThreads

此属性已弃用。它被 remotingThreads 替换,如果您正在使用此属性,请更新您的配置。

remotingThreads

默认情况下,Apache ActiveMQ Artemis 将使用与 Runtime.getRuntime().availableProcessors() 报告的核心数(或超线程数)三倍的线程数来处理传入的数据包。如果您想覆盖此值,可以通过指定此参数来设置线程数。此参数的默认值为 -1,这意味着使用来自 Runtime.getRuntime().availableProcessors() * 3 的值。

localAddress

配置 Netty 连接器时,可以指定客户端连接到远程地址时将使用的本地地址。这通常在应用程序服务器中或运行嵌入式时使用,以控制用于出站连接的地址。如果未设置本地地址,则连接器将使用任何可用的本地地址。

localPort

配置 Netty 连接器时,可以指定客户端连接到远程地址时将使用的本地端口。这通常在应用程序服务器中或运行嵌入式时使用,以控制用于出站连接的端口。如果使用本地端口的默认值,即 0,则连接器将让系统选择一个临时端口。有效端口为 0 到 65535

connectionsAllowed

此设置仅对 acceptor 有效。它限制 acceptor 允许的连接数。当达到此限制时,一条 DEBUG 级别的消息将被发送到日志,并且连接将被拒绝。使用的客户端类型将决定连接被拒绝时会发生什么。对于 `core` 客户端,它将导致 `org.apache.activemq.artemis.api.core.ActiveMQConnectionTimedOutException` 错误。默认值为 -1(无限制)。

handshake-timeout

防止未经授权的客户端打开大量连接并保持连接打开。由于每个连接都需要一个文件句柄,因此这会消耗资源,而这些资源将无法用于其他客户端。连接被认证后,将执行有关资源消耗的常规规则。默认值为 10 秒。每个整数都是有效值。当设置值为零或负整数时,此功能将被关闭。更改值需要重新启动服务器才能生效。

autoStart

确定 acceptor 在 broker 启动时是否自动启动。默认值为 `true`。

4.3. 配置 Netty 原生传输

Netty 原生传输支持存在于某些操作系统平台上。这允许 Apache ActiveMQ Artemis 使用原生套接字/IO 而不是 Java NIO。

这些原生传输添加了特定于特定平台的功能,生成更少的垃圾,并且与基于 Java NIO 的传输相比,通常可以提高性能。

客户端和服务器都可以从这种传输中获益。

当前支持的平台。

  • 运行 64 位 JVM 的 Linux

  • 运行 64 位 JVM 的 macOS

如果检测到支持的平台,Apache ActiveMQ Artemis 默认情况下将启用相应的原生传输。

如果在不支持的平台上运行,或者在加载原生库时遇到任何问题,Apache ActiveMQ Artemis 将回退到 Java NIO。

4.3.1. Linux 原生传输

在支持的 Linux 平台上,使用 Epoll,@see https://en.wikipedia.org/wiki/Epoll

以下属性特定于此原生传输

useEpoll

如果检测到支持的 Linux 平台运行 64 位 JVM,则启用 epoll 的使用。将其设置为 `false` 将强制使用 Java NIO 而不是 epoll。默认值为 `true`

4.3.2. macOS 原生传输

在支持的 macOS 平台上,使用 KQueue,@see https://en.wikipedia.org/wiki/Kqueue

以下属性特定于此原生传输

useKQueue

如果检测到支持的 macOS 平台运行 64 位 JVM,则启用 kqueue 的使用。将其设置为 `false` 将强制使用 Java NIO 而不是 kqueue。默认值为 `true`

4.4. 配置 Netty SSL

Netty SSL 类似于 Netty TCP 传输,但它通过使用安全套接字层 SSL 加密 TCP 连接来提供额外的安全性。

有关使用 Netty SSL 的完整工作示例,请参阅 示例

Netty SSL 使用与 Netty TCP 相同的所有属性,但添加了以下附加属性

sslContext

一个可选的缓存键,仅在 `org.apache.activemq.artemis.core.remoting.impl.ssl.CachingSSLContextFactory` 处于活动状态时进行评估,用于缓存最初创建的 SSL 上下文并重用它。如果未指定,CachingSSLContextFactory 将根据给定的密钥库/信任库参数自动计算缓存键。有关更多详细信息,请参阅 配置 SSLContextFactory

sslEnabled

必须为 `true` 才能启用 SSL。默认值为 `false`。

sslAutoReload

必须为 `true` 才能使 broker “监视” acceptor 的 keyStorePath 和/或 trustStorePath,并在更新时调用 reload()。监视周期由 配置重新加载功能 控制。默认值为 `false`。

keyStorePath

在 `acceptor` 上使用时,这是服务器上 SSL 密钥库的路径,该密钥库包含服务器的证书(无论是自签名还是由授权机构签名)。

在 `connector` 上使用时,这是客户端 SSL 密钥库的路径,该密钥库包含客户端证书。这仅在您使用双向 SSL(即相互认证)时与 `connector` 相关。尽管此值是在服务器上配置的,但它会被下载并在客户端使用。如果客户端需要使用与服务器上设置的路径不同的路径,则可以通过使用常用的“javax.net.ssl.keyStore”系统属性或 ActiveMQ 特定的“org.apache.activemq.ssl.keyStore”系统属性来覆盖服务器端设置。如果客户端上的另一个组件已经在使用标准 Java 系统属性,则 ActiveMQ 特定的系统属性很有用。

keyStorePassword

在 `acceptor` 上使用时,这是服务器端密钥库的密码。

在 `connector` 上使用时,这是客户端密钥库的密码。这仅在您使用双向 SSL(即相互认证)时与 `connector` 相关。尽管此值可以在服务器上配置,但它会被下载并在客户端使用。如果客户端需要使用与服务器上设置的密码不同的密码,则可以通过使用常用的“javax.net.ssl.keyStorePassword”系统属性或 ActiveMQ 特定的“org.apache.activemq.ssl.keyStorePassword”系统属性来覆盖服务器端设置。如果客户端上的另一个组件已经在使用标准 Java 系统属性,则 ActiveMQ 特定的系统属性很有用。

keyStoreType

正在使用的密钥库类型。例如,`JKS`、`JCEKS`、`PKCS12`、`PEM` 等。此值也可以通过“javax.net.ssl.keyStoreType”系统属性或 ActiveMQ 特定的“org.apache.activemq.ssl.keyStoreType”系统属性设置。如果客户端上的另一个组件已经在使用标准 Java 系统属性,则 ActiveMQ 特定的系统属性很有用。默认值为 `JKS`。

keyStoreProvider

用于密钥库的提供者。例如,`SUN`、`SunJCE` 等。此值也可以通过“javax.net.ssl.keyStoreProvider”系统属性或 ActiveMQ 特定的“org.apache.activemq.ssl.keyStoreProvider”系统属性设置。如果客户端上的另一个组件已经在使用标准 Java 系统属性,则 ActiveMQ 特定的系统属性很有用。默认值为 `null`。

keyStoreAlias

在 `acceptor` 上使用时,这是从 SSL 密钥库(通过 `keyStorePath` 指定)中选择的别名,以在客户端连接时呈现给客户端。

在 `connector` 上使用时,这是从 SSL 密钥库(通过 `keyStorePath` 指定)中选择的别名,以在客户端连接到服务器时呈现给服务器。这仅在使用双向 SSL(即相互认证)时与 `connector` 相关。

默认值为 `null`。

trustStorePath

在 `acceptor` 上使用时,这是服务器端 SSL 密钥库的路径,该密钥库包含服务器信任的所有客户端的密钥。这仅在您使用双向 SSL(即相互认证)时与 `acceptor` 相关。

在 `connector` 上使用时,这是客户端 SSL 密钥库的路径,该密钥库包含客户端信任的所有服务器的公钥。尽管此值可以在服务器上配置,但它会被下载并在客户端使用。如果客户端需要使用与服务器上设置的路径不同的路径,则可以通过使用常用的“javax.net.ssl.trustStore”系统属性或 ActiveMQ 特定的“org.apache.activemq.ssl.trustStore”系统属性来覆盖服务器端设置。如果客户端上的另一个组件已经在使用标准 Java 系统属性,则 ActiveMQ 特定的系统属性很有用。

trustStorePassword

在 `acceptor` 上使用时,这是服务器端信任库的密码。这仅在您使用双向 SSL(即相互认证)时与 `acceptor` 相关。

在 `connector` 上使用时,这是客户端信任库的密码。尽管此值可以在服务器上配置,但它会被下载并在客户端使用。如果客户端需要使用与服务器上设置的密码不同的密码,则可以通过使用常用的“javax.net.ssl.trustStorePassword”系统属性或 ActiveMQ 特定的“org.apache.activemq.ssl.trustStorePassword”系统属性来覆盖服务器端设置。如果客户端上的另一个组件已经在使用标准 Java 系统属性,则 ActiveMQ 特定的系统属性很有用。

trustStoreType

正在使用的信任库类型。例如,`JKS`、`JCEKS`、`PKCS12`、`PEM` 等。此值也可以通过“javax.net.ssl.trustStoreType”系统属性或 ActiveMQ 特定的“org.apache.activemq.ssl.trustStoreType”系统属性设置。如果客户端上的另一个组件已经在使用标准 Java 系统属性,则 ActiveMQ 特定的系统属性很有用。默认值为 `JKS`。

trustStoreProvider

用于信任库的提供者。例如,`SUN`、`SunJCE` 等。此值也可以通过“javax.net.ssl.trustStoreProvider”系统属性或 ActiveMQ 特定的“org.apache.activemq.ssl.trustStoreProvider”系统属性设置。如果客户端上的另一个组件已经在使用标准 Java 系统属性,则 ActiveMQ 特定的系统属性很有用。默认值为 `null`。

enabledCipherSuites

无论是在 `acceptor` 还是 `connector` 上使用,这都是用于 SSL 通信的密码套件的逗号分隔列表。默认值为 `null`,这意味着将使用 JVM 的默认值。

enabledProtocols

无论是在 `acceptor` 还是 `connector` 上使用,这都是用于 SSL 通信的协议的逗号分隔列表。默认值为 `null`,这意味着将使用 JVM 的默认值。

needClientAuth

此属性仅适用于 `acceptor`。它告诉连接到此 acceptor 的客户端需要双向 SSL。有效值为 `true` 或 `false`。默认值为 `false`。

此属性优先于 `wantClientAuth`,如果其值为 true,则 `wantClientAuth` 将被忽略。
wantClientAuth

此属性仅适用于 `acceptor`。它告诉连接到此 acceptor 的客户端请求双向 SSL,但不是必需的。有效值为 `true` 或 `false`。默认值为 `false`。

如果属性 `needClientAuth` 设置为 `true`,则该属性将优先,并且此属性将被忽略。
verifyHost

在 `connector` 上使用时,将比较服务器 SSL 证书的 `CN` 或主题备用名称值与正在连接到的主机名,以验证匹配。这对于单向和双向 SSL 都很有用。

在 `acceptor` 上使用时,将比较连接的客户端 SSL 证书的 `CN` 或主题备用名称值与其主机名,以验证匹配。这仅对双向 SSL 有用。

有效值为 `true` 或 `false`。对于 connector,默认值为 `true`,对于 acceptor,默认值为 `false`。

trustAll

在 `connector` 上使用时,客户端将隐式地信任提供的服务器证书,无论配置了任何信任库。

此设置主要用于测试目的,不应在生产环境中使用。

有效值为 `true` 或 `false`。默认值为 `false`。

forceSSLParameters

在 `connector` 上使用时,将使用作为 connector 上参数设置的任何 SSL 设置,而不是 JVM 系统属性,包括 javax.net.ssl 和 ActiveMQ 系统属性,以配置此 connector 的 SSL 上下文。

有效值为 `true` 或 `false`。默认值为 `false`。

useDefaultSslContext

仅在 `connector` 上有效。允许 `connector` 使用“默认”SSL 上下文(通过 `SSLContext.getDefault()`),该上下文可以通过客户端(通过 `SSLContext.setDefault(SSLContext)`)以编程方式设置。如果设置为 `true`,则所有其他 SSL 相关参数(除了 `sslEnabled`)都将被忽略。

有效值为 `true` 或 `false`。默认值为 `false`。

sslProvider

用于在JDKOPENSSL之间切换SSL提供程序。默认值为JDK。如果与OPENSSL一起使用,可以将netty-tcnative添加到类路径中以使用本地安装的openssl。如果您想使用openssl支持但JDK提供程序不支持的特殊密码套件-椭圆曲线组合,这将很有用。有关更多信息,请参见https://en.wikipedia.org/wiki/Comparison_of_TLS_implementations

sniHost

当在acceptor上使用时,sniHost是一个正则表达式,用于匹配传入SSL连接上的server_name扩展。如果名称不匹配,则对接收器的连接将被拒绝。如果发生这种情况,将记录警告消息。如果传入连接不包含server_name扩展,则将接受连接。

当在connector上使用时,sniHost值用于SSL连接上的server_name扩展。

trustManagerFactoryPlugin

这在acceptorconnector上都有效。它定义了实现org.apache.activemq.artemis.api.core.TrustManagerFactoryPlugin的类的名称。这是一个简单的接口,具有单个方法,该方法返回一个javax.net.ssl.TrustManagerFactory。当底层javax.net.ssl.SSLContext初始化时,将使用TrustManagerFactory。这允许对代理和客户端信任的对象进行细粒度的自定义。

该值优先于应用于信任管理器的所有其他SSL参数(即trustAlltruststoreProvidertruststorePathtruststorePasswordcrlPath)。

指定的任何插件都需要放在代理的类路径上。

4.4.1. 配置SSLContextFactory

如果您使用JDK作为SSL提供程序(默认值),您可以配置要使用的SSLContextFactory。目前提供以下两种实现

  • org.apache.activemq.artemis.core.remoting.impl.ssl.DefaultSSLContextFactory(由默认值注册)

  • org.apache.activemq.artemis.core.remoting.impl.ssl.CachingSSLContextFactory

您也可以创建自己的org.apache.activemq.artemis.spi.core.remoting.ssl.SSLContextFactory实现。

这些实现由java.util.ServiceLoader加载,因此您需要在META-INF/services/org.apache.activemq.artemis.spi.core.remoting.ssl.SSLContextFactory文件中声明您的实现。如果有多个实现可用,将选择优先级最高的实现。

例如,如果您想使用org.apache.activemq.artemis.core.remoting.impl.ssl.CachingSSLContextFactory,则需要将META-INF/services/org.apache.activemq.artemis.spi.core.remoting.ssl.SSLContextFactory文件添加到您的类路径中,其内容为org.apache.activemq.artemis.core.remoting.impl.ssl.CachingSSLContextFactory

类似的机制也存在于OPENSSL SSL提供程序中,在这种情况下,您可以配置OpenSSLContextFactory。目前提供以下两种实现

  • org.apache.activemq.artemis.core.remoting.impl.ssl.DefaultOpenSSLContextFactory(由默认值注册)

  • org.apache.activemq.artemis.core.remoting.impl.ssl.CachingOpenSSLContextFactory

您也可以创建自己的org.apache.activemq.artemis.spi.core.remoting.ssl.OpenSSLContextFactory实现。

4.5. 配置Netty HTTP

Netty HTTP通过HTTP协议隧道传输数据包。它在防火墙只允许HTTP流量通过的情况下很有用。

请参见示例,了解使用Netty HTTP的完整工作示例。

Netty HTTP使用与Netty TCP相同的属性,但添加了以下其他属性

httpEnabled

在客户端激活http。这在代理上是不需要的。使用单端口支持,Apache ActiveMQ Artemis现在会自动检测是否正在使用http,并进行配置。

httpClientIdleTime

客户端在发送空http请求以保持连接活动之前的空闲时间

httpClientIdleScanPeriod

扫描空闲客户端的频率(毫秒)

httpResponseTime

服务器在发送空http响应以保持连接活动之前可以等待的时间

httpServerScanPeriod

扫描需要响应的客户端的频率(毫秒)

httpRequiresSessionId

如果为true,客户端将在第一次调用后等待接收会话ID。使用http连接器连接到servlet接收器(不推荐)

4.6. 配置Netty SOCKS 代理

所有这些参数只适用于connector和/或客户端URL。

使用循环回送地址(例如localhost127.0.0.1)作为connector或URL的目标将绕过这些配置属性的应用。换句话说,即使设置了这些属性,也不会配置任何SOCKS代理支持。
socksEnabled

是否在connector上启用SOCKS支持。

socksHost

要使用的SOCKS服务器的名称。

socksPort

要使用的SOCKS服务器的端口。

socksVersion

要使用的SOCKS版本。必须是整数。默认值为5

socksUsername

连接到socksHost时要使用的用户名。

socksPassword

连接到socksHost时要使用的密码。仅当socksVersion5时适用。

socksRemoteDNS

是否创建未解析的远程目标套接字并禁用DNS解析。默认值为false