Springboot整合RabbitMq測試TTL的方法詳解
什么是TTL?
在RabbitMq
中,存在一種高級特性
TTL
。
TTL
即Time To Live
的縮寫,含義為存活時(shí)間
或者過期時(shí)間
。即:
設(shè)定消息在隊(duì)列中存活的時(shí)間。
當(dāng)指定時(shí)間內(nèi)
,消息依舊未被消費(fèi)
,則由隊(duì)列自動將其刪除。
如何設(shè)置TTL?
既然涉及到設(shè)定消息的存活時(shí)間
,在RabbitMq
中,存在兩種設(shè)置方式:
- 設(shè)置整個(gè)隊(duì)列的過期時(shí)間。
- 設(shè)置單個(gè)消息的過期時(shí)間。
設(shè)定整個(gè)隊(duì)列的過期時(shí)間
按照上一篇文章的依賴導(dǎo)入和配置編寫方式進(jìn)行。
配置類編寫
在原有基礎(chǔ)之上,新創(chuàng)建幾個(gè)配置的bean
類,申明bean對象,并進(jìn)行交換機(jī)
與隊(duì)列
的關(guān)聯(lián),如下所示:、
package cn.linkpower.config; 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 java.util.HashMap; import java.util.Map; @Configuration public class MQConfiguration { // =========================== Direct 直連模式 ================================== //隊(duì)列名稱 public static final String QUEUQ_NAME = "xiangjiao.queue"; //交換器名稱 public static final String EXCHANGE = "xiangjiao.exchange"; //路由key public static final String ROUTING_KEY = "xiangjiao.routingKey"; // =========================== Direct 普通隊(duì)列申明 和 交換機(jī)綁定 =================== //創(chuàng)建隊(duì)列 @Bean(value = "getQueue") public Queue getQueue(){ //QueueBuilder.durable(QUEUQ_NAME).build(); return new Queue(QUEUQ_NAME); } //實(shí)例化交換機(jī) @Bean(value = "getDirectExchange") public DirectExchange getDirectExchange(){ //DirectExchange(String name, boolean durable, boolean autoDelete) /** * 參數(shù)一:交換機(jī)名稱;<br> * 參數(shù)二:是否永久;<br> * 參數(shù)三:是否自動刪除;<br> */ //ExchangeBuilder.directExchange(EXCHANGE).durable(true).build(); return new DirectExchange(EXCHANGE, true, false); //綁定消息隊(duì)列和交換機(jī) @Bean public Binding bindExchangeAndQueue(@Qualifier(value = "getDirectExchange") DirectExchange exchange, @Qualifier(value = "getQueue") Queue queue){ return BindingBuilder.bind(queue).to(exchange).with(ROUTING_KEY); // =========================== TTL ================================ public static final String ttl_queue_name = "xiangjiao.ttl.queue"; public static final String ttl_exchange_name = "xiangjiao.ttl.exchange"; public static final String ttl_routing_key = "xiangjiao.ttl.routingKey"; @Bean(value = "getTtlQueue") public Queue getTtlQueue(){ // 設(shè)置 ttl 隊(duì)列,并設(shè)定 x-message-ttl 參數(shù),表示 消息存活最大時(shí)間,單位 ms //return QueueBuilder.durable(ttl_queue_name).withArgument("x-message-ttl",10000).build(); Map<String, Object> arguments = new HashMap<>(); arguments.put("x-message-ttl",10000); return new Queue(ttl_queue_name,true,false,false,arguments); @Bean(value = "getTTlExchange") public DirectExchange getTTlExchange(){ // 設(shè)置交換機(jī)屬性,并保證交換機(jī)持久化 return new DirectExchange(ttl_exchange_name, true, false); public Binding bindExchangeAndQueueTTL(@Qualifier(value = "getTTlExchange") DirectExchange getTTlExchange, @Qualifier(value = "getTtlQueue") Queue queue){ return BindingBuilder.bind(queue).to(getTTlExchange).with(ttl_routing_key); }
對比原有的配置類,不難發(fā)現(xiàn)區(qū)別:
對
隊(duì)列
設(shè)置過期屬性
,只需要傳遞一個(gè)x-message-ttl
的屬性值即可。(單位:ms)
Map<String, Object> arguments = new HashMap<>(); arguments.put("x-message-ttl",10000); return new Queue(ttl_queue_name,true,false,false,arguments);
然后定義交換機(jī)類型,并將指定的交換機(jī)和隊(duì)列進(jìn)行綁定。
為了測試效果,暫未定義任何該隊(duì)列的消費(fèi)者信息。
測試
為了便于測試,需要定義一個(gè)接口,生產(chǎn)新的數(shù)據(jù)信息,并將數(shù)據(jù)向?qū)?yīng)的Exchange
中傳遞。
/** * 發(fā)送消息,指定ttl參數(shù)信息(隊(duì)列) * @return */ @RequestMapping("/sendQueueTtl") @ResponseBody public String sendQueueTtl(){ //發(fā)送10條消息 for (int i = 0; i < 10; i++) { String msg = "msg"+i; System.out.println("發(fā)送消息 msg:"+msg); rabbitmqService.sendMessage(MQConfiguration.ttl_exchange_name,MQConfiguration.ttl_routing_key,msg); //每兩秒發(fā)送一次 try { Thread.sleep(8000); } catch (InterruptedException e) { e.printStackTrace(); } } return "send ok"; }
兩條消息之間的過期時(shí)間為
8s
。
請求鏈接進(jìn)行測試,查看Rabbitmq web
視圖信息:
http://localhost/sendQueueTtl
查看控制臺輸出日志:
消息正常發(fā)送到了Exchange
,同時(shí)Exchange 也將消息推送到了指定的隊(duì)列 !
設(shè)置有
Confirm
和Return
監(jiān)聽。
【說明:】
給隊(duì)列設(shè)定時(shí)間后,單位時(shí)間內(nèi)的消息如果未被消費(fèi),則隊(duì)列會將其中的數(shù)據(jù)進(jìn)行刪除處理。
對單個(gè)消息設(shè)定過期時(shí)間
上面的操作和測試,已經(jīng)驗(yàn)證對隊(duì)列
設(shè)定過期時(shí)間
,會導(dǎo)致所有的消息過期時(shí)間都是一樣
的現(xiàn)象。
但實(shí)際開發(fā)中,可能一個(gè)隊(duì)列
需要存放不同過期時(shí)間
的消息信息,如果需要進(jìn)行實(shí)現(xiàn),就不能再設(shè)定隊(duì)列的過期時(shí)間信息了,需要采取下面要說到的針對單個(gè)消息,設(shè)置不同過期時(shí)間
。
配置
既然是針對單個(gè)消息
設(shè)定不同的過期時(shí)間
操作,則需要去掉隊(duì)列過期
設(shè)置。
為了測試的簡單化,此處采取直連 Direct 交換機(jī)
類型,進(jìn)行交換機(jī)和隊(duì)列數(shù)據(jù)的綁定方式。如下所示:
// =========================== Direct 直連模式 ================================== //隊(duì)列名稱 public static final String QUEUQ_NAME = "xiangjiao.queue"; //交換器名稱 public static final String EXCHANGE = "xiangjiao.exchange"; //路由key public static final String ROUTING_KEY = "xiangjiao.routingKey"; // =========================== Direct 普通隊(duì)列申明 和 交換機(jī)綁定 =================== //創(chuàng)建隊(duì)列 @Bean(value = "getQueue") public Queue getQueue(){ //QueueBuilder.durable(QUEUQ_NAME).build(); return new Queue(QUEUQ_NAME); } //實(shí)例化交換機(jī) @Bean(value = "getDirectExchange") public DirectExchange getDirectExchange(){ //DirectExchange(String name, boolean durable, boolean autoDelete) /** * 參數(shù)一:交換機(jī)名稱;<br> * 參數(shù)二:是否永久;<br> * 參數(shù)三:是否自動刪除;<br> */ //ExchangeBuilder.directExchange(EXCHANGE).durable(true).build(); return new DirectExchange(EXCHANGE, true, false); } //綁定消息隊(duì)列和交換機(jī) @Bean public Binding bindExchangeAndQueue(@Qualifier(value = "getDirectExchange") DirectExchange exchange, @Qualifier(value = "getQueue") Queue queue){ return BindingBuilder.bind(queue).to(exchange).with(ROUTING_KEY); }
對于消息的發(fā)送,依舊沿用之前寫的發(fā)送處理方式
設(shè)定
confirm
和return
監(jiān)聽,保證消息能夠正常到達(dá)指定的隊(duì)列中。
測試
編寫一個(gè)測試的接口,設(shè)定單個(gè)消息的過期時(shí)間屬性
,保證不同消息具備不同的過期時(shí)間
。
在之前博客中,針對消息的持久化
設(shè)置,需要保證消息向隊(duì)列設(shè)定屬性時(shí),傳遞一個(gè)deliveryMode
參數(shù)值信息。
同理,設(shè)定每個(gè)消息的過期時(shí)間,也需要設(shè)定對應(yīng)的屬性信息。如下所示:
/** * 發(fā)送消息,指定ttl參數(shù)信息(單個(gè)消息); * 測試需要將消息消費(fèi)者關(guān)閉監(jiān)聽 * @return */ @RequestMapping("/sendTtl") @ResponseBody public String sendTtl(){ //發(fā)送10條消息 for (int i = 0; i < 10; i++) { String msg = "msg"+i; System.out.println("發(fā)送消息 msg:"+msg); MessageProperties messageProperties = new MessageProperties(); messageProperties.setExpiration("5000"); // 針對消息設(shè)定時(shí)限 // 將消息數(shù)據(jù)和設(shè)置屬性進(jìn)行封裝,采取消息發(fā)送模板,將消息數(shù)據(jù)推送至指定的交換機(jī) exchange 中 Message message = new Message(msg.getBytes(), messageProperties); rabbitmqService.sendMessage(MQConfiguration.EXCHANGE, MQConfiguration.ROUTING_KEY,message); //每兩秒發(fā)送一次 try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } } return "send ok"; }
上面代碼的編寫核心為將消息內(nèi)容體和消息對象屬性進(jìn)行封裝
。
MessageProperties messageProperties = new MessageProperties(); messageProperties.setExpiration("5000"); // 針對消息設(shè)定時(shí)限 // 將消息數(shù)據(jù)和設(shè)置屬性進(jìn)行封裝,采取消息發(fā)送模板,將消息數(shù)據(jù)推送至指定的交換機(jī) exchange 中 Message message = new Message(msg.getBytes(), messageProperties);
引申一點(diǎn):消息的持久化
Springboot 2.x ——RabbitTemplate為什么會默認(rèn)消息持久化?
請求連接進(jìn)行測試:
http://localhost/sendTtl
查看控制臺打印日志情況:
總結(jié)
1、設(shè)置隊(duì)列過期
時(shí)間使用參數(shù):x-message-ttl
,單位:ms
(毫秒),會對整個(gè)隊(duì)列消息統(tǒng)一過期
。
2、設(shè)置消息過期
時(shí)間使用參數(shù):expiration
。單位:ms
(毫秒),當(dāng)該消息在隊(duì)列頭部
時(shí)(消費(fèi)時(shí)),會單獨(dú)判斷
這一消息是否過期
。
3、如果兩者都進(jìn)行了設(shè)置,以時(shí)間短的為準(zhǔn)。
代碼下載
到此這篇關(guān)于Springboot整合RabbitMq測試TTL的文章就介紹到這了,更多相關(guān)Springboot整合RabbitMq內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
利用Intellij Idea連接遠(yuǎn)程服務(wù)器實(shí)現(xiàn)遠(yuǎn)程上傳部署功能
大家在使用Intellij Idea開發(fā)程序的時(shí)候,是不是需要部署到遠(yuǎn)程SSH服務(wù)器運(yùn)行呢,當(dāng)然也可以直接在idea軟件內(nèi)容實(shí)現(xiàn)配置部署操作,接下來通過本文給大家分享利用Intellij Idea連接遠(yuǎn)程服務(wù)器實(shí)現(xiàn)遠(yuǎn)程上傳部署功能,感興趣的朋友跟隨小編一起看看吧2021-05-05SpringBoot中間件ORM框架實(shí)現(xiàn)案例詳解(Mybatis)
這篇文章主要介紹了SpringBoot中間件ORM框架實(shí)現(xiàn)案例詳解(Mybatis),本篇文章提煉出mybatis最經(jīng)典、最精簡、最核心的代碼設(shè)計(jì),來實(shí)現(xiàn)一個(gè)mini-mybatis,從而熟悉并掌握ORM框架的涉及實(shí)現(xiàn),需要的朋友可以參考下2023-07-07IDEA卡在”正在解析Maven依賴項(xiàng)“的解決方法
在創(chuàng)建新的SpringBoot項(xiàng)目時(shí),始終卡在"正在解析Maven依賴項(xiàng)…",本文小編給大家介紹了幾種相關(guān)的解決方案,具有一定的參考價(jià)值,需要的朋友可以參考下2023-11-11SpringBoot中的MongoTemplate的各種條件查詢示例詳解
這篇文章主要介紹了SpringBoot中的MongoTemplate的各種條件查詢示例詳解,本文通過示例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借價(jià)值,需要的朋友參考下吧2024-01-01Java23種設(shè)計(jì)模式中的單例模式你了解嗎
這篇文章主要為大家詳細(xì)介紹了Java23種設(shè)計(jì)模式中的單例模式,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助2022-02-02C++/java 繼承類的多態(tài)詳解及實(shí)例代碼
這篇文章主要介紹了C++/java 繼承類的多態(tài)詳解及實(shí)例代碼的相關(guān)資料,需要的朋友可以參考下2017-02-02springboot+vue實(shí)現(xiàn)登錄功能的最新方法整理
最近做項(xiàng)目時(shí)使用到了springboot+vue實(shí)現(xiàn)登錄功能的技術(shù),所以下面這篇文章主要給大家介紹了關(guān)于springboot+vue實(shí)現(xiàn)登錄功能的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-06-06通過實(shí)例了解java spring使用構(gòu)造器注入的原因
這篇文章主要介紹了通過實(shí)例了解spring使用構(gòu)造器注入的原因,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-12-12Mybatis-Plus開發(fā)提速器generator的使用
本文就介紹這款基于Mybatis-Plus的代碼自助生成器,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-07-07