??為處理生產(chǎn)者將消息推送到交換機(jī)中,交換機(jī)按照消息中的路由鍵及自身策略無(wú)法將消息投遞到指定隊(duì)列中造成消息丟失的問(wèn)題,可以使用備份交換機(jī)。
??為處理在消息隊(duì)列中到達(dá)TTL的過(guò)期消息,可采用死信交換機(jī)進(jìn)行消息轉(zhuǎn)存??梢酝ㄟ^(guò)死信交換機(jī)的方式實(shí)現(xiàn)延遲隊(duì)列的需求。
??為實(shí)現(xiàn)消息優(yōu)先消費(fèi)可以針對(duì)隊(duì)列和消息設(shè)置優(yōu)先級(jí),在消息積壓的情況下優(yōu)先級(jí)高的消息將優(yōu)先被消費(fèi)。
??通過(guò)上述描述可知,備份交換機(jī)和死信交換機(jī)處理的場(chǎng)景不同。備份交換機(jī)是處理未被路由的消息,死信交換機(jī)是處理隊(duì)列中過(guò)期的消息。但是,它們都是為了避免消息丟失提供的一種手段。
備份交換機(jī)
??生產(chǎn)者發(fā)送消息的過(guò)程中會(huì)指明交換機(jī)名稱和路由鍵,RabbitMQ接收到消息后,根據(jù)交換機(jī)名稱將消息投遞到指定交換機(jī)中,交換機(jī)再根據(jù)自身類型以及消息攜帶的路由鍵將消息投遞到隊(duì)列中。當(dāng)無(wú)法路由到隊(duì)列時(shí),并且該交換機(jī)存在備份交換機(jī),則該交換機(jī)將該消息投遞給其備份交換機(jī)進(jìn)行處理。
??備份交換機(jī)接收到消息后依舊根據(jù)其自身類型和消息路由鍵進(jìn)行消息投遞,如果依舊無(wú)法匹配到隊(duì)列中,則該消息被丟失。該過(guò)程中的具體流程如下圖所示。
備份交換機(jī)的實(shí)現(xiàn)
??備份交換機(jī)的實(shí)現(xiàn)方式包括:聲明交換機(jī)時(shí)通過(guò)參數(shù)配置和通過(guò)策略進(jìn)行配置。申明交換機(jī)時(shí)配置備份交換機(jī)如下所示。
Map<String, Object> args = new HashMap<>();
args.put("alternate-exchange","myAe");
channel.exchangeDeclare("normalExchange","direct",true,false,args);
channel.exchangeDeclare("myAe","fanout",true,false,null);
??通過(guò)上述代碼即實(shí)現(xiàn)了聲明兩個(gè)交換機(jī),其中交換機(jī)myAe是normalExchange的備份交換機(jī)。備份交換機(jī)可以理解為一個(gè)普通交換機(jī),備份交換機(jī)自身并不知曉自己是備份交換機(jī),當(dāng)某個(gè)消息無(wú)法被路由到隊(duì)列中時(shí),該交換機(jī)會(huì)查找自己的備份交換機(jī),如果存在則將消息交由備份交換機(jī)進(jìn)行處理。
??需要說(shuō)明的時(shí),備份交換機(jī)在消息入隊(duì)的時(shí)候也會(huì)根據(jù)自身類型進(jìn)行路由匹配,消息重發(fā)到備份交換機(jī)時(shí)路由鍵和從生產(chǎn)者發(fā)送時(shí)的路由鍵一致,如果是直接交換機(jī)或者主題交換機(jī),則依舊可能會(huì)導(dǎo)致消息丟失,因此備份交換機(jī)建議采用扇形交換機(jī)。
備份交換機(jī)存在以下特殊情況
- 如果備份交換機(jī)和mandatory參數(shù)一起使用,則mandatory參數(shù)無(wú)效。
- 如果備份交換機(jī)不存在,則消息丟失且生產(chǎn)者和RabbitMQ都不會(huì)有異常出現(xiàn)。
- 如果備份交換機(jī)沒(méi)有綁定隊(duì)列,則消息丟失且生產(chǎn)者和RabbitMQ都不會(huì)有異常出現(xiàn)。
- 如果備份交換機(jī)依舊無(wú)法將消息路由到隊(duì)列,則消息丟失且生產(chǎn)者和RabbitMQ都不會(huì)有異常出現(xiàn)。
死信交換機(jī)
??當(dāng)一個(gè)消息在一個(gè)隊(duì)列中變成死信后,它能被重新發(fā)送到另一個(gè)交換機(jī)中,這個(gè)交換機(jī)就是DLX(死信交換機(jī):Dead-Letter-Exchange),綁定DLX的隊(duì)列就是死信隊(duì)列。
消息變成死信一般由以下幾種情況:
- 消息被消費(fèi)者拒絕,并且設(shè)置不可重新入隊(duì)
- 消息過(guò)期(TTL)
- 隊(duì)列達(dá)到最大長(zhǎng)度。
??根據(jù)上述描述,隊(duì)列中的消息變成死信后將轉(zhuǎn)發(fā)給死信交換機(jī),因此死信交換機(jī)的設(shè)置是在聲明隊(duì)列的過(guò)程中完成的。死信交換機(jī)和備份交換機(jī)類似,其自身并不知道自己是死信交換機(jī),僅指定其為死信交換機(jī)的隊(duì)列知道其死信交換機(jī)身份的存在,本質(zhì)上死信交換機(jī)和正常交換機(jī)并不存在區(qū)別。
??死信交換機(jī)的設(shè)置可通過(guò)聲明隊(duì)列時(shí)設(shè)置和通過(guò)策略設(shè)置兩種方式實(shí)現(xiàn)。聲明隊(duì)列時(shí)設(shè)置如下所示:
Map<String, Object> args = new HashMap<>();
// 聲明該隊(duì)列的死信交換機(jī)為”dlx_exchange“
args.put("x-dead-letter-exchange","dlx_exchange");
// 聲明死信交由死信交換機(jī)處理時(shí)將路由鍵替換為dlx-routing-key
args.put("x-dead-letter-routing-key","dlx-routing-key");
channel.queueDeclare("queue",false,false,false,args);
死信交換機(jī)存在以下特殊情況
- 如果死信交換機(jī)不存在,則消息丟失且RabbitMQ都不會(huì)有異常出現(xiàn)。
- 如果死信交換機(jī)沒(méi)有綁定隊(duì)列,則消息丟失且RabbitMQ都不會(huì)有異常出現(xiàn)。
- 如果死信交換機(jī)依舊無(wú)法將消息路由到隊(duì)列,則消息丟失且RabbitMQ都不會(huì)有異常出現(xiàn)。
延遲隊(duì)列
??延遲隊(duì)列是指當(dāng)消息發(fā)送完成后,消費(fèi)者間隔一段時(shí)間后消費(fèi)該消息,可以通過(guò)死信隊(duì)列的方式實(shí)現(xiàn)延遲隊(duì)列,生產(chǎn)者把消息發(fā)送給設(shè)置了過(guò)期時(shí)間的隊(duì)列中,該隊(duì)列不存在消費(fèi)者,待消費(fèi)過(guò)期后消息會(huì)被投遞到延遲隊(duì)列(死信隊(duì)列),消費(fèi)者消費(fèi)延遲隊(duì)列中的消息,這樣就實(shí)現(xiàn)了消息的延遲處理。
優(yōu)先級(jí)隊(duì)列
??可以針對(duì)隊(duì)列和消息設(shè)置消息,在消息積壓的情況下消費(fèi)者可以優(yōu)先消費(fèi)高優(yōu)先級(jí)的消息。
??僅向設(shè)置優(yōu)先級(jí)的隊(duì)列中發(fā)送具備優(yōu)先級(jí)的消息優(yōu)先級(jí)設(shè)置才有效,如果僅對(duì)消息設(shè)置優(yōu)先級(jí)則優(yōu)先級(jí)設(shè)置無(wú)效。
??消息的優(yōu)先級(jí)默認(rèn)為0,最高為隊(duì)列設(shè)置的最大優(yōu)先級(jí),如果設(shè)置的消息優(yōu)先級(jí)大于隊(duì)列設(shè)置的最大優(yōu)先級(jí),則按照隊(duì)列最大優(yōu)先級(jí)進(jìn)行計(jì)算。
設(shè)置隊(duì)列為優(yōu)先級(jí)隊(duì)列如下所示:
Map<String,Object> map = new HashMap<>();
map.put("x-max-priority",10);
channel.queueDeclare(QUEUE_NAME,true,false,false,map);
發(fā)送具備優(yōu)先級(jí)的消息如下所示:文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-631482.html
AMQP.BasicProperties.Builder builder = new AMQP.BasicProperties.Builder();
builder.priority(20000);
AMQP.BasicProperties basicProperties = builder.build();
channel.basicPublish(EXCHANGE_NAME ,ROUTING_KEY,basicProperties,msg.getBytes());
??優(yōu)先級(jí)隊(duì)列存在以下幾點(diǎn)需要注意:文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-631482.html
- 僅在消息積壓的情況下優(yōu)先級(jí)隊(duì)列的設(shè)置才有意義
- 設(shè)置優(yōu)先級(jí)的消息僅在優(yōu)先級(jí)隊(duì)列中才能體現(xiàn)出優(yōu)先級(jí)消費(fèi)
- 一旦消息中的優(yōu)先級(jí)設(shè)置大于隊(duì)列的優(yōu)先級(jí),則按照隊(duì)列的優(yōu)先級(jí)進(jìn)行計(jì)算
總結(jié)
比較 | 備份交換機(jī) | 死信交換機(jī) | 優(yōu)先級(jí)隊(duì)列 |
---|---|---|---|
作用 | 消息無(wú)法路由到隊(duì)列中后交由備份交換機(jī)進(jìn)行處理 | 消息從隊(duì)列成為死信后交由死信交換機(jī)進(jìn)行處理 | 擠壓消息在優(yōu)先級(jí)隊(duì)列中可以按照優(yōu)先級(jí)高低被消費(fèi)者消費(fèi) |
設(shè)置方法 | 給某個(gè)交換機(jī)設(shè)置備份交換機(jī),備份交換機(jī)自身不知道自己備份交換機(jī)的身份 | 給某個(gè)隊(duì)列設(shè)置死信交換機(jī),死信交換機(jī)本身不知道自己死信交換機(jī)的身份 | 設(shè)置某個(gè)隊(duì)列的優(yōu)先級(jí),在發(fā)送消息的過(guò)程中也聲明消息優(yōu)先級(jí) |
到了這里,關(guān)于RabbitMQ 備份交換機(jī)和死信交換機(jī)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!