最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

RabbitMQ高級(jí)特性之死信隊(duì)列深入解析

 更新時(shí)間:2026年01月06日 10:47:37   作者:新綠MEHO  
死信隊(duì)列(DeadLetterQueue, DLQ)是存儲(chǔ)那些無法被正常消費(fèi)或處理的消息的特殊隊(duì)列,應(yīng)用場景包括消息重試、消息丟棄和日志收集,本文給大家介紹RabbitMQ高級(jí)特性之死信隊(duì)列的相關(guān)知識(shí),感興趣的朋友跟隨小編一起看看吧

死信隊(duì)列

死信(dead message) 簡單理解就是因?yàn)榉N種原因, ?法被消費(fèi)的信息, 就是死信.
有死信, ?然就有死信隊(duì)列. 當(dāng)消息在?個(gè)隊(duì)列中變成死信之后,它能被重新被發(fā)送到另?個(gè)交換器
中,這個(gè)交換器就是DLX( Dead Letter Exchange ), 綁定DLX的隊(duì)列, 就稱為死信隊(duì)列(Dead
Letter Queue,簡稱DLQ).

消息變成死信?般是由于以下?種情況:

1. 消息被拒絕( Basic.Reject/Basic.Nack ),并且設(shè)置 requeue 參數(shù)為 false.
2. 消息過期.
3. 隊(duì)列達(dá)到最??度.

添加配置

spring:
  application:
    name: rabbit-extensions-demo
  rabbitmq:
    addresses: amqp://study:study@47.98.109.138:5672/extension

常量類

public class Constants {
    //死信
    public static final String NORMAL_QUEUE = "normal.queue";
    public static final String NORMAL_EXCHANGE = "normal.exchange";
    public static final String DL_QUEUE = "dl.queue";
    public static final String DL_EXCHANGE= "dl.exchange";
}

聲明隊(duì)列和交換機(jī)并綁定二者關(guān)系

import org.springframework.amqp.core.*;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import rabbitextensionsdemo.constant.Constants;
@Configuration
public class DLConfig {
    //正常的交換機(jī)和隊(duì)列
    @Bean("normalQueue")
    public Queue normalQueue(){
        return QueueBuilder.durable(Constants.NORMAL_QUEUE)
                .deadLetterExchange(Constants.DL_EXCHANGE)
                .deadLetterRoutingKey("dlx")
                .build();
    }
    @Bean("normalExchange")
    public DirectExchange normalExchange(){
        return ExchangeBuilder.directExchange(Constants.NORMAL_EXCHANGE).build();
    }
    @Bean("normalBinding")
    public Binding normalBinding(@Qualifier("normalQueue") Queue queue, @Qualifier("normalExchange") Exchange exchange){
        return BindingBuilder.bind(queue).to(exchange).with("normal").noargs();
    }
    //死信交換機(jī)和隊(duì)列
    @Bean("dlQueue")
    public Queue dlQueue(){
        return QueueBuilder.durable(Constants.DL_QUEUE).build();
    }
    @Bean("dlExchange")
    public DirectExchange dlExchange(){
        return ExchangeBuilder.directExchange(Constants.DL_EXCHANGE).build();
    }
    @Bean("dlBinding")
    public Binding dlBinding(@Qualifier("dlQueue") Queue queue, @Qualifier("dlExchange") Exchange exchange){
        return BindingBuilder.bind(queue).to(exchange).with("dlx").noargs();
    }
}

死信--消息過期

給隊(duì)列設(shè)置TTL

編寫生產(chǎn)消息代碼

    @RequestMapping("/dl")
    public String dl() {
        System.out.println("dl...");
        //發(fā)送普通消息
        rabbitTemplate.convertAndSend(Constants.NORMAL_EXCHANGE, "normal", "dl test...");
        System.out.printf("%tc 消息發(fā)送成功 \n", new Date());
        return "消息發(fā)送成功";
    }

編寫消費(fèi)消息代碼

import com.rabbitmq.client.Channel;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
import rabbitextensionsdemo.constant.Constants;
import java.util.Date;
@Component
public class DLListener {
    @RabbitListener(queues = Constants.DL_QUEUE)
    public void dlHandMessage(Message message, Channel channel) throws Exception {
        //消費(fèi)者邏輯
        System.out.printf("[dl.queue] %tc 接收到消息: %s, deliveryTag: %d \n", new Date(), new String(message.getBody(),"UTF-8"), message.getMessageProperties().getDeliveryTag());
    }
}

觀察現(xiàn)象

我們可以看到,消息在10秒后過期,從normal隊(duì)列進(jìn)入到了死信隊(duì)列,消息進(jìn)入到死信隊(duì)列后被消費(fèi)。

死信--消息超過隊(duì)列最大長度

設(shè)置隊(duì)列的最大長度

編寫生產(chǎn)消息代碼

    @RequestMapping("/dl")
    public String dl() {
        //測試隊(duì)列長度
        for (int i = 0; i < 20; i++) {
            rabbitTemplate.convertAndSend(Constants.NORMAL_EXCHANGE, "normal", "dl test..."+i);
        }
        return "消息發(fā)送成功";
    }

編寫消費(fèi)消息代碼

import com.rabbitmq.client.Channel;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
import rabbitextensionsdemo.constant.Constants;
import java.util.Date;
@Component
public class DLListener {
    @RabbitListener(queues = Constants.DL_QUEUE)
    public void dlHandMessage(Message message, Channel channel) throws Exception {
        //消費(fèi)者邏輯
        System.out.printf("[dl.queue] %tc 接收到消息: %s, deliveryTag: %d \n", new Date(), new String(message.getBody(),"UTF-8"), message.getMessageProperties().getDeliveryTag());
    }
}

觀察現(xiàn)象

此時(shí)我們可以看到,給隊(duì)列設(shè)置了最大長度為10,但是隊(duì)列接收到了20條消息,就會(huì)導(dǎo)致前10條消息變成死信。

死信--消息被拒絕

編寫生產(chǎn)消息代碼

    @RequestMapping("/dl")
    public String dl() {
        System.out.println("dl...");
        //發(fā)送普通消息
        rabbitTemplate.convertAndSend(Constants.NORMAL_EXCHANGE, "normal", "dl test...");
        System.out.printf("%tc 消息發(fā)送成功 \n", new Date());
        return "消息發(fā)送成功";
    }

編寫消費(fèi)消息代碼

import com.rabbitmq.client.Channel;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
import rabbitextensionsdemo.constant.Constants;
@Component
public class DLListener {
    @RabbitListener(queues = Constants.NORMAL_QUEUE)
    public void handMessage(Message message, Channel channel) throws Exception {
        long deliveryTag = message.getMessageProperties().getDeliveryTag();
        try {
            //消費(fèi)者邏輯
            System.out.printf("[normal.queue]接收到消息: %s, deliveryTag: %d \n", new String(message.getBody(),"UTF-8"), message.getMessageProperties().getDeliveryTag());
            //進(jìn)行業(yè)務(wù)邏輯處理
            System.out.println("業(yè)務(wù)邏輯處理");
            int num = 3/0;
            System.out.println("業(yè)務(wù)處理完成");
            //肯定確認(rèn)
            channel.basicAck(deliveryTag,false);
        } catch (Exception e) {
            //否定確認(rèn)
            channel.basicNack(deliveryTag, false, false);  //requeue為false, 該消息成為死信
        }
    }
}

觀察現(xiàn)象

可以看到,normal隊(duì)列中的消息在被消費(fèi)時(shí)因?yàn)榘l(fā)生了異常而執(zhí)行到了拒絕消息的代碼,而且設(shè)置了消息不重新入隊(duì),導(dǎo)致消息變成了死信,進(jìn)而進(jìn)入到了死信隊(duì)列。

面試題

1.死信隊(duì)列的概念

死信(Dead Letter)是消息隊(duì)列中的?種特殊消息, 它指的是那些?法被正常消費(fèi)或處理的消息. 在消息隊(duì)列系統(tǒng)中, 如RabbitMQ, 死信隊(duì)列?于存儲(chǔ)這些死信消息。

2.死信的來源

1) 消息過期: 消息在隊(duì)列中存活的時(shí)間超過了設(shè)定的TTL
2) 消息被拒絕: 消費(fèi)者在處理消息時(shí), 可能因?yàn)橄?nèi)容錯(cuò)誤, 處理邏輯異常等原因拒絕處理該消息. 如果拒絕時(shí)指定不重新?隊(duì)(requeue=false), 消息也會(huì)成為死信.
3) 隊(duì)列滿了: 當(dāng)隊(duì)列達(dá)到最??度, ?法再容納新的消息時(shí), 新來的消息會(huì)被處理為死信.

3.死信的應(yīng)用場景 

對(duì)于RabbitMQ來說, 死信隊(duì)列是?個(gè)?常有?的特性. 它可以處理異常情況下,消息不能夠被消費(fèi)者正確消費(fèi)?被置?死信隊(duì)列中的情況, 應(yīng)?程序可以通過消費(fèi)這個(gè)死信隊(duì)列中的內(nèi)容來分析當(dāng)時(shí)所遇到的異常情況, 進(jìn)?可以改善和優(yōu)化系統(tǒng).

?如: ???付訂單之后, ?付系統(tǒng)會(huì)給訂單系統(tǒng)返回當(dāng)前訂單的?付狀態(tài)
為了保證?付信息不丟失, 需要使?到死信隊(duì)列機(jī)制. 當(dāng)消息消費(fèi)異常時(shí), 將消息投?到死信隊(duì)列中, 由訂單系統(tǒng)的其他消費(fèi)者來監(jiān)聽這個(gè)隊(duì)列, 并對(duì)數(shù)據(jù)進(jìn)?處理(?如發(fā)送?單等,進(jìn)???確認(rèn)).

場景的應(yīng)?場景還有:

• 消息重試:將死信消息重新發(fā)送到原隊(duì)列或另?個(gè)隊(duì)列進(jìn)?重試處理.
• 消息丟棄:直接丟棄這些?法處理的消息,以避免它們占?系統(tǒng)資源.
• ?志收集:將死信消息作為?志收集起來,?于后續(xù)分析和問題定位.

到此這篇關(guān)于詳解RabbitMQ高級(jí)特性之死信隊(duì)列的文章就介紹到這了,更多相關(guān)RabbitMQ死信隊(duì)列內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • java中List數(shù)組用逗號(hào)分隔開轉(zhuǎn)成字符串2種方法

    java中List數(shù)組用逗號(hào)分隔開轉(zhuǎn)成字符串2種方法

    在我們?nèi)粘i_發(fā)中,在前后端交互的時(shí)候會(huì)遇到多個(gè)id或其他字段存放到一個(gè)字段中,這時(shí)我們會(huì)遇到一個(gè)List(集合)---->String(單個(gè)字段),這篇文章主要給大家介紹了關(guān)于java中List數(shù)組用逗號(hào)分隔開轉(zhuǎn)成字符串的2種方法,需要的朋友可以參考下
    2023-10-10
  • Java 批量獲取地址間距離工具(支持中轉(zhuǎn)站)

    Java 批量獲取地址間距離工具(支持中轉(zhuǎn)站)

    本文主要介紹了Java批量獲取地址間距離,獲取兩個(gè)地址間距離,實(shí)現(xiàn)方式比較多,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-07-07
  • spring boot使用logback日志級(jí)別打印控制操作

    spring boot使用logback日志級(jí)別打印控制操作

    這篇文章主要介紹了spring boot使用logback日志級(jí)別打印控制操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2021-03-03
  • SpringBoot中的事務(wù)全方位詳解

    SpringBoot中的事務(wù)全方位詳解

    這篇文章主要介紹了SpringBoot中的事務(wù)全方位詳解,在Spring中,事務(wù)有兩種實(shí)現(xiàn)方式,分別是編程式事務(wù)管理和聲明式事務(wù)管理兩種方式,文中舉例詳細(xì)說明了這兩種事務(wù),需要的朋友可以參考下
    2023-08-08
  • Java面試之高級(jí)特性基礎(chǔ)總結(jié)

    Java面試之高級(jí)特性基礎(chǔ)總結(jié)

    這篇文章主要為大家詳細(xì)介紹了10個(gè)Java高級(jí)特性基礎(chǔ)相關(guān)的問題,也是大家面試中常常會(huì)遇到的問題。文中的示例代講解詳細(xì),感興趣的可以了解一下
    2023-01-01
  • Java中ResultSetMetaData 元數(shù)據(jù)的具體使用

    Java中ResultSetMetaData 元數(shù)據(jù)的具體使用

    本文主要介紹了Java中ResultSetMetaData 元數(shù)據(jù)的具體使用,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-04-04
  • Java?synchronized關(guān)鍵字性能考量及優(yōu)化探索

    Java?synchronized關(guān)鍵字性能考量及優(yōu)化探索

    這篇文章主要為大家介紹了Java?synchronized關(guān)鍵字性能考量及優(yōu)化探索示例分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-12-12
  • Java實(shí)現(xiàn)合并兩個(gè)有序序列算法示例

    Java實(shí)現(xiàn)合并兩個(gè)有序序列算法示例

    這篇文章主要介紹了Java實(shí)現(xiàn)合并兩個(gè)有序序列算法,簡單描述了序列合并算法的原理與java合并有序序列的具體操作步驟及相關(guān)實(shí)現(xiàn)技巧,需要的朋友可以參考下
    2017-09-09
  • Java中Map.getOrDefault()方法舉例詳解

    Java中Map.getOrDefault()方法舉例詳解

    這篇文章主要介紹了Java?8中Map接口的getOrDefault()方法,該方法在獲取鍵值對(duì)時(shí),如果鍵不存在則返回默認(rèn)值,文中通過一個(gè)統(tǒng)計(jì)網(wǎng)站用戶點(diǎn)擊次數(shù)的應(yīng)用場景,詳細(xì)展示了getOrDefault()的用法,需要的朋友可以參考下
    2025-02-02
  • Java中Lambda表達(dá)式和函數(shù)式接口的使用和特性

    Java中Lambda表達(dá)式和函數(shù)式接口的使用和特性

    Java Lambda表達(dá)式是一種函數(shù)式編程的特性,可簡化匿名內(nèi)部類的寫法,與函數(shù)式接口搭配使用,實(shí)現(xiàn)代碼簡潔、可讀性高、易于維護(hù)的特點(diǎn),適用于集合操作、多線程編程等場景
    2023-04-04

最新評(píng)論

子长县| 永吉县| 会同县| 永顺县| 高碑店市| 英山县| 荆州市| 廊坊市| 忻州市| 廊坊市| 蓝山县| 文水县| 栾川县| 隆子县| 福建省| 宜兰市| 怀远县| 马关县| 阿拉善左旗| 邢台市| 大厂| 鹤山市| 澜沧| 周宁县| 郓城县| 托里县| 榆中县| 吉木萨尔县| 苍南县| 出国| 图木舒克市| 克东县| 凤阳县| 乐安县| 峨山| 四会市| 林口县| 曲阳县| 清新县| 诏安县| 新沂市|