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

Java RabbitMQ 中的消息長(zhǎng)期不消費(fèi)會(huì)過期嗎

 更新時(shí)間:2021年09月23日 09:16:50   作者:_江南一點(diǎn)雨  
RabbitMQ支持消息的過期時(shí)間,在消息發(fā)送時(shí)可以進(jìn)行指定。 RabbitMQ支持隊(duì)列的過期時(shí)間,從消息入隊(duì)列開始計(jì)算,只要超過了隊(duì)列的超時(shí)時(shí)間配置,那么消息會(huì)自動(dòng)的清除

RabbitMQ 中的消息長(zhǎng)期未被消費(fèi)會(huì)過期嗎?用過 RabbitMQ 的小伙伴可能都有這樣的疑問,今天松哥就來和大家捋一捋這個(gè)問題。

1. 默認(rèn)情況

首先我們來看看默認(rèn)情況。

默認(rèn)情況下,消息是不會(huì)過期的,也就是我們平日里在消息發(fā)送時(shí),如果不設(shè)置任何消息過期的相關(guān)參數(shù),那么消息是不會(huì)過期的,即使消息沒被消費(fèi)掉,也會(huì)一直存儲(chǔ)在隊(duì)列中。

這種情況具體代碼就不用我再演示了吧,松哥之前的文章凡是涉及到 RabbitMQ 的,基本上都是這樣的。

2. TTL

TTL(Time-To-Live),消息存活的時(shí)間,即消息的有效期。如果我們希望消息能夠有一個(gè)存活時(shí)間,那么我們可以通過設(shè)置 TTL 來實(shí)現(xiàn)這一需求。如果消息的存活時(shí)間超過了 TTL 并且還沒有被消息,此時(shí)消息就會(huì)變成死信,關(guān)于死信以及死信隊(duì)列,松哥后面再和大家介紹。

TTL 的設(shè)置有兩種不同的方式:

  • 在聲明隊(duì)列的時(shí)候,我們可以在隊(duì)列屬性中設(shè)置消息的有效期,這樣所有進(jìn)入該隊(duì)列的消息都會(huì)有一個(gè)相同的有效期。
  • 在發(fā)送消息的時(shí)候設(shè)置消息的有效期,這樣不同的消息就具有不同的有效期。

那如果兩個(gè)都設(shè)置了呢?

以時(shí)間短的為準(zhǔn)。

當(dāng)我們?cè)O(shè)置了消息有效期后,消息過期了就會(huì)被從隊(duì)列中刪除了(進(jìn)入到死信隊(duì)列,后文一樣,不再標(biāo)注),但是兩種方式對(duì)應(yīng)的刪除時(shí)機(jī)有一些差異:

對(duì)于第一種方式,當(dāng)消息隊(duì)列設(shè)置過期時(shí)間的時(shí)候,那么消息過期了就會(huì)被刪除,因?yàn)橄⑦M(jìn)入 RabbitMQ 后是存在一個(gè)消息隊(duì)列中,隊(duì)列的頭部是最早要過期的消息,所以 RabbitMQ 只需要一個(gè)定時(shí)任務(wù),從頭部開始掃描是否有過期消息,有的話就直接刪除。對(duì)于第二種方式,當(dāng)消息過期后并不會(huì)立馬被刪除,而是當(dāng)消息要投遞給消費(fèi)者的時(shí)候才會(huì)去刪除,因?yàn)榈诙N方式,每條消息的過期時(shí)間都不一樣,想要知道哪條消息過期,必須要遍歷隊(duì)列中的所有消息才能實(shí)現(xiàn),當(dāng)消息比較多時(shí)這樣就比較耗費(fèi)性能,因此對(duì)于第二種方式,當(dāng)消息要投遞給消費(fèi)者的時(shí)候才去刪除。

介紹完 TTL 之后,接下來我們來看看具體用法。

接下來所有代碼松哥都以 Spring Boot 中封裝的 AMPQ 為例來講解。

2.1 單條消息過期

我們先來看單條消息的過期時(shí)間。

首先創(chuàng)建一個(gè) Spring Boot 項(xiàng)目,引入 Web 和 RabbitMQ 依賴,如下:

然后在 application.properties 中配置一下 RabbitMQ 的連接信息,如下:

spring.rabbitmq.host=127.0.0.1
spring.rabbitmq.port=5672
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest
spring.rabbitmq.virtual-host=/

接下來稍微配置一下消息隊(duì)列:

@Configuration
public class QueueConfig {

    public static final String JAVABOY_QUEUE_DEMO = "javaboy_queue_demo";
    public static final String JAVABOY_EXCHANGE_DEMO = "javaboy_exchange_demo";
    public static final String HELLO_ROUTING_KEY = "hello_routing_key";

    @Bean
    Queue queue() {
        return new Queue(JAVABOY_QUEUE_DEMO, true, false, false);
    }

    @Bean
    DirectExchange directExchange() {
        return new DirectExchange(JAVABOY_EXCHANGE_DEMO, true, false);
    }

    @Bean
    Binding binding() {
        return BindingBuilder.bind(queue())
                .to(directExchange())
                .with(HELLO_ROUTING_KEY);
    }
}

這個(gè)配置類主要干了三件事:配置消息隊(duì)列、配置交換機(jī)以及將兩者綁定在一起。

  • 首先配置一個(gè)消息隊(duì)列,new 一個(gè) Queue:第一個(gè)參數(shù)是消息隊(duì)列的名字;第二個(gè)參數(shù)表示消息是否持久化;第三個(gè)參數(shù)表示消息隊(duì)列是否排他,一般我們都是設(shè)置為 false,即不排他;第四個(gè)參數(shù)表示如果該隊(duì)列沒有任何訂閱的消費(fèi)者的話,該隊(duì)列會(huì)被自動(dòng)刪除,一般適用于臨時(shí)隊(duì)列。
  • 配置一個(gè) DirectExchange 交換機(jī)。
  • 將交換機(jī)和隊(duì)列綁定到一起。

這段配置應(yīng)該很簡(jiǎn)單,沒啥好解釋的,有一個(gè)排他性,松哥這里稍微多說兩句:

關(guān)于排他性,如果設(shè)置為 true,則該消息隊(duì)列只有創(chuàng)建它的 Connection 才能訪問,其他的 Connection 都不能訪問該消息隊(duì)列,如果試圖在不同的連接中重新聲明或者訪問排他性隊(duì)列,那么系統(tǒng)會(huì)報(bào)一個(gè)資源被鎖定的錯(cuò)誤。另一方面,對(duì)于排他性隊(duì)列而言,當(dāng)連接斷掉的時(shí)候,該消息隊(duì)列也會(huì)自動(dòng)刪除(無論該隊(duì)列是否被聲明為持久性隊(duì)列都會(huì)被刪除)。

接下來提供一個(gè)消息發(fā)送接口,如下:

@RestController
public class HelloController {
    @Autowired
    RabbitTemplate rabbitTemplate;

    @GetMapping("/hello")
    public void hello() {
        Message message = MessageBuilder.withBody("hello javaboy".getBytes())
                .setExpiration("10000")
                .build();
        rabbitTemplate.convertAndSend(QueueConfig.JAVABOY_QUEUE_DEMO, message);
    }
}

在創(chuàng)建 Message 對(duì)象的時(shí)候我們可以設(shè)置消息的過期時(shí)間,這里設(shè)置消息的過期時(shí)間為 10 秒。

這就可以啦!

接下來我們啟動(dòng)項(xiàng)目,進(jìn)行消息發(fā)送測(cè)試。當(dāng)消息發(fā)送成功之后,由于沒有消費(fèi)者,所以這條消息并不會(huì)被消費(fèi)。打開 RabbitMQ 管理頁面,點(diǎn)擊到 Queues 選項(xiàng)卡,10s 之后,我們會(huì)發(fā)現(xiàn)消息已經(jīng)不見了:

很簡(jiǎn)單吧!

單條消息設(shè)置過期時(shí)間,就是在消息發(fā)送的時(shí)候設(shè)置一下消息有效期即可。

2.2 隊(duì)列消息過期

給隊(duì)列設(shè)置消息過期時(shí)間,方式如下:

@Bean
Queue queue() {
    Map<String, Object> args = new HashMap<>();
    args.put("x-message-ttl", 10000);
    return new Queue(JAVABOY_QUEUE_DEMO, true, false, false, args);
}

設(shè)置完成后,我們修改消息的發(fā)送邏輯,如下:

@RestController
public class HelloController {
    @Autowired
    RabbitTemplate rabbitTemplate;

    @GetMapping("/hello")
    public void hello() {
        Message message = MessageBuilder.withBody("hello javaboy".getBytes())
                .build();
        rabbitTemplate.convertAndSend(QueueConfig.JAVABOY_QUEUE_DEMO, message);
    }
}

可以看到,消息正常發(fā)送即可,不用設(shè)置消息過期時(shí)間。

OK,啟動(dòng)項(xiàng)目,發(fā)送一條消息進(jìn)行測(cè)試。查看 RabbitMQ 管理頁面,如下:

可以看到,消息隊(duì)列的 Features 屬性為 D 和 TTL,D 表示消息隊(duì)列中消息持久化,TTL 則表示消息會(huì)過期。

10s 之后刷新頁面,發(fā)現(xiàn)消息數(shù)量已經(jīng)恢復(fù)為 0。

這就是給消息隊(duì)列設(shè)置消息過期時(shí)間,一旦設(shè)置了,所有進(jìn)入到該隊(duì)列的消息都有一個(gè)過期時(shí)間了。

2.3 特殊情況

還有一種特殊情況,就是將消息的過期時(shí)間 TTL 設(shè)置為 0,這表示如果消息不能立馬消費(fèi)則會(huì)被立即丟掉,這個(gè)特性可以部分替代 RabbitMQ3.0 以前支持的 immediate 參數(shù),之所以所部分代替,是因?yàn)?immediate 參數(shù)在投遞失敗會(huì)有 basic.return 方法將消息體返回(這個(gè)功能可以利用死信隊(duì)列來實(shí)現(xiàn))。

具體代碼松哥就不演示了,這個(gè)應(yīng)該比較容易。

3. 死信隊(duì)列

有小伙伴不禁要問,被刪除的消息去哪了?真的被刪除了嗎?非也非也!這就涉及到死信隊(duì)列了,接下來我們來看看死信隊(duì)列。

3.1 死信交換機(jī)

死信交換機(jī),Dead-Letter-Exchange 即 DLX。

死信交換機(jī)用來接收死信消息(Dead Message)的,那什么是死信消息呢?一般消息變成死信消息有如下幾種情況:

  • 消息被拒絕(Basic.Reject/Basic.Nack) ,井且設(shè)置requeue 參數(shù)為false
  • 消息過期
  • 隊(duì)列達(dá)到最大長(zhǎng)度

當(dāng)消息在一個(gè)隊(duì)列中變成了死信消息后,此時(shí)就會(huì)被發(fā)送到 DLX,綁定 DLX 的消息隊(duì)列則稱為死信隊(duì)列。

DLX 本質(zhì)上也是一個(gè)普普通通的交換機(jī),我們可以為任意隊(duì)列指定 DLX,當(dāng)該隊(duì)列中存在死信時(shí),RabbitMQ 就會(huì)自動(dòng)的將這個(gè)死信發(fā)布到 DLX 上去,進(jìn)而被路由到另一個(gè)綁定了 DLX 的隊(duì)列上(即死信隊(duì)列)。

3.2 死信隊(duì)列

這個(gè)好理解,綁定了死信交換機(jī)的隊(duì)列就是死信隊(duì)列。

3.3 實(shí)踐

我們來看一個(gè)簡(jiǎn)單的例子。

首先我們來創(chuàng)建一個(gè)死信交換機(jī),接著創(chuàng)建一個(gè)死信隊(duì)列,再將死信交換機(jī)和死信隊(duì)列綁定到一起:

public static final String DLX_EXCHANGE_NAME = "dlx_exchange_name";
public static final String DLX_QUEUE_NAME = "dlx_queue_name";
public static final String DLX_ROUTING_KEY = "dlx_routing_key";

/**
 * 配置死信交換機(jī)
 *
 * @return
 */
@Bean
DirectExchange dlxDirectExchange() {
    return new DirectExchange(DLX_EXCHANGE_NAME, true, false);
}
/**
 * 配置死信隊(duì)列
 * @return
 */
@Bean
Queue dlxQueue() {
    return new Queue(DLX_QUEUE_NAME);
}
/**
 * 綁定死信隊(duì)列和死信交換機(jī)
 * @return
 */
@Bean
Binding dlxBinding() {
    return BindingBuilder.bind(dlxQueue())
            .to(dlxDirectExchange())
            .with(DLX_ROUTING_KEY);
}

這其實(shí)跟普通的交換機(jī),普通的消息隊(duì)列沒啥兩樣。

接下來為消息隊(duì)列配置死信交換機(jī),如下:

@Bean
Queue queue() {
    Map<String, Object> args = new HashMap<>();
    //設(shè)置消息過期時(shí)間
    args.put("x-message-ttl", 0);
    //設(shè)置死信交換機(jī)
    args.put("x-dead-letter-exchange", DLX_EXCHANGE_NAME);
    //設(shè)置死信 routing_key
    args.put("x-dead-letter-routing-key", DLX_ROUTING_KEY);
    return new Queue(JAVABOY_QUEUE_DEMO, true, false, false, args);
}

就兩個(gè)參數(shù):

  • x-dead-letter-exchange:配置死信交換機(jī)。
  • x-dead-letter-routing-key:配置死信 routing_key

這就配置好了。

將來發(fā)送到這個(gè)消息隊(duì)列上的消息,如果發(fā)生了 nack、reject 或者過期等問題,就會(huì)被發(fā)送到 DLX 上,進(jìn)而進(jìn)入到與 DLX 綁定的消息隊(duì)列上。

死信消息隊(duì)列的消費(fèi)和普通消息隊(duì)列的消費(fèi)并無二致:

@RabbitListener(queues = QueueConfig.DLX_QUEUE_NAME)
public void dlxHandle(String msg) {
    System.out.println("dlx msg = " + msg);
}

很容易吧~

4. 小結(jié)

好啦,今天就和小伙伴們聊一聊 RabbitMQ 中的消息過期問題,感興趣的小伙伴可以去試試哦~

參考資料:

Java RabbitMQ的TTL和DLX全面精解

到此這篇關(guān)于Java RabbitMQ 中的消息長(zhǎng)期不消費(fèi)會(huì)過期嗎的文章就介紹到這了,更多相關(guān)Java RabbitMQ 消息過期內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java創(chuàng)建多線程服務(wù)器流程

    Java創(chuàng)建多線程服務(wù)器流程

    這篇文章主要介紹了Java創(chuàng)建多線程服務(wù)器流程,以下實(shí)例演示了如何使用Socket類的accept()方法和ServerSocket類的MultiThreadServer(socketname)方法來實(shí)現(xiàn)多線程服務(wù)器程序
    2023-05-05
  • Java日期工具類DateUtils實(shí)例詳解

    Java日期工具類DateUtils實(shí)例詳解

    這篇文章主要為大家詳細(xì)介紹了Java日期工具類DateUtils實(shí)例,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-12-12
  • Spring RestTemplate簡(jiǎn)化HTTP通信實(shí)現(xiàn)功能探究

    Spring RestTemplate簡(jiǎn)化HTTP通信實(shí)現(xiàn)功能探究

    這篇文章主要為大家介紹了Spring框架中的RestTemplate,如果你是個(gè)Java程序員,那么你肯定知道Spring框架的重要性,在Spring的眾多工具中,RestTemplate是用來簡(jiǎn)化HTTP通信的一個(gè)強(qiáng)大工具
    2024-01-01
  • Java不可變類機(jī)制淺析

    Java不可變類機(jī)制淺析

    所謂的不可變類是指這個(gè)類的實(shí)例一旦創(chuàng)建完成后,就不能改變其成員變量值。如JDK內(nèi)部自帶的很多不可變類:Interger、Long和String等。接下來通過本文給大家介紹Java不可變類機(jī)制,需要的朋友參考下
    2017-02-02
  • springboot springmvc拋出全局異常的解決方法

    springboot springmvc拋出全局異常的解決方法

    這篇文章主要為大家詳細(xì)介紹了springboot springmvc拋出全局異常的解決方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-06-06
  • Java?@Scheduled定時(shí)任務(wù)不執(zhí)行解決辦法

    Java?@Scheduled定時(shí)任務(wù)不執(zhí)行解決辦法

    這篇文章主要給大家介紹了關(guān)于Java?@Scheduled定時(shí)任務(wù)不執(zhí)行解決的相關(guān)資料,當(dāng)@Scheduled定時(shí)任務(wù)不執(zhí)行時(shí)可以根據(jù)以下步驟進(jìn)行排查和解決,需要的朋友可以參考下
    2023-10-10
  • TreeSet詳解和使用示例_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理

    TreeSet詳解和使用示例_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理

    TreeSet是一個(gè)有序的集合,它的作用是提供有序的Set集合。這篇文章主要介紹了TreeSet使用示例,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-05-05
  • 淺析scala中map與flatMap的區(qū)別

    淺析scala中map與flatMap的區(qū)別

    這篇文章主要介紹了淺析scala中map與flatMap的區(qū)別,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-06-06
  • Java中Future和FutureTask的示例詳解及使用

    Java中Future和FutureTask的示例詳解及使用

    Java中的Future和FutureTask通常和線程池搭配使用,用來獲取線程池返回執(zhí)行后的返回值,下面這篇文章主要給大家介紹了關(guān)于Java中Future和FutureTask使用的相關(guān)資料,需要的朋友可以參考下
    2021-11-11
  • Spring Boot 校驗(yàn)用戶上傳的圖片文件(兩種方式)

    Spring Boot 校驗(yàn)用戶上傳的圖片文件(兩種方式)

    圖片上傳是現(xiàn)代應(yīng)用中非常常見的一種功能,也是風(fēng)險(xiǎn)比較高的一個(gè)地方,惡意用戶可能會(huì)上傳一些病毒、木馬,本文給大家介紹兩種對(duì)圖片文件進(jìn)行校驗(yàn)的方法,感興趣的朋友一起看看吧
    2023-11-11

最新評(píng)論

峡江县| 东乌珠穆沁旗| 南华县| 文昌市| 宁陵县| 搜索| 扎囊县| 靖边县| 桐乡市| 台中县| 水富县| 阜城县| 石狮市| 建德市| 拉孜县| 新河县| 绥滨县| 从江县| 松江区| 高淳县| 平远县| 建始县| 曲松县| 山西省| 呼和浩特市| 台南市| 唐海县| 大同市| 焦作市| 民县| 虎林市| 泰来县| 辽中县| 大名县| 安康市| 万源市| 永州市| 阳江市| 呼伦贝尔市| 怀柔区| 长白|