Rabbitmq 通過延遲插件實現延遲隊列

Rabbitmq 通過延遲插件實現延遲隊列

DLX+TTL 存在時序問題

由於隊列先入先出的特性. 通過死信隊列(DLX)和給每條消息設置過期時間(TTL)來實現延遲隊列, 會存在時序問題. 即排在隊列頭的消息過期使時間如果設置的比較長, 會導致隊列後面過期時間比較短的消息, 過期了遲遲不被消費掉. 可以通過給 Rabbitmq 安裝延遲插件來實現延遲隊列功能

安裝延遲插件

下載地址

rabbitmq-delayed-message-exchange 插件可到這裏下載: RabbitMQ 延遲插件

也可以到github上下載 : RabbitMQ Delayed Message Plugin

(注意插件版本, 這個插件適應的版本時 3.5.8 及其以後的版本)

安裝

登錄 Linux 服務器, 將插件複製到這個路徑下: /usr/lib/rabbitmq/lib/rabbitmq_server-3.6.15/plugins/

然後執行以下指令:

# 開啓插件
rabbitmq-plugins enable rabbitmq_delayed_message_exchange

# 重啓 rabbitmq
/sbin/service rabbitmq-server restart

Java 代碼實現

@Configuration
public class RabbitConfig implements ApplicationContextAware {
    
    private ApplicationContext applicationContext;    
    
    @PostConstruct
    public RabbitAdmin rabbitAdmin() {
        RabbitAdmin rabbitAdmin = applicationContext.getBean("rabbitAdmin", RabbitAdmin.class);
        TopicExchange exchange = new TopicExchange("exchange.delay");
        // 交換器設置延遲屬性
        exchange.setDelayed(true);				                  
        rabbitAdmin.declareQueue(new Queue("queue.delay"));
        rabbitAdmin.declareExchange(exchange);
        rabbitAdmin.declareBinding(BindingBuilder.bind(new Queue("queue.delay")).to(exchange).with("rountingkey.delay");
        return rabbitAdmin;
    }
}

 // 消息發送器                                  
public class SendMQService {
    @Autowired
    private RabbitTemplate rabbitTemplate;
    
    // 發送消息
    public void sendMessage(String exchange, String routingKey, String msg, Integer expirationTime) {
        rabbitTemplate.convertAndSend(exchange, routingKey, msg, message -> {
            // 給每條消息設置過期時間
            message.getMessageProperties().setExpiration(expirationTime);
            return message;
        });
    }
}

// 消息監聽器, 交換器 delayed = "true"
@Component
@RabbitListener(containerFactory = "listenerContainerFactory",
    bindings = @QueueBinding(value = @Queue(value = "queue.delay"),
        exchange = @Exchange(value = "exchange.delay", type = ExchangeTypes.TOPIC, delayed = "true"),
        key = "rountingkey.delay"))
@Slf4j
public class MsgListener {

    @RabbitHandler
    public void msgHandler(String msg) {
        log.info("接收到的延遲消息 [{}]",msg)
    }
}                         
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章