springBoot + RabbitMqは、遅延メッセージ送信を実装します-デッドレターモード

RabbitMqが高い同時実行性、永続性、および高可用性をサポートすることの利点を考慮して、activeMqからRabbitMqに切り替えることが決定されました。予備調査が不十分だったため、RabbitMq自体は遅延メッセージをサポートしていないことが判明しました。デッドレターまたは統合プラグインここでは、最初にデッドレターの方法を紹介します。

ここではRabbitの詳細な使用法については説明しません。コードに移動して、実装手順を紹介します。

1.メッセージキューの定数を定義します

public static final String ACT_QUEUE= "act_queue";//活动立即消费队列
public static final String ACT_DELAY_QUEUE= "act_delay_queue";//活动死信消费队列
public static final String ACT_EXCHANGE = "act_exchage";         //交换器
public static final String ACT_DEAD_LETTER_EXCHANGE = "act_dead_letter_exchange"; //死信交换器
public static final String ACT_ROUTING_KEY = "act_routing_key";//立即消费路由键
public static final String ACT_DELAY_ROUTING_KEY = "act_delay_routing_key"; //延迟路由键

2.キューを構成します

-------------------注意深く見てください、これは完全なコードです

//立即消费队列
@Bean
public Queue actQueue() {
    return new Queue(ACT_QUEUE,true);
}

/**
 * 延迟队列: 创建一个延迟队列, 此队列中的消息没有消费者去消费, 到了过期时间之后变成死信, 变死信之后会根据
 *           绑定的DLX和routingKey重新发送到指定交换机再到指定队列。
*/
@Bean
public Queue delayQueue() {
    Map<String, Object> map = new HashMap<>();
    // x-dead-letter-exchange 声明了队列里的死信转发到的DLX名称,
    map.put("x-dead-letter-exchange", ACT_EXCHANGE);
    // x-dead-letter-routing-key 声明了这些死信在转发时携带的 routing-key 名称。
    map.put("x-dead-letter-routing-key", ACT_ROUTING_KEY);
    Queue queue = new Queue(ACT_DELAY_QUEUE, true, false, false, map);
    System.out.println("----------------------------deadLetterQueue :" + queue.getArguments());
    return queue;
}

/**
 *  声明立即消费队列交换机-direct类型
 * 注:把消息投递到那些binding key与routing key完全匹配的队列中。
 * */
@Bean
public DirectExchange actExchage(){
    // 一共有三种构造方法,可以只传exchange的名字, 第二种,可以传exchange名字,是否支持持久化,是否可以自动删除,
    //第三种在第二种参数上可以增加Map,Map中可以存放自定义exchange中的参数
    return new DirectExchange (ACT_EXCHANGE,true, false);
}

//声明死信队列交换机-direct类型
@Bean
public DirectExchange deadLetterExchange() {
    return new DirectExchange(ACT_DEAD_LETTER_EXCHANGE, true, false);
}

/**
 * @description   绑定队列与交换机
 *                  把立即消费的队列和立即消费交换机绑定, immediate_exchange, 路由键:immediate_routing_key
 * @author        songchengye
 * @date          2020/10/24 13:24
 */
@Bean
public Binding actBinding() {
    return BindingBuilder.bind(actQueue()).to(actExchage()).with(ACT_ROUTING_KEY);
}

/**
 * @description   死信队列的交换机绑定:把延迟消费的队列和死信交换机绑定, immediate_dead_exchange, 路由键:delay_routing_key
 * @author        songchengye
 * @date          2020/10/24 13:24
*/
@Bean
public Binding queueDeadBinding() {
    return BindingBuilder.bind(delayQueue()).to(deadLetterExchange()).with(ACT_DELAY_ROUTING_KEY);
}

3.メッセージの送信者を書く

import com.alibaba.fastjson.JSONObject;
import com.jeesite.modules.sp.entity.SpAct;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.AmqpException;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessagePostProcessor;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.Date;


@Service
public class MQActSender {

private static Logger log = LoggerFactory.getLogger(MQActSender.class);

@Autowired
RabbitTemplate rabbitTemplate;

//发送延时消息
public void sendDelayCancelAct(Object message){
    log.info("进入活动消息生产者-----------sendDelayCancelAct---------------发送活动延时消息:"+message.toString());
    SpAct spAct = (SpAct) message;
    JSONObject jsonObject = new JSONObject();
    jsonObject.put("test","测试发送消息到死信队列");
    String time = "60000";//延时时间,这样得到的值是毫秒级,rabbitMQ默认是毫秒
    log.info("----sendDelayCancelAct---------------------------活动消息延迟时间:"+time);
    rabbitTemplate.convertAndSend(MQConfig.ACT_DEAD_LETTER_EXCHANGE, MQConfig.ACT_DELAY_ROUTING_KEY, jsonObject,
            new MessagePostProcessor() {
                @Override
                public Message postProcessMessage(Message message) throws AmqpException {
                    //设置消息持久化
                    //message.getMessageProperties().setDeliveryMode(MessageDeliveryMode.PERSISTENT);
                    message.getMessageProperties().setExpiration(time);
                    return message;
                }
            });
}

4.メッセージの消費者を書く

import com.alibaba.fastjson.JSONObject;
import com.jeesite.modules.sp.api.constant.Dict;
import com.jeesite.modules.sp.entity.SpAct;
import com.jeesite.modules.sp.entity.SpActEnter;
import com.jeesite.modules.sp.service.SpActEnterService;
import com.jeesite.modules.sp.service.SpActService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import java.util.Date;


@Service
@Component
public class MQActReceiver {

@Autowired
private SpActService spActService;

@Autowired
private SpActEnterService spActEnterService;


private static Logger log = LoggerFactory.getLogger(MQActReceiver.class);

@RabbitListener(queues  = MQConfig.ACT_QUEUE)
public void receive(JSONObject message){
    log.info("进入消息消费者----------------------------监听活动消息 = " + message.toJSONString());
    try {
        String test= message.getString("test").toString();
        log.info("---------------------------MQActReceiver--------监听到的消息:"+test
    } catch (Exception e) {
        e.printStackTrace();
    }

}

この時点で、送信の遅延は基本的に実現されますが、キューの先入れ先出しの問題により、メッセージブロッキングの問題が発生します。たとえば、メッセージBが5分であっても、メッセージAは10分です。その場合、メッセージBはメッセージAのみを待つことができます。消費後に消費できます。

一般的なプロセスは次のとおりです。
デッドレターキューには独自のコンシューマーがありません。
ここに画像の説明を挿入

おすすめ

転載: blog.csdn.net/weixin_43945983/article/details/109293486
おすすめ