<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          RabbitMq如何確保消息不丟失

          共 1811字,需瀏覽 4分鐘

           ·

          2020-09-25 22:33

          上篇寫了掌握Rabbitmq幾個(gè)重要概念,從一條消息說(shuō)起,這篇來(lái)總結(jié)關(guān)于消息丟失讓人頭痛的事情。網(wǎng)絡(luò)故障、服務(wù)器重啟、硬盤損壞等都會(huì)導(dǎo)致消息的丟失。消息從生產(chǎn)到消費(fèi)主要結(jié)果以下幾個(gè)階段如下圖。

          ①生產(chǎn)階段,生產(chǎn)者創(chuàng)建消息,經(jīng)過(guò)網(wǎng)絡(luò)發(fā)送到rabbit服務(wù)器

          ②消息存儲(chǔ)階段,首先被發(fā)送到交換器然后經(jīng)過(guò)路由算法,到達(dá)隊(duì)列,等待被拉取消費(fèi)

          ③消費(fèi)階段,消費(fèi)者經(jīng)過(guò)網(wǎng)絡(luò)從rabbit服務(wù)器拉取消息進(jìn)行消費(fèi)?


          這三個(gè)階段都有可能消息丟失,下面一一分析。

          消息存儲(chǔ)階段

          正常情況下,我們使用BasicPublish方法發(fā)送消息到交換器上然后路由到隊(duì)列上面,消費(fèi)者還沒(méi)進(jìn)行消費(fèi),此時(shí)服務(wù)器重啟了(隊(duì)列、交換器使用默認(rèn)的創(chuàng)建方式),會(huì)發(fā)生什么?答案是:消息丟失。原因很簡(jiǎn)單:消息在內(nèi)存中,沒(méi)有刷盤,并且,他們默認(rèn)是非持久化的,服務(wù)重啟之后,它們需要重新創(chuàng)建,消息自然就丟失!
          還好,Rabbit提供持久化的機(jī)制,隊(duì)列、交換器創(chuàng)建的時(shí)候,durable屬性設(shè)置為true,同時(shí)消息投遞模式(delivery mode)設(shè)置為2,則消息標(biāo)記成持久化。這樣可以避免服務(wù)器重啟消息丟失的情況。

          發(fā)送階段

          由于發(fā)布操作不返回任何信息給生產(chǎn)者,那你怎么知道服務(wù)器是否已經(jīng)持久化了持久消息到硬盤呢?服務(wù)器可能在把消息寫入磁盤前就宕機(jī)了,消息因此而丟失!

          ?有。)

          Rabbit提供兩中解決方案,事務(wù),但是性能會(huì)大打折扣,而且會(huì)使生產(chǎn)者應(yīng)用程序產(chǎn)生同步。生產(chǎn)環(huán)境一般不會(huì)采用;另外一種方案是確認(rèn)模式。也很簡(jiǎn)單,消息路由給所有匹配的訂閱隊(duì)列中,之后會(huì)異步的告之生產(chǎn)者。使用channel.ConfirmSelect()方法,使信道開(kāi)啟確認(rèn)模式。然后注入兩個(gè)回調(diào)函數(shù),ack和nack事件。
          channel.BasicAcks += (sender, ev) =>                {                    Console.WriteLine("消息已經(jīng)確認(rèn)收到" + ev.DeliveryTag);
          };
          channel.BasicNacks += (sender, ev) => { Console.WriteLine("消息未確認(rèn)" + ev.DeliveryTag); };


          消費(fèi)階段

          你可能會(huì)問(wèn),消費(fèi)端消息怎么會(huì)丟失呢?Rabbitmq提供自動(dòng)和手動(dòng)確認(rèn)消息,然后消息從隊(duì)列中移除。如果autoAck為true,自動(dòng)確認(rèn)模式,服務(wù)器就會(huì)在消息發(fā)給消費(fèi)端后自動(dòng)將其出隊(duì)。如果因?yàn)槟承┰蜻B接中斷了,或者你的消費(fèi)端應(yīng)用發(fā)生了故障,那么消息就會(huì)丟失!

          通過(guò)把AutoAck設(shè)置為false,手工確認(rèn),告知服務(wù)器,消息已經(jīng)處理了,可以進(jìn)行消息出隊(duì)刪除。

          ?

           channel.BasicConsume(queue: queueName,                                     autoAck: false,                                     consumer: consumer);
           consumer.Received += (model, ea) =>                {                    //dosometing????????????????????channel.BasicAck(ea.DeliveryTag,?false);//確認(rèn)                };

          小結(jié):如果做了以上的處理,那么消息就不會(huì)跟你躲貓貓了。這里有性能的問(wèn)題,消息持久化,是要刷到磁盤上的會(huì)影響投遞速度,并且消息確認(rèn)也會(huì)影響到消息投遞速度。不基本上能夠滿足需求了。如果不能滿足性能需求,可以使用其他方法,比如 在每次發(fā)送消息的時(shí)候,都包含應(yīng)答隊(duì)列的名稱,這樣消費(fèi)者就可以回發(fā)應(yīng)答以確認(rèn)接受到了。如果消息應(yīng)答未在合理時(shí)間范圍內(nèi)到達(dá),生產(chǎn)者就重新發(fā)送消息。

          瀏覽 65
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  日韩人妻久久 | daxiangjiaojiujiu | 婷婷天堂站 | 日本黄色网址大全免费 | 91麻豆天美成人电影 |