Rocketmq 使用延迟队列

spring-cloud-stream-binder-rocketmq 不支持延时队列,需要使用原生的mq进行消息发送。

一、引入依赖

 implementation 'com.alibaba.cloud:spring-cloud-stream-binder-rocketmq:2.1.0.RELEASE'

二、定义生产信道和消费信道

//消费信道
public interface PagePointSink {
    String PAGE_POINT_INPUT = "page_point_input";

    @Input(PAGE_POINT_INPUT)
    SubscribableChannel pagepointInput();
}

//生产信道
public interface PagePointSource {
    String PAGE_POINT_OUTPUT = "page_point_output";

    @Output(PAGE_POINT_OUTPUT)
    MessageChannel pagepointOutput();
}

三、配置文件配置

spring.cloud.stream.bindings.page_point_output.destination=page_point
spring.cloud.stream.bindings.page_point_output.content-type=application/json
spring.cloud.stream.bindings.page_point_input.destination=page_point
spring.cloud.stream.bindings.page_point_input.content-type=application/json
spring.cloud.stream.bindings.page_point_input.group=page_point_input

四、延时发送

1、生产端

import java.util.Date;

import org.apache.rocketmq.client.exception.MQBrokerException;
import org.apache.rocketmq.client.exception.MQClientException;
import org.apache.rocketmq.client.producer.DefaultMQProducer;
import org.apache.rocketmq.common.message.Message;
import org.apache.rocketmq.remoting.exception.RemotingException;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Service;

import cn.hutool.json.JSONUtil;

import lombok.extern.slf4j.Slf4j;

@Slf4j
@Service
public class PagePointCommandService {

    @Autowired
    private PagePointSource pagePointSource;

    @Autowired
    DefaultMQProducer defaultMQProducer;

    
    @Override
    public void send(PagePointCommand command) {

        //延时发送
        Message message = new Message("page_point", JSONUtil.toJsonStr(command).getBytes());
        //messageDelayLevel=1s 5s 10s 30s 1m 2m 3m 4m 5m 6m 7m 8m 9m 10m 20m 30m 1h 2h
        //4 指的是30s
        message.setDelayTimeLevel(4);
        message.setTags("test");
         try {
            defaultMQProducer.send(message);
        } catch (MQClientException | RemotingException | MQBrokerException | InterruptedException ignored) {
        
         }
       
    }
}

2、消费端


import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.stream.annotation.StreamListener;
import org.springframework.context.ApplicationContext;
import org.springframework.integration.annotation.ServiceActivator;
import org.springframework.messaging.handler.annotation.Headers;
import org.springframework.messaging.handler.annotation.Payload;
import org.springframework.messaging.support.ErrorMessage;
import org.springframework.stereotype.Component;

import lombok.extern.slf4j.Slf4j;


@Slf4j
@Component
public class PagePointConsumer {
    //condition = "headers['rocketmq_TAGS']=='test'" 表示只处理headers包含rocketmq_TAGS为test的消息
    @StreamListener(value = PagePointSink.PAGE_POINT_INPUT, condition = "headers['rocketmq_TAGS']=='test'")
    public void dealInput(@Payload PagePointCommand command, @Headers Map headers) {
            // dosomething
    }

}

五、异常重试

1、配置中心修改配置

#重试的初始时间间隔是1000豪秒,每次翻3倍,最大的间隔时间是15秒,进行5次重试
spring.cloud.stream.bindings.page_point_input.consumer.maxAttempts=5
spring.cloud.stream.bindings.page_point_input.consumer.backOffInitialInterval=1000
spring.cloud.stream.bindings.page_point_input.consumer.backOffMultiplier=3
spring.cloud.stream.bindings.page_point_input.consumer.backOffMaxInterval=15000

2、生产端

import java.util.Date;

import org.apache.rocketmq.client.exception.MQBrokerException;
import org.apache.rocketmq.client.exception.MQClientException;
import org.apache.rocketmq.client.producer.DefaultMQProducer;
import org.apache.rocketmq.common.message.Message;
import org.apache.rocketmq.remoting.exception.RemotingException;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Service;

import cn.hutool.json.JSONUtil;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@Service
public class PagePointCommandService {

    @Autowired
    private PagePointSource pagePointSource;

    @Autowired
    DefaultMQProducer defaultMQProducer;
    
    @Override
    public void send(PagePointCommand command) {

        //异常重试
        Message message = new Message("page_point", JSONUtil.toJsonStr(command).getBytes());
        message.setTags("test");
         try {
            defaultMQProducer.send(message);
        } catch (MQClientException | RemotingException | MQBrokerException | InterruptedException ignored) {
        
         }
       
    }
}

3、消费端


import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.stream.annotation.StreamListener;
import org.springframework.context.ApplicationContext;
import org.springframework.integration.annotation.ServiceActivator;
import org.springframework.messaging.handler.annotation.Headers;
import org.springframework.messaging.handler.annotation.Payload;
import org.springframework.messaging.support.ErrorMessage;
import org.springframework.stereotype.Component;

import lombok.extern.slf4j.Slf4j;


@Slf4j
@Component
public class PagePointConsumer {

    @StreamListener(value = PagePointSink.PAGE_POINT_INPUT, condition = "headers['rocketmq_TAGS']=='test'")
    public void dealInput(@Payload PagePointCommand command, @Headers Map headers) {
        throw new RuntimeException();
    }

    
    //在接收消息时,如果消息处理失败,Spring Cloud会把失败的消息转到名为<destination>.<group>.errors的Channel,
    //并可通过@ServiceActivator方法进行接收。
    @ServiceActivator(inputChannel = "page_point.page_point_input.errors")
    public void handleConsumeUserError(ErrorMessage message) {
        log.info("收到处理失败的消息{}", message.getPayload());
    }

}
### 实现和配置 RocketMQ 延迟队列 #### 配置延迟级别 为了使 RocketMQ 支持不同级别的延迟发送,默认情况下,Broker 端可以通过 `messageDelayLevel` 参数设置多个预定义的时间间隔。这些时间间隔决定了消息可以被推迟多久才真正投递给消费者[^5]。 例如,在 Broker 的配置文件中添加或修改如下属性: ```properties messageDelayLevel=1s 5s 10s 30s 1m 2m 3m 4m 5m 6m 7m 8m 9m 10m 20m 30m 1h 2h ``` 这表示支持从一秒到两小时的不同层次的延迟等级。 #### 使用 API 发送带有时效性的消息 当应用程序想要发送一条具有特定延迟的消息时,只需指定该消息所属的 Topic 和 Tag 同时利用 `setDelayTimeLevel()` 方法指明希望使用的延迟级别即可。 下面是一个简单的 Java 示例展示了如何向名为 "TestTopic" 的主题发布带有三分钟延迟的消息: ```java // 创建生产者实例并指定名称服务地址 DefaultMQProducer producer = new DefaultMQProducer("please_rename_unique_group_name"); producer.setNamesrvAddr("localhost:9876"); try { // 初始化生产者 producer.start(); // 构建消息对象 Message msg = new Message( "TestTopic", // topic "TagA", // tag ("Hello RocketMQ").getBytes(RemotingHelper.DEFAULT_CHARSET)); // 设置延迟级别为第四个选项即三分钟 msg.setDelayTimeLevel(4); // 异步发送消息至 broker SendResult sendResult = producer.send(msg); } catch (Exception e) { e.printStackTrace(); } finally{ producer.shutdown(); } ``` 需要注意的是,上述代码中的 `msg.setDelayTimeLevel(4)` 表示选择了第四层延迟——也就是三分钟后的传递;如果需要其他时间段,则应调整此参数值以匹配所需的延迟水平。 对于更灵活的需求,如任意秒数内的精准延时,RocketMQ 5 提供了一种新的机制允许用户自定义更加精细粒度的延迟策略而不局限于固定的几个档位之外[^1]。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值