消息中間件消費到的消息處理失敗怎麼辦?

閱讀本文大概須要 6.2 分鐘。

做者:愛釣魚的桌子哥程序員

 

一、日趨流行的面試問法面試

 

如今網上不少面試題,主要是針對技術自己的提問,好比:你聊聊對Dubbo的理解?你說說分佈式事務是什麼?數據庫

這些問題就比如中學考試的送分題,好比默寫古詩,你只要準備了,下點功夫,都沒啥問題。微信

因此這裏對技術自己的提問,其實就至關於送分題,主要是作一個基本的區分。你能回答出來,說明你至少平時還注意積累知識,不是一個混日子的工程師。網絡

可是如今出去面試,尤爲是一些大廠的面試愈來愈難了,從之前普通的技術知識自己,如今到了會考察你不少生產環境中的一些特殊情況。架構

也就是說從之前的知識積累和背誦,到如今開始考察你的具體實踐和經驗積累。異步

好比如今可能不少面試官開始這麼問:大家項目裏用Dubbo時,有沒有遇到什麼技術問題?大家Dubbo服務的超時通常怎麼設置的?服務之間調用通常會遇到超時嗎?若是超時了會怎麼樣?分佈式

相似這樣的問題,都是在考察你對一個技術的實踐經驗,而這目前愈來愈成爲了面試的重點。性能

因此本文將經過一道面試中的經典高頻問題:消息中間件消費到的消息處理失敗了怎麼辦?學習

藉助這道經典題目,來闡述一下這個問題。咱們應該從哪些角度思考,才能作出滿分回答。

 

 

二、消息中間件在生產系統中的使用

 

 

這是一個很是典型的生產環境的問題,不少公司都會在生產系統裏使用MQ,即消息隊列,或者消息中間件。

也就是說,一個系統跟另一個系統之間進行通訊的時候,假如系統A但願發送一個消息給系統B,讓他去處理。

可是系統A不關注系統B到底怎麼處理或者有沒有處理好,因此係統A把消息發送給MQ,而後就無論這條消息的「死活」了,接着系統B從MQ裏消費出來處理便可。

至於怎麼處理,是否處理完畢,何時處理,都是系統B的事兒,與系統A無關。

上述過程,能夠經過下圖看的很清晰:

這樣的一種通訊方式,就是所謂的「異步」通訊方式

對於系統A來講,只要把消息發給MQ,而後系統B就會異步的去進行處理了,系統A不須要「同步」的等待系統B處理完。

這樣的好處是什麼呢?

兩個字:解耦

系統A要跟系統B通訊,可是他不須要關注系統B如何處理的一些細節。咱們來舉幾個例子說明:

好比,A不須要關注B何時處理完,這樣假如系統B處理一個消息要耗費10分鐘也不關係統A的事兒。

不然,系統A直接調用系統B的接口,系統B一會兒處理了10分鐘怎麼辦?難不成系統A也阻塞等待10分鐘?

再好比,系統A不須要關注系統B處理成功與否,即便系統B處理失敗了,也是系統B本身去考慮這個場景和從新嘗試處理。

不然若是系統調用系統B的接口,萬一處理失敗了報錯了,系統A受到一個調用異常該怎麼處理?

還有,系統A不須要關注系統B是否存活。萬一要是系統B掛掉了,系統A經過MQ來通訊也不須要管系統B的「死活」,系統B本身恢復了以後就能夠從MQ消費消息再次處理便可。

不然系統A直接調用系統B的接口,萬一系統B掛了,難道系統A還要把消息暫存到數據庫?等待系統B恢復了再給他發過去嗎?

這就是經過MQ進行異步通訊,讓兩個系統解耦以後的好處,能夠大幅度提高整個大系統的容錯性,增長系統的彈性,而不是到處耦合,一個系統出錯連帶致使其餘系統所有出錯。

解耦以後,即便出錯也只是大系統中的一個系統B出錯而已,不影響別人。

 

 

三、經典生產案例:早教盒子APP的發貨

 

 

接下來用一個經典的生產案例給你們說說MQ在生產的使用。

如今不少早教類的APP,都會提供早教盒子,什麼意思呢?

早教APP提供的核心服務就是三塊:

一、APP裏的早教視頻課程

二、線上微信羣的助教答疑指導

三、線下送你早教盒子,裏面有不少上課道具

這樣一個媽媽陪伴孩子上早教的過程多是這樣的:

一、首先在APP裏看早教視頻課程,孩子看着很感興趣。

二、接着媽媽從早教盒子裏取出來道具,陪孩子把視頻裏的遊戲和任務都作一遍,讓孩子加深印象

三、最後天天媽媽會打卡,有助教會來給媽媽進行答疑。

因此說,假設如今咱們要在一個早教APP裏購買一個早教課程,他的流程大體以下:

一、選擇購買早教課程

二、直接支付

三、建立訂單

四、給用戶增長課程權限

五、通知倉庫準備發早教盒子

六、通知物流公司去倉庫取早教盒子進行配送。

咱們來分析一下每一個環節。首先你要是購買一個早教課程,那麼點擊「購買」的按鈕以後,通常直接會跳入一個支付界面。

這個時候,你就能夠直接選擇支付了。此時後臺系統必定會經過支付系統跟第三方支付系統進行通訊,好比說支付寶、微信之類的,而後等待支付完成。

一旦支付完成,就會在本身內部系統幹兩個事:

第一,給這個用戶id建立一個訂單;

第二,給這個用戶id增長看某個早教視頻課程的權限。

此時用戶其實在「個人訂單」界面就能夠看到本身的訂單了,並且在「個人課程」界面,就能夠開始看早教課程的視頻了。

若是對上面過程不太理解的,再看看下面的圖,應該就清楚了:

可是如今問題主要在後面兩個步驟,如今你的訂單系統做爲核心入口,他要通知倉庫系統去扣減一個早教盒子的庫存。

同時,還得準備好早教盒子的發貨(好比說提早打包裝箱,準備一些給快遞公司使用的發貨單之類的,須要帖子箱子上)。

而後通知第三方物流公司的系統,能夠去本身的倉庫取早教盒子發貨了。

這兩個步驟須要涉及到對倉庫系統以及第三方物流公司系統的調用,那麼是採用訂單系統直接同步調用那兩個系統的方式嗎?

恐怕不妥,由於這裏最大的問題就是性能問題和可用性問題。

舉個例子,假如如今倉庫系統部署在其餘地方,由於網絡問題致使性能不好,訪問速度很慢,那麼是否是可能會致使用戶支付以後,等待了幾分鐘都看不到整個流程的完成?

或者要是說第三方物流公司的系統如今要是故障了,暫時沒法訪問,那麼會不會致使用戶支付了以後,一直沒有給用戶發貨早教盒子?

因此說,在這裏就應該引入MQ,訂單系統在完成訂單的建立以及課程的分配以後,就能夠發送一個消息到MQ,而後有一個專門的倉儲系統負責消費這個消息,接着嘗試去調用獨立倉庫系統通知發貨,以及通知第三方物流系統去配送。

整個過程,以下圖所示:

這麼作有什麼好處呢?

好處是顯而易見的,假如如今獨立倉庫系統和第三方物流系統的訪問性能忽然變得不好,大不了就是倉儲系統在後面慢慢的跟人家通訊等着人家處理完畢好了,對訂單系統是沒影響的。

對於訂單系統而言,建立訂單和分配課程都是速度很快的,而後發送個消息到MQ速度也很快。

這樣一來,用戶看到的就是一兩秒的時間支付就成功了,而後能夠查到訂單,看到本身的課程,而後訂單的物流顯示的是「待配送」的狀態。

那麼若是獨立倉庫系統或者第三方物流系統故障了,致使倉儲系統消費到一條訂單消息以後,嘗試進行發貨失敗,也就是對這條消費到的消息處理失敗。這種狀況,怎麼處理?

這就是本文最核心的地方了!!!

 

 

四、死信隊列的使用:處理失敗的消息

 

 

通常生產環境中,若是你有豐富的架構設計經驗,都會在使用MQ的時候設計兩個隊列:一個是核心業務隊列,一個是死信隊列。

核心業務隊列,就是好比上面專門用來讓訂單系統發送訂單消息的,而後另一個死信隊列就是用來處理異常狀況的。

之因此咱們這篇文章拋出一個面試題,結果先長篇大論說一個生產實踐案例和業務場景,就是由於面試被問到這個問題時,必需要結合你本身的業務實踐經驗來講。

你須要先給面試官說有血有肉的業務系統場景,而後再結合這個場景回答他的問題,由於面試官想聽的就是你真實的實踐經驗。

好比說要是第三方物流系統故障了,此時沒法請求,那麼倉儲系統每次消費到一條訂單消息,嘗試通知發貨和配送,都會遇到對方的接口報錯。

此時倉儲系統就能夠把這條消息拒絕訪問,或者標誌位處理失敗!注意,這個步驟很重要。

一旦標誌這條消息處理失敗了以後,MQ就會把這條消息轉入提早設置好的一個死信隊列中。

而後你會看到的就是,在第三方物流系統故障期間,全部訂單消息所有處理失敗,所有會轉入死信隊列。

而後你的倉儲系統得專門有一個後臺線程,監控第三方物流系統是否正常,可否請求的,不停的監視。

一旦發現對方恢復正常,這個後臺線程就從死信隊列消費出來處理失敗的訂單,從新執行發貨和配送的通知邏輯。

死信隊列的使用,其實就是MQ在生產實踐中很是重要的一環,也就是架構設計必需要考慮的。

整個過程,以下圖所示:

 

 

五、總結

 

 

最後再給各位朋友強調一下,若是面試被問到生產實踐類的問題,必定記住:結合有血有肉的業務系統和場景來闡述你的實踐經驗,以及在業務場景下,應該如何設計技術方案。

這樣你的回答,才能匹配上面試官心裏深處最但願聽到的滿分答案!

 

·END·

程序員的成長之路

路雖遠,行則必至

本文原發於 同名微信公衆號「程序員的成長之路」,回覆「1024」你懂得,給個讚唄。

回覆 [ 520 ] 領取程序員最佳學習方式

回覆 [ 256 ] 查看 Java 程序員成長規劃

 

往期精彩回顧

 

 

相關文章
相關標籤/搜索