跳至主内容
版本:4.3

STOMP 插件

概述

RabbitMQ 通过核心发行版中自带的插件支持 STOMP 协议。该插件支持 STOMP 1.0 到 1.2 版本,并包含一些扩展和限制

STOMP 客户端可以与其他协议互操作。管理界面中的所有功能以及其他几个插件都可以与 STOMP 一起使用,尽管可能存在一些限制或需要调整默认设置。

启用插件

STOMP 插件包含在 RabbitMQ 发行版中。在客户端成功连接之前,必须使用 rabbitmq-plugins 启用它。

rabbitmq-plugins enable rabbitmq_stomp

插件配置

TCP 监听器

当未指定配置时,STOMP 适配器将监听所有接口的 61613 端口,并使用默认的用户名/密码 guest/guest

要更改监听端口,请编辑您的配置文件,为 rabbitmq_stomp 应用程序添加一个 tcp_listeners 变量。

例如,一个将监听端口更改为 12345 的最小化配置文件如下所示:

stomp.listeners.tcp.1 = 12345

而一个仅监听 localhost(IPv4 和 IPv6)的配置将如下所示

stomp.listeners.tcp.1 = 127.0.0.1:61613
stomp.listeners.tcp.2 = ::1:61613

TCP 监听器选项

该插件支持 TCP 监听器选项配置。

这些设置使用通用前缀 stomp.tcp_listen_options,并控制 TCP 缓冲区大小、入站 TCP 连接队列长度、是否启用 TCP keepalives 等。详情请参阅网络指南

stomp.listeners.tcp.1 = 127.0.0.1:61613
stomp.listeners.tcp.2 = ::1:61613

stomp.tcp_listen_options.backlog = 4096
stomp.tcp_listen_options.recbuf = 131072
stomp.tcp_listen_options.sndbuf = 131072

stomp.tcp_listen_options.keepalive = true
stomp.tcp_listen_options.nodelay = true

stomp.tcp_listen_options.exit_on_close = true
stomp.tcp_listen_options.send_timeout = 120

TLS 支持

要在 STOMP 连接中使用 TLS,必须在代理中配置 TLS。要启用支持 TLS 的 STOMP 连接,请使用 stomp.listeners.ssl.* 配置键为 STOMP 添加 TLS 监听器。

该插件将使用核心 RabbitMQ 服务器证书和密钥(就像 AMQP 0.9.1 和 AMQP 1.0 监听器一样)

ssl_options.cacertfile = /path/to/tls/ca_certificate.pem
ssl_options.certfile = /path/to/tls/server_certificate.pem
ssl_options.keyfile = /path/to/tls/server_key.pem
ssl_options.verify = verify_peer
ssl_options.fail_if_no_peer_cert = true

stomp.listeners.tcp.1 = 61613
# default TLS-enabled port for STOMP connections
stomp.listeners.ssl.1 = 61614

此配置在端口 61613 上创建一个标准 TCP 监听器,在端口 61614 上创建一个 TLS 监听器。

设置 TLS 监听器后,您可能希望停用所有非 TLS 监听器。这可以通过以下方式配置:

stomp.listeners.tcp = none
stomp.listeners.ssl.1 = 61614

默认用户

如果配置了默认用户,RabbitMQ STOMP 适配器允许 CONNECT 帧省略 loginpasscode 头部。

要配置默认用户名和密码,请在 rabbitmq_stomp 应用程序配置中添加一个 default_user 部分。例如:

stomp.default_user = guest
stomp.default_pass = guest

上面的配置示例将 guest/guest 设为默认的用户名/密码对。

使用 TLS/x509 客户端证书进行身份验证

该插件可以通过从客户端的 TLS (x509) 证书中提取名称来对 TLS 连接进行身份验证,而无需使用密码。

为了安全起见,必须将服务器的TLS 选项配置为 fail_if_no_peer_cert 设置为 true,并将 verify 设置为 verify_peer,以强制所有 TLS 客户端提供可验证的客户端证书。

要开启此功能,请将 rabbitmq_stomp 应用程序的 ssl_cert_login 设置为 true。例如:

stomp.ssl_cert_login = true

默认情况下,这将把用户名设置为证书主体(Subject)的标识名(Distinguished Name)的 RFC4514 风格字符串形式,类似于 OpenSSL 的 "-nameopt RFC2253" 选项产生的结果。

要改用通用名称(Common Name),请添加:

ssl_cert_login_from = common_name

到您的配置中。

请注意

  • 经过身份验证的用户必须存在于已配置的身份验证/授权后端中。
  • 客户端不得提供 loginpasscode 头部。

隐式连接

如果您配置了默认用户或使用了 SSL 客户端证书身份验证,还可以允许客户端完全省略 CONNECT 帧。在此模式下,如果会话上发送的第一帧不是 CONNECT,客户端将自动以默认用户或 SSL 证书中提供的用户身份连接。

要启用隐式连接,请将 rabbit_stomp 应用程序的 implicit_connect 设置为 true。例如:

stomp.default_user = guest
stomp.default_pass = guest
stomp.implicit_connect = true

默认情况下,隐式连接启用。

注意:触发隐式连接的客户端不会从服务器收到 CONNECTED 帧。

代理协议

STOMP 插件支持 proxy protocol。此功能默认关闭。要为 STOMP 客户端开启它:

stomp.proxy_protocol = true

有关代理协议的更多信息,请参阅 网络指南

帧大小限制

默认情况下,帧大小限制为 4Mb。当帧超过此限制时,将视为错误并关闭连接。

stomp.max_frame_size = 4 * 1024 * 1024

目的地

STOMP 规范未规定代理必须支持何种类型的目的地,SENDMESSAGE 帧中 destination 头的值由具体的代理决定。RabbitMQ STOMP 适配器支持多种不同的目的地类型:

  • /exchange -- 发送(SEND)到任意路由键,并订阅(SUBSCRIBE)到任意绑定模式;
  • /queue -- 发送(SEND)和订阅(SUBSCRIBE)到由 STOMP 网关管理的队列;
  • /amq/queue -- 发送(SEND)和订阅(SUBSCRIBE)到在 STOMP 网关之外创建的队列;
  • /topic -- 发送(SEND)和订阅(SUBSCRIBE)到瞬时和持久主题;
  • /temp-queue/ -- 创建临时队列(仅限在 reply-to 头部中使用)。

AMQP 0-9-1 语义

MESSAGE 帧上的 destination 头部设置方式就像该消息源自 SEND 帧一样:

  • 发布到默认交换机的消息被赋予 /queue/queuename 的目的地;
  • 发布到 amq.topic 的消息被赋予 /topic/routing_key 的目的地;
  • 所有其他消息被赋予 /exchange/exchange_name[/routing_key] 的目的地。

如果 queuenameexchange_namerouting_key 中包含 /% 或非 ASCII 字节,它们将被替换为 %dd 序列,其中 dd 是该字节的十六进制代码。

由于这些规则,MESSAGE 帧上的目的地可能与发布它的 SEND 帧上的目的地不完全匹配。

不同的目的地具有不同的队列参数默认值。它们可以通过头部显式控制,具体说明见本指南后续部分。

交换机目的地

可以使用以 /exchange 为前缀的目的地访问任何交换机/队列或交换机/路由键组合。

对于 SUBSCRIBE 帧,可以使用 /exchange/<name>[/<pattern>] 格式的目的地。该目的地:

  • <name> 交换机上创建一个独占的、自动删除的队列;
  • 如果提供了 <pattern>,则使用 <pattern> 将队列绑定到 <name> 交换机;以及
  • 针对当前 STOMP 会话在该队列上注册订阅。

对于 SEND 帧,可以使用 /exchange/<name>[/<routing-key>] 格式的目的地。该目的地:

  • 发送消息到 <name> 交换机,并使用 <routing-key> 作为路由键。

注意:交换机目的地不适合从现有队列消费消息。每个订阅者都会创建一个新队列,并使用提供的路由键绑定到指定的交换机。要使用现有队列,请使用 /amq/queue 目的地。

队列目的地

对于简单队列,可以使用 /queue/<name> 格式的目的地。

队列目的地将每条消息传递给最多一个订阅者。当没有订阅者存在时发送的消息将被排队,直到有订阅者连接到该队列。

AMQP 0-9-1 语义

对于 SUBSCRIBE 帧,这些目的地会创建一个共享队列 <name>。并为当前 STOMP 会话创建针对队列 <name> 的订阅。

对于 SEND 帧,在当前会话中第一次发送到此目的地时,会创建共享队列 <name>,之后不再创建。消息通过默认交换机发送,路由键为 <name>

如果未指定队列参数,队列将被视为持久、非独占且非自动删除的。

AMQ 队列目的地

要寻址在 STOMP 适配器外部创建的现有队列,可以使用 /amq/queue/<name> 格式的目的地。

AMQP 0-9-1 语义

对于 SENDSUBSCRIBE 帧,都不会创建队列。对于 SUBSCRIBE 帧,如果队列不存在,则视为错误。

对于 SEND 帧,消息通过默认交换机直接发送到名为 <name> 的现有队列。

对于 SUBSCRIBE 帧,将为当前 STOMP 会话创建针对现有队列 <name> 的订阅。

如果未指定队列参数,队列将被视为持久、非独占且非自动删除的。

主题目的地

STOMP 客户端使用最广泛的目的地类型可能是 /topic/<name>。它们根据订阅者模式对发布的消息执行主题匹配,并可以将消息路由到多个订阅者(每个订阅者获得一份副本)。主题目的地支持 AMQP 0-9-1 主题交换机的所有路由模式。

发送到没有活跃订阅者的主题目的地的消息会被简单地丢弃。

AMQP 0-9-1 语义

对于 SEND 帧,消息发送到 amq.topic 交换机,路由键为 <name>

对于 SUBSCRIBE 帧,会创建一个自动删除、非持久的队列,并使用路由键 <name> 绑定到 amq.topic 交换机。并针对该队列创建订阅。

可以使用 stomp.default_topic_exchange 配置设置来指定与 amq.topic 不同的默认交换机:

stomp.default_topic_exchange = some.exchange

持久主题订阅

STOMP 适配器支持持久主题订阅。持久订阅允许客户端根据需要与 STOMP 代理断开连接并重新连接,而不会丢失发送到该主题的消息。

主题本身既不是持久的也不是瞬时的,而是订阅分为持久或瞬时。对于给定的主题,持久和瞬时订阅可以共存。

创建持久订阅

要创建持久订阅,请在 SUBSCRIBE 帧中将 durable 头部设置为 true。为了与早期插件版本向后兼容,persistent 也被支持作为 durable 的别名。

在为主题目的地创建持久订阅时,请将 auto-delete 设置为 false,以确保当最后一个订阅者断开连接时,支持您订阅的队列不会被删除。

创建持久订阅时,必须指定 id 头部。例如:

SUBSCRIBE
destination:/topic/my-durable
id:1234
durable:true
auto-delete:false

AMQP 0-9-1 语义

对于 SEND 帧,消息发送到 amq.topic 交换机,路由键为 <name>

对于 SUBSCRIBE 帧,会为每个不同的订阅 ID x 目的地对创建一个共享队列,并使用路由键 <name> 绑定到 amq.topic 交换机。并针对该队列创建订阅。

注意:可以使用 stomp.default_topic_exchange 配置设置来指定与 amq.topic 不同的默认交换机。

删除持久订阅

要永久删除持久订阅,请发送该订阅 ID 的 UNSUBSCRIBE 帧,并使用与订阅时相同的 durableauto-delete 头部值。

例如:

UNSUBSCRIBE
id:1234
durable:true
auto-delete:false

临时队列目的地

临时队列目的地允许您在 SEND 帧的 reply-to 头部中定义临时目的地。

临时队列由代理管理,它们的身份对每个会话是私有的——无需为不同会话中的临时队列选择不同的名称。

要使用临时队列,请在 SEND 帧上放置 reply-to 头部,并使用以 /temp-queue/ 开头的头部值。例如:

SEND
destination:/queue/reply-test
reply-to:/temp-queue/foo

Hello World!

此帧会创建一个会话私有的临时队列(具有生成的名称),并自动订阅该队列。另一个使用 reply-to:/temp-queue/foo 的会话将创建另一个新的、独立的队列。

内部订阅 ID 是字符串 /temp-queue/ 与临时队列名称的串联(在本例中为 /temp-queue/foo)。该订阅 ID 可用于识别回复消息。无法通过 destination 头部识别回复消息,因为它将不同于 reply-to 头部中的值。内部订阅使用自动确认模式,且无法取消。

/temp-queue/ 目的地不是接收客户端在发送回复时使用的目的地名称。相反,接收客户端可以从 MESSAGE 帧的 reply-to 头部中获取(真实的)回复目的地队列名称。然后,该回复目的地名称可用作接收到 MESSAGE 后所发送回复的 SEND 帧中 destination 头部的值。

回复目的地队列名称是不透明的,无法从 /temp-queue/ 名称中推断出来。

SENDSUBSCRIBE 帧的 destination 头部不得包含 /temp-queue 目的地。消息无法发送到 /temp-queue 目的地,且回复队列的订阅是自动创建的。

AMQP 0-9-1 语义

每个 /temp-queue/ 对应一个独立的匿名、独占、自动删除队列。因此,无需显式清理回复队列。

为主题和交换机目的地生成用户自定义的队列名称

当订阅 exchangetopic 目的地时,RabbitMQ 默认会生成一个队列名称。可以使用 x-queue-name 头部提供自定义名称:

SUBSCRIBE
destination:/topic/alarms
x-queue-name:my-alarms-queue

使用 STOMP 控制 RabbitMQ 队列参数

队列属性可以通过 STOMP 头部进行控制:

  • durable (别名为 persistent)
  • auto-delete
  • exclusive

以及用于控制死信、队列和消息 TTL、队列限制等的可选参数("x-arguments"):

  • x-dead-letter-exchange
  • x-dead-letter-routing-key
  • x-expires
  • x-message-ttl
  • x-max-length
  • x-max-length-bytes
  • x-max-age (仅适用于 )
  • x-stream-max-segment-size-bytes (仅适用于 )
  • x-overflow
  • x-max-priority
  • x-queue-type (用于声明仲裁队列)

每个头部的含义与通过 AMQP 0-9-1 声明队列时的含义相同。详情请参考其余文档。

在 STOMP 中使用策略

RabbitMQ 策略允许对队列和交换机进行灵活、集中的属性配置。策略可以应用于 STOMP 插件使用的队列。

策略使得在 STOMP 中可以使用更多的 RabbitMQ 特性:

STOMP 插件创建的所有服务器命名队列都带有 stomp- 前缀,这使得在策略中匹配这些队列变得容易。例如,要将 STOMP 队列长度限制为 1000 条消息,请创建以下策略:

rabbitmqctl set_policy stomp-queues "^stomp-" '{"max-length":1000}' --apply-to queues

使用 Windows 上的 rabbitmqctl.bat

rabbitmqctl.bat set_policy stomp-queues "^stomp-" "{""max-length"":1000}" --apply-to queues

请注意,一个队列一次只能应用一个策略,因此要指定多个参数(例如队列长度限制和死信),需要将它们放入单个策略中。

协议扩展和限制

RabbitMQ STOMP 适配器放宽了对 CONNECT 的协议限制,并在某些帧上支持多个非标准头部。这些额外头部提供了对 STOMP 规范中未描述的功能的访问。此外,我们禁止使用一些保留给服务器使用的头部。详情如下。

连接和虚拟主机

STOMP 1.1 中的 CONNECT (或 STOMP) 帧有一个强制性的 host 头部(用于选择连接所使用的虚拟主机)。RabbitMQ 适配器允许该头部可选。

省略时,默认为默认虚拟主机 (/)。要配置不同的默认虚拟主机,请在 rabbitmq_stomp 应用程序配置中添加一个 default_vhost 部分,例如:

stomp.default_vhost = /

如果指定了 host 头部,它必须是 RabbitMQ 服务器已知的虚拟主机之一,否则连接将被拒绝。即使连接时协商的是 STOMP 1.0 版本,host 头部也会被遵循。

消息持久性

SEND 帧上,STOMP 适配器支持包含 persistent 头部。

persistent 头部设置为 true 可以使消息持久化。

对于带有 persistent:trueSEND 帧,在从代理接收到确认之前,不会发送回执。有关持久消息确认的具体语义,请参见此处

持久消息的 MESSAGE 帧将包含一个 persistent:true 头部。

ACK 和 NACK

RabbitMQ STOMP 插件支持 autoclientclient-individual 订阅头部,它们会影响 ACKNACK 操作的工作方式。

auto 模式使用自动确认。client 模式是手动(由客户端驱动)一次确认多条消息。client-individual 用于逐条手动确认消息。

NACK 帧可以选择性地携带 requeue 头部,该头部控制消息是被重新排队还是被丢弃/进入死信队列。默认值为 true

预取

默认情况下,所有订阅的预取计数被设置为无限。这可以通过将 SUBSCRIBE 帧上的 prefetch-count 头部设置为所需的整数计数来控制。

流支持

SUBSCRIBE 帧支持 x-stream-offset 头部,以指定从中的哪个偏移量开始消费。典型的流订阅帧如下所示:

SUBSCRIBE
destination:/amq/queue/my-stream
ack:client
prefetch-count:10
x-stream-offset:next

注意,ackprefetch-count 头部也是必需的。x-stream-offset 头部与 AMQP 0.9.1 中的语义相同,可能的值包括:

  • first:从流中第一个可用消息开始消费;
  • last:从最后写入的消息块开始消费;
  • next:从流的末尾开始消费(注意,在有人向流发布消息之前,消费者将不会收到任何消息);
  • offset=<offset-value>:从特定偏移量开始,例如 offset=40000
  • timestamp=<unix-time>:从给定时间开始,例如 timestamp=1619432061 代表 2021-04-26T10:14:21+00:00

默认值为 next

从流中传递消息时,消息偏移量(即消息在流中的位置)包含在 MESSAGE 帧的 x-stream-offset 头部中。

同时支持流过滤流协议是与流交互的首选方式,但大多数功能也适用于其他协议。流过滤也不例外,它在 STOMP 中的工作方式与在 AMQP 中的工作方式相同:

  • 声明:可以在订阅时创建流。将 x-queue-type 头部设置为 stream,并使用 x-stream-filter-size-bytes 头部设置过滤器大小(可选)。
  • 发布:使用 x-stream-filter-value 头部为出站消息设置过滤器值。
  • 消费:使用 x-stream-filter 头部设置期望的过滤器值(用逗号分隔多个值),并可选择使用 x-stream-match-unfiltered 头部(truefalse)以同时接收没有任何过滤器值的消息(默认为 false)。应用程序还必须实现客户端过滤,因为仍然可能收到不符合过滤器值标准的消息。

禁止在 SEND 上设置的头部

禁止在 SEND 帧上设置 message-id 头部。该头部及其值由服务器在发送给客户端的 MESSAGE 帧上设置。

队列属性

SEND 帧还允许使用对应于发布消息时可用AMQP 属性的头部。这些头部也会在发送给客户端的 MESSAGE 帧上设置。

支持所有非弃用的 AMQP 0-9-1 属性(content-type, content-encoding, headers, delivery-mode, priority, correlation-id, reply-to, expiration, message-id, timestamp, type, user-idapp-id)。以下是特殊规则:

  • STOMP 中的 amqp-message-id 会转换为 AMQP 中的 message-id,反之亦然。
  • reply-to 头部会导致创建临时队列(参见上文的临时队列目的地)。
  • 一些以 x- 开头的 STOMP 头部会被转换为可选队列参数(见下文)。

可选队列属性

在 RabbitMQ 中,SENDSUBSCRIBE 帧可以包含一组头部来配置队列行为,例如使用 TTL 或类似扩展。

支持的头部列表如下:

例如,如果您想在 STOMP 中使用优先级队列,可以通过以下头部进行 SUBSCRIBE (或 SEND):

SUBSCRIBE
destination:/queue/my-priority-queue
x-max-priority:5

队列不可变性

一旦声明了队列,其属性就无法更改。可选参数可以通过策略进行修改。否则,必须删除并重新声明该队列。对于 STOMP 客户端和 AMQP 0-9-1 客户端,情况都是如此。

© . This site is unofficial and not affiliated with VMware.