RabbitMQ 中TTL消息介紹
1. 前言
Hello,大家好。本小節(jié)會(huì)為同學(xué)們介紹 RabbitMQ 中自帶的另一種機(jī)制,就是 TTL 消息,以及 TTL 消息隊(duì)列。TTL 消息和 TTL 消息隊(duì)列是我們實(shí)際工作中使用頻率較高的一種機(jī)制,這種機(jī)制規(guī)定了在特定條件下,消息的有效時(shí)間,通過(guò)應(yīng)用這種機(jī)制,我們可以很靈活地對(duì)消息進(jìn)行控制。
TTL 消息以及 TTL 消息隊(duì)列這種機(jī)制,一般不會(huì)單獨(dú)使用,在實(shí)際工作中都會(huì)搭配死信隊(duì)列一并使用,那么在本節(jié)中,會(huì)首先為同學(xué)們介紹何為 TTL 消息以及 TTL 消息隊(duì)列,在下一節(jié)就會(huì)為同學(xué)們介紹什么是死信隊(duì)列了。
話不多說(shuō),就讓我們先來(lái)了解一下什么是 TTL 消息吧。
本節(jié)主要內(nèi)容:
- TTL 消息概述;
2. TTL 消息概述
基礎(chǔ)概念:
TTL,全稱為 Time to Live ,即生存時(shí)間。 說(shuō)到這個(gè) TTL ,想必大家都有所接觸,這個(gè) TTL 并不是 RabbitMQ 中獨(dú)有的特性,我們?cè)谶M(jìn)行應(yīng)用程序開(kāi)發(fā)時(shí),我們使用的其他工具中,也具備這個(gè)生存時(shí)間的概念,只不過(guò)描述的可能不一樣,但是含義相同。那么在 RabbitMQ 中,TTL 描述的又是什么呢?
在 RabbitMQ 中,TTL 這一概念是作用于消息和消息隊(duì)列上,即為消息以及消息隊(duì)列規(guī)定了一個(gè)生存時(shí)間,當(dāng)消息或消息隊(duì)列的生存時(shí)間超過(guò)了 TTL 所規(guī)定的生存時(shí)間之后,消息就會(huì)失效,且不會(huì)被消費(fèi)。
其中,對(duì)于消息來(lái)說(shuō),一旦消息的生存時(shí)間超過(guò)了 TTL 所規(guī)定的消息生存時(shí)間,那么,這條消息會(huì)立即失效,并且不會(huì)被任何消費(fèi)者消費(fèi),且會(huì)變成一種死信,并最終會(huì)被 RabbitMQ 放入死信隊(duì)列中(相關(guān)概念下節(jié)介紹,下同)。
而對(duì)于消息隊(duì)列來(lái)說(shuō),如果消息隊(duì)列的生存時(shí)間超過(guò)了 TTL 所規(guī)定的消息隊(duì)列的生存時(shí)間,那么消息隊(duì)列會(huì)立即失效,且該消息隊(duì)列中的消息也會(huì)隨著消息隊(duì)列的失效而失效。 這就提醒我們,在對(duì)應(yīng)用程序中的消息進(jìn)行操作時(shí),可以根據(jù)業(yè)務(wù)需要來(lái)設(shè)置專門(mén)一條消息的生存時(shí)間,也可以設(shè)置同一消息類(lèi)型的消息隊(duì)列的生存時(shí)間,以靈活控制消息的有效期限。
從消費(fèi)者的角度來(lái)說(shuō),我們也可以這樣理解:在消息被設(shè)置了 TTL 之后,如果這個(gè)消息的等待時(shí)間超過(guò)了 TTL ,則這個(gè)消息就不會(huì)被任何消費(fèi)者消費(fèi);從生產(chǎn)者的角度來(lái)說(shuō),生產(chǎn)者發(fā)送了一條消息到 RabbitMQ Server 中,且已經(jīng)設(shè)置了 TTL ,如果這個(gè)消息的等待時(shí)間超過(guò)了 TTL ,即使有消費(fèi)者來(lái)接收消息,這個(gè)消息也不會(huì)被接收,同時(shí),生產(chǎn)者也不會(huì)再次發(fā)送相同的消息。
在了解了 TTL 的基礎(chǔ)概念之后,我們還需要了解如何通過(guò)代碼,來(lái)配置 TTL 消息。
代碼實(shí)現(xiàn):
配置 TTL ,需要我們?cè)谏a(chǎn)端進(jìn)行配置,代碼如下:
ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory.setHost("xx");
connectionFactory.setPort("5672");
connectionFactory.setVirtualHost("/");
Connection connection = connectionFactory.newConnection();
Channel channel = connection.createChanel();
AMQP.BasicProperties properties = new AMQP.BasicProperties.Builder()
.deliveryMode(2)
.expiration("10000")
.contentEncoding("UTF-8")
.build();
channel.basicPublish(exchangeName, routingKey, true, properties, msg.getBytes());
代碼解釋:
第 1-5 行,我們使用 ConnectionFactory 創(chuàng)建了一個(gè)客戶端連接 RabbitMQ Server 的連接。
第 6 行,我們使用建立好的連接,來(lái)創(chuàng)建了一個(gè)頻道 channel 。
第 7-12 行,我們使用 AMQP.BasicProperties 來(lái)初始化了一個(gè)具體消息的 properties 參數(shù),初始化 properties 的過(guò)程采用了 AMQP 的調(diào)用鏈模式,即通過(guò) AMQP.BasicProperties.Builder() 來(lái)對(duì) properties 進(jìn)行初始化。
其中,deliveryMode 表示 properties 的投遞模式,2 表示持久化投遞,即 RabbitMQ Server 重啟之后依然有效;contentEncoding 表示 properties 的編碼模式,這里是支持中文的 UTF-8 格式;expiration 屬性就是來(lái)對(duì)當(dāng)前的消息設(shè)置生存時(shí)間的屬性,其單位為毫秒,這里設(shè)置的 TTL 為 10 秒, 當(dāng)我們對(duì) properties 的屬性設(shè)置完畢后,調(diào)用 build 方法即可完成 properties 的構(gòu)建。
第 13 行,我們使用 channel 的 basicPublish 方法,將消息發(fā)送到 RabbitMQ Server 中,這里我們直接來(lái)看 basicPublish 方法的第四個(gè)參數(shù),其他參數(shù)已經(jīng)介紹很多次了,這里不再介紹。
我們都知道,在 RabbitMQ 中,一條具體的消息被分為了消息體和消息參數(shù)兩個(gè)部分, 其中,消息體指的是我們應(yīng)用程序中的數(shù)據(jù),消息參數(shù)指的是針對(duì)這一應(yīng)用程序中的數(shù)據(jù)進(jìn)行配置的一系列參數(shù),常見(jiàn)的參數(shù)有字符集、請(qǐng)求頭、投遞方式等。basicPublish 方法的第三個(gè)參數(shù)指的就是一條消息的消息參數(shù),即我們通過(guò)調(diào)用鏈模式來(lái)構(gòu)造出的 properties 參數(shù)。
將我們構(gòu)造好的 properties 參數(shù)一同發(fā)送到 RabbitMQ Server 中,那么,我們配置的 properties 的屬性就會(huì)生效,即該條消息的 TTL 為 10 秒。
上述代碼是配置 TTL 消息的,那么 TTL 消息隊(duì)列又該如何配置呢,我們看以下代碼:
代碼實(shí)現(xiàn):
// 省略客戶端連接 RabbitMQ Server 代碼
Map<String, Object> queueArgumentMap = new HashMap<>();
queueArgumentMap.put("x-message-ttl", "10000");
channel.queueDeclare(queueName, true, true, false, queueArgumentMap);
代碼解釋:
第 2-3 行,我們聲明了一個(gè)名為 queueArgumentMap 的 HashMap ,并且指定 key 為 x-message-ttl ,value 為 10000 ,且都是字符串類(lèi)型。
第 4 行,我們使用 channel 的 queueDeclare 方法,來(lái)聲明一個(gè)隊(duì)列,這里我們重點(diǎn)看 queueDeclare 方法的第五個(gè)參數(shù),這個(gè)參數(shù)是一個(gè) Map 類(lèi)型的 arguments 參數(shù),是專門(mén)來(lái)對(duì)隊(duì)列進(jìn)行額外配置的參數(shù), 其值就是我們聲明的這個(gè) queueArgumentMap 。
在 queueArgumentMap 中,key 為 RabbitMQ 官方規(guī)定的設(shè)置 TTL 的 key 值,value 即為我們要設(shè)置的 TTL 的具體時(shí)間,單位為毫秒,這里同樣設(shè)置為了 10 秒。
Tips: 1.在實(shí)際工作中,給消息或者消息隊(duì)列設(shè)置 TTL 是很常見(jiàn)的,所以需要同學(xué)們完全掌握本節(jié)內(nèi)容,這樣才能在工作中運(yùn)用自如;
2. queueArgumentMap 中 key 的指定必須要按照 RabbitMQ 官方給出的 key 值來(lái)聲明,不能自定義聲明,否則,將不會(huì)起到任何作用;
3. 在為消息或消息隊(duì)列設(shè)置了 TTL 之后,如果我們想要看到直觀地結(jié)果,我們可以自行編寫(xiě)一個(gè)測(cè)試程序,并結(jié)合 RabbitMQ 的消息管控臺(tái)來(lái)觀察,這樣效果會(huì)很明顯。
3. 小結(jié)

本小節(jié)為同學(xué)們介紹了 RabbitMQ 中,如何為消息以及消息隊(duì)列設(shè)置 TTL 生存時(shí)間。從 TTL 的基礎(chǔ)概念開(kāi)始,到 TTL 消息以及 TTL 消息隊(duì)列的編碼實(shí)現(xiàn)結(jié)束,詳細(xì)介紹了 TTL 是什么、TTL 的作用,以及不同組件下如何配置 TTL ,TTL 在實(shí)際工作中應(yīng)用較多,希望同學(xué)們可以完全掌握通過(guò)代碼的方式來(lái)對(duì)消息和消息隊(duì)列配置 TTL ,這樣我們才能對(duì)消息更加靈活地進(jìn)行配置。