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 cn.medbanks.trading.order.application.command.cmd.PagePointCommand;
import cn.medbanks.trading.order.infrastructure.db.dataobject.PagePointEntity;
import cn.medbanks.trading.order.infrastructure.db.repo.PagePointRepository;
import cn.medbanks.trading.order.infrastructure.event.PagePointEvent;
import cn.medbanks.trading.order.infrastructure.mq.channel.PagePointSource;
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、消费端

package cn.medbanks.trading.order.infrastructure.mq.comsumer;

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 cn.medbanks.trading.order.application.command.cmd.PagePointCommand;
import cn.medbanks.trading.order.infrastructure.mq.channel.PagePointSink;
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 cn.medbanks.trading.order.application.command.cmd.PagePointCommand;
import cn.medbanks.trading.order.infrastructure.db.dataobject.PagePointEntity;
import cn.medbanks.trading.order.infrastructure.db.repo.PagePointRepository;
import cn.medbanks.trading.order.infrastructure.event.PagePointEvent;
import cn.medbanks.trading.order.infrastructure.mq.channel.PagePointSource;
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、消费端

package cn.medbanks.trading.order.infrastructure.mq.comsumer;

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 cn.medbanks.trading.order.application.command.cmd.PagePointCommand;
import cn.medbanks.trading.order.infrastructure.mq.channel.PagePointSink;
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会把失败的消息转到名为..errors的Channel,
    //并可通过@ServiceActivator方法进行接收。
    @ServiceActivator(inputChannel = "page_point.page_point_input.errors")
    public void handleConsumeUserError(ErrorMessage message) {
        log.info("收到处理失败的消息{}", message.getPayload());
    }

}

你可能感兴趣的:(中间件)