spring-amqp

目录

官方文档地址

AMQP抽象(消息、交换机、队列、绑定)

资源管理

AmqpTemplate

消息转换:MessageConverter 和 MessagePropertiesConverter消息


官方文档地址

  1. Spring官网:Spring AMQP
  2. 中文文档:版本2.3.11,要注意版本区别http://geekdoc.top/docs/languages/java/spring/spring-amqp/2.3.11/reference/html/index.html
  3. springboot集成AMQP:Messaging
  4. RabbitMQ可配置属性:Common Application Properties

AMQP抽象(消息、交换机、队列、绑定)

  • Message类:为了方便参数传递和操作,AMQP定义的通用领域模型,但是在0-9-1 AMQP规范中没有定义该类或接口。

其中,两个关键属性:

  • private final MessageProperties messageProperties:用于定义常见属性、头信息等;
  • private final byte[] body:消息体
  1. 在实际开发过程中,我们经常调用convertAndSend函数发送消息,此时入参可以为Object类型,在RabbitTemplate内部,会调用convertMessageIfNecessary方法,将消息转换为Message类,然后再进行发送。
  2. 从版本 1.5.7、1.6.11、1.7.4 和 2.0.0 开始,如果 消息体是一个序列化的 Serializable java 对象,在执行 toString() 操作(例如在日志消息中)时不再反序列化(默认情况下)。 这是为了防止不安全的反序列化。 默认情况下,只有 java.util 和 java.lang 类被反序列化。 要恢复到以前的行为,您可以通过调用 Message.addAllowedListPatterns(… ) 添加允许的类/包模式。 支持简单的 通配符,例如 com.something., *.MyClass. 无法反序列化的主体在日志消息中由 byte[ ] 表示。
  • Exchange接口:定义了交换机的基本属性,并且根据类型有相应的默认实现。
  • Queue类:定义了队列的相关属性。可以通过流API:QueueBuilder进行绑定。
  • Binding类:定义了绑定相关的属性和操作。可以通过流API:BindingBuilder进行绑定。
  • 更多的抽象可以在org.springframework.amqp.core中查看。

资源管理

连接工程厂:管理与 RabbitMQ 代理的连接的核心组件是 ConnectionFactory 接口。ConnectionFactory实现的职责是提供一个 org.springframework.amqp. rabbit.connection. Connection 的实例。共有三种连接工厂可供选择。

  • PooledChannelConnectionFactory:
  1. 对于大多数用例,应该使用 PooledChannelConnectionFactory。如果您想确保严格的消息排序而不需要使用 作用域操作,可以使用 ThreadChannelConnectionFactory。
  2. 该工厂基于 Apache Pool2 管理单个连接和两个通道池。 一个池用于事务通道,另一个池用于非事务通道。 池是具有默认配置的 GenericObjectPool,提供回调以配置池。
  • ThreadChannelConnectionFactory

这个工厂管理一个连接和两个 ThreadLocal ,一个用于事务性通道,另一个用于非事务性通道。 该工厂确保同一线程上的所有操作都使用相同的通道(只要它保持打开状态)。 这有助于严格的消息排序,而无需作用域操作。 为避免内存泄漏,如果您的应用程序使用许多短期线程,您必须调用工厂的 closeThreadChannel() 来释放通道资源。 从版本 2.3.7 开始,一个线程可以将其通道传输到另一个线程。 

  • CachingConnectionFactory:
  1. 默认情况下,它会建立一个可由应用程序共享的连接代理。 共享连接是可能的,因为使用 AMQP 进行消息传递的“工作单元”实际上是一个“通道”(在某些方面,这类似于 JMS 中连接和会话之间的关系)。 连接实例提供了一个 createChannel 方法。 CachingConnectionFactory 实现支持对这些通道进行缓存,并根据通道是否为事务性维护单独的缓存。 创建 CachingConnectionFactory 的实例时,您可以通过构造函数提供“主机名”。 您还应该提供“用户名”和“密码”属性。 要配置通道缓存的大小(默认为 25),您可以调用 setChannelCacheSize() 方法。
  2. CachingConnectionFactory 现在通过 getCacheProperties() 方法提供缓存统计信息。 这些统计信息可用于调整缓存以在生产中对其进行优化。 
  3. 如果你想使用相关的发布者确认或者如果你想通过它的 CacheMode打开多个连接,应该使用 CachingConnectionFactory。【SpringBoot默认工厂】

所有三个工厂都支持简单的发布者确认。

  • 发布者确认和返回
  1. 将 CachingConnectionFactory 属性 publisherConfirmType 设置为 ConfirmType.CORRELATED 和 publisherReturns 来支持确认(具有相关性)和返回的消息 > 属性为“真”。
  2. 设置这些选项后,工厂创建的 Channel 实例被包装在 PublisherCallbackChannel 中,用于促进回调。 当获得这样的频道时,客户端可以向 Channel 注册一个 PublisherCallbackChannel.Listener。 PublisherCallbackChannel 实现包含将确认或返回路由到适当侦听器的逻辑。
  • 连接和通道监听器
  1. 连接工厂支持注册 ConnectionListener 和 ChannelListener 实现。 这允许您接收连接和通道相关事件的通知。

AmqpTemplate

  • 目前只有一个实现:RabbitTemplate。
  • 可以引入spring-retry实现重试功能。使用Java的@Configuration注册如下:
@Bean
public RabbitTemplate rabbitTemplate() {
    RabbitTemplate template = new RabbitTemplate(connectionFactory());
    RetryTemplate retryTemplate = new RetryTemplate();
    ExponentialBackOffPolicy backOffPolicy = new ExponentialBackOffPolicy();
    backOffPolicy.setInitialInterval(500);
    backOffPolicy.setMultiplier(10.0);
    backOffPolicy.setMaxInterval(10000);
    retryTemplate.setBackOffPolicy(backOffPolicy);
    template.setRetryTemplate(retryTemplate);
    return template;
}
  • AmqpTemplate 的 RabbitTemplate 实现支持发布者确认和返回。对于返回的消息,模板的 mandatory 属性必须设置为 true 或 mandatory-expression 必须评估为 true 对于特定消息。 此功能需要一个 CachingConnectionFactory,其 publisherReturns 属性设置为 true。 通过调用 setReturnsCallback(ReturnsCallback callback) 注册 RabbitTemplate.ReturnsCallback,将返回发送到客户端。
  • 关于发送和接收消息的方法参考:RabbitTemplate.java
  • 发送相关的send/convertAndSend
  • 接收相关的receive/receiveAndConvert
  • 批量发布:可以使用BatchingRabbitTemplate.java,可以根据批处理策略进行批量发布消息。存在数据丢失风险!
  1. 消息接收:
  • 轮询消费者
  1. AmqpTemplate 本身可用于轮询 Message 接收。 默认情况下,如果没有可用消息,则立即返回 null。 没有阻塞。 从版本 1.5 开始,您可以设置 receiveTimeout,以毫秒为单位,并且接收方法阻塞长达那么长时间,等待消息。 小于零的值意味着无限期地阻塞(或至少直到与代理的连接丢失)。
  2. 相关函数:receive/receiveAndConvert
  • 异步消费者:通过@RabbitListener注解注册监听器,预期默认值为250.
  • 批处理:
    @Bean
    public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory() {
        SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
        factory.setConnectionFactory(connectionFactory());
        factory.setBatchListener(true);
        return factory;
    }

    @RabbitListener(queues = "batch.1")
    public void listen1(List<Thing> in) {
    ...
    }
// or

    @RabbitListener(queues = "batch.2")
    public void listen2(List<Message<Thing>> in) {
    ...
    }

@RabbitListener及容器

除了常见的通过RabbitListener注解注册监听器端点,还可以通过编程的方式。代码实例如下所示。

@Configuration
@EnableRabbit
public class AppConfig implements RabbitListenerConfigurer {

   @Override
   public void configureRabbitListeners(RabbitListenerEndpointRegistrar registrar) {
      SimpleRabbitListenerEndpoint endpoint = new SimpleRabbitListenerEndpoint();
      endpoint.setQueueNames("anotherQueue");
      endpoint.setMessageListener(message -> {
         // processing
      });
      registrar.registerEndpoint(endpoint);
   }
}
  1. 创建监听器容器
  • 方式1、使用SimpleRabbitListenerEndpoint如下代码所示。
@Bean
public SimpleMessageListenerContainer factoryCreatedContainerSimpleListener(
      SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory) {
   SimpleRabbitListenerEndpoint endpoint = new SimpleRabbitListenerEndpoint();
   endpoint.setQueueNames("queue.1");
   endpoint.setMessageListener(message -> {
       ...
   });
   return rabbitListenerContainerFactory.createListenerContainer(endpoint);
}
  • 方式2、创建后添加侦听器
@Bean
public SimpleMessageListenerContainer factoryCreatedContainerNoListener(
      SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory) {
   SimpleMessageListenerContainer container = rabbitListenerContainerFactory.createListenerContainer();
   container.setMessageListener(message -> {
       ...
   });
   container.setQueueNames("test.no.listener.yet");
   return container;
}

【注意】这两种方式创建的容器只是一个普通的bean,并没有注册到RabbitListenerEndpointRegistry中。

使用容器工厂

  • SMLC(SimpleMessageListenerContainer)有以下特性,但DMLC(DirectMessageListener- Container)没有:
    1. batchSize:使用SMLC,您可以设置此值以控制在一个事务中传递的消息数量或减少ack的数量,但它可能会导致失败后重复传递的数量增加。(DMLC有messagesPerAck,你可以使用它来减少ack,与batchSize和SMLC一样,但它不能用于事务——每个消息在一个单独的事务中被交付和ack)。
    2. consumerBatchEnabled:允许在消费者中对离散消息进行批处理。
    3. maxConcurrentConsumers和consumer伸缩间隔或触发器——DMLC中没有自动伸缩功能。但是,它允许您以编程方式更改consumersPerQueue属性,并相应地调整消费者。
  • 与SMLC相比,DMLC有以下优点:
    1. 在运行时添加和删除队列更有效。使用SMLC,将重启整个使用者线程(取消并重新创建所有使用者)。通过DMLC,未受影响的消费者不会被取消。
    2. 避免了RabbitMQ Client线程和consumer线程之间的上下文切换。
    3. 线程在使用者之间共享,而不是在SMLC中为每个使用者拥有一个专用线程。
  • 检测空闲消费者:
  1. 可通过配置SimpleMessageListenerContainer或SimpleRabbitListenerContainerFactory的idleEventInterval属性。
  2. 可通过使用@EventListener监听特定的消费者
public class Listener {

   @RabbitListener(id="someId", queues="#{queue.name}")
   public String listen(String foo) {
      return foo.toUpperCase();
   }

   @EventListener(condition = "event.listenerId == 'someId'")
   public void onApplicationEvent(ListenerContainerIdleEvent event) {
        ...
   }
}

消息转换:MessageConverter 和 MessagePropertiesConverter消息

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值