使用 Spring AMQP
本章探讨的接口和类是使用 Spring AMQP 开发应用程序的核心组件。
章节摘要
AMQP 抽象
Spring AMQP 由两个模块组成(分发包中各对应一个 JAR): spring-amqp 和 spring-rabbit。'spring-amqp' 模块包含 org.springframework.amqp.core 包。在该包中,你可以找到代表核心 AMQP“模型”的类。我们的意图是提供不依赖任何特定 AMQP broker 实现或客户端库的通用抽象。最终用户代码可以更方便地跨厂商实现 移植,因为它只针对抽象层开发。这些抽象随后由特定于 broker 的模块 (例如 'spring-rabbit')实现。目前只有一个 RabbitMQ 实现。 不过,除 RabbitMQ 之外,这些抽象还在 .NET 中使用 Apache Qpid 得到了验证。由于 AMQP 工作在协议层,原则上你可以将 RabbitMQ 客户端用于任何支持相同协议版本的 broker,但我们目前不测试其他 broker。
连接与资源管理
上一节描述的 AMQP 模型是通用的、适用于所有实现,但进入资源管理时, 细节就是 broker 实现所特有的了。因此本节聚焦于仅存在于我们 “spring-rabbit” 模块中的代码,因为目前 RabbitMQ 是唯一支持的实现。
添加自定义客户端连接属性
CachingConnectionFactory 现在允许你访问底层连接工厂,以便 例如设置自定义客户端属性。下例展示了如何这样做:
AmqpTemplate
与 Spring Framework 及相关项目提供的许多其他高级抽象一样, Spring AMQP 提供了一个起核心作用的“模板”。定义主要操作的接口 名为 AmqpTemplate。这些操作涵盖发送和接收消息的一般行为。换句话说, 它们并非任何实现所独有——因此名称中有“AMQP”。另一方面,该接口 也有一些与 AMQP 协议实现绑定的实现。与 JMS 本身就是接口级 API 不同,AMQP 是线级协议。该协议的实现提供自己的客户端库,因此模板 接口的每个实现都依赖于特定的客户端库。目前只有一个实现: RabbitTemplate。在下面的示例中,我们经常使用 AmqpTemplate。不过, 当你查看配置示例或任何实例化模板或调用 setter 的代码摘录时,就能 看到实现类型(例如 RabbitTemplate)。
发送消息
发送消息时,你可以使用以下任一方法:
接收消息
14 个项目
容器与 Broker 命名队列
虽然更推荐使用 AnonymousQueue 实例作为自动删除队列,但从 版本 2.1 开始,你可以在监听器容器中使用 Broker 命名队列。 下例展示了如何这样做:
消息转换器
AmqpTemplate 还定义了若干发送和接收消息的方法,它们委托给 MessageConverter。MessageConverter 为每个方向提供一个方法:一个 用于转换为 Message,另一个用于从 Message 转换。注意,转换为 Message 时,除对象外还可以提供属性。object 参数通常对应消息体。 下面的清单展示了 MessageConverter 接口的定义:
修改消息——压缩及更多
存在许多扩展点。它们让你可以在消息发送到 RabbitMQ 之前或 收到消息之后立即对消息执行一些处理。
请求/回复消息传递
AmqpTemplate 还提供了多种 sendAndReceive 方法,它们接受与前面 所述单向发送操作相同的参数选项(exchange、routingKey 和 Message)。这些方法对于请求-回复场景非常有用,因为它们在发送前 处理必要的 reply-to 属性配置,并可以在内部为此目的创建的独占队列上 监听回复消息。
配置 Broker
AMQP 规范描述了如何使用该协议在 broker 上配置队列、交换机和绑定。这些 操作(从 0.8 规范起可移植)存在于 org.springframework.amqp.core 包的 AmqpAdmin 接口中。该类的 RabbitMQ 实现是位于 org.springframework.amqp.rabbit.core 包中的 RabbitAdmin。
Broker 事件监听器
启用 Event Exchange Plugin 后,如果你向应用程序上下文添加一个 BrokerEventListener 类型的 bean,它会将选定的 broker 事件发布为 BrokerEvent 实例,可以用普通的 Spring ApplicationListener 或 @EventListener 方法消费这些事件。broker 将事件发布到 topic 交换机 amq.rabbitmq.event,每种事件类型对应不同的路由键。监听器使用 事件键,这些键用于将 AnonymousQueue 绑定到该交换机,从而使监听器 只接收选定的事件。由于它是 topic 交换机,可以使用通配符(也可以显式 请求特定事件),如下例所示:
延迟消息交换机
1.6 版本引入了对延迟消息交换机插件的支持
RabbitMQ REST API
启用管理插件后,RabbitMQ 服务器会暴露一个 REST API,用于监控和 配置 broker。现在提供了该 API 的 Java 绑定。 com.rabbitmq.http.client.Client 是一个标准、即时(因而阻塞)的 API。它基于 Spring Web 模块及其 RestTemplate 实现。另一方面, com.rabbitmq.http.client.ReactorNettyClient 是一个基于 Reactor Netty 项目的响应式、非阻塞实现。
异常处理
使用 RabbitMQ Java 客户端的许多操作都可能抛出受检异常。例如, 在很多情况下可能抛出 IOException 实例。RabbitTemplate、 SimpleMessageListenerContainer 以及其他 Spring AMQP 组件会 捕获这些异常,并将它们转换为 AmqpException 体系中的某个异常。 这些异常定义在 'org.springframework.amqp' 包中,AmqpException 是该体系的基类。
事务
Spring Rabbit 框架在同步和异步用例中支持自动事务管理, 并提供多种不同语义,可以像现有 Spring 事务用户所熟悉的那样以声明 方式选择。这使得许多(即使不是大多数)常见消息传递模式都易于 实现。
消息监听器容器配置
配置 SimpleMessageListenerContainer(SMLC)和 DirectMessageListenerContainer(DMLC)时,与事务和服务质量相关的选项 相当多,其中一些还会相互影响。适用于 SMLC、DMLC 或 StreamListenerContainer(StLC)(参见使用 RabbitMQ 流插件)的属性由相应 列中的对勾标出。参见选择容器,了解帮助你决定哪种容器适合应用的信息。
监听器并发
默认情况下,监听器容器启动单个消费者,从队列接收消息。
独占消费者
从版本 1.3 开始,你可以为监听器容器配置单个独占消费者。 这会阻止其他容器从队列中消费,直到当前消费者被取消。此类 容器的并发数必须为 1。
监听器容器队列
1.3 版本为在监听器容器中处理多个队列引入了多项改进。
弹性:从错误和 Broker 故障中恢复
Spring AMQP 提供的一些关键(也是最受欢迎的)高级功能与协议错误 或 broker 故障发生时的恢复和自动重连有关。本指南中我们已经见过 所有相关组件,但在这里把它们汇集到一起,并逐一说明这些功能和恢复 场景会有所帮助。
多 Broker(或集群)支持
2.3 版本为单个应用程序与多个 broker 或 broker 集群之间的通信 增加了更多便利。在消费者一侧,主要好处是基础设施可以自动将 自动声明的队列关联到相应的 broker。
调试
Spring AMQP 提供了详尽的日志,尤其是在 `DEBUG` 级别。