中字頭 中建二局項目一期 aop

消息隊列場景簡介
“ 消息 ”是在兩臺計算機間傳送的數據單位。消息可以非常簡單,例如只包含文本字符串;也可以更復雜,可能包含嵌入對象。消息被髮送到隊列中,“ 消息隊列 ”是在消息的傳輸過程中保存消息的 容器 。

在目前廣泛的Web應用中,都會出現一種場景:在某一個時刻,網站會迎來一個用戶請求的高峯期(比如:淘寶的雙十一購物狂歡節,12306的春運搶票節等),一般的設計中,用戶的請求都會被直接寫入數據庫或文件中,在高併發的情形下會對數據庫服務器或文件服務器造成巨大的壓力,同時呢,也使響應延遲加劇。這也說明了,爲什麼我們當時那麼地抱怨和吐槽這些網站的響應速度了。當時2011年的京東圖書促銷,曾一直出現在購物車中點擊“購買”按鈕後一直是“ Service is too busy ”,其實就是因爲當時的 併發訪問量過大,超過了系統的最大負載能力 。當然,後邊,劉強東臨時購買了不少服務器進行擴展以求增強處理併發請求的能力,還請了信息部的人員“喝茶”,現在京東已經是超大型的網上商城了,我也有同學在京東成都研究院工作了。
使用消息隊列
從京東當年的“Service is too busy”不難看出,高併發的用戶請求是網站成長過程中必不可少的過程,也是一個必須要解決的難題。在衆多的實踐當中,除了增加服務器數量配置服務器集羣實現伸縮性架構設計之外,異步操作也被廣泛採用。而異步操作中最核心的就是使用 消息隊列 ,通過消息隊列,將短時間高併發產生的事務消息存儲在消息隊列中,從而削平高峯期的併發事務,改善網站系統的性能。在京東之類的電子商務網站促銷活動中, 合理地使用消息隊列,可以有效地抵禦促銷活動剛開始就開始大量涌入的訂單對系統造成的衝擊 。
記得我在實習期間,成都市XXXX局的一個價格信息採集發佈系統項目中有一個採集任務發佈的模塊,其中每個任務都是一個事務,這個事務中需要向數據庫中不斷地插入行,每個任務發佈時都要往表中插入幾百行甚至幾千行的任務數據(比如價格採集日報,往往需要發佈2-3年的任務數據,每一天都是一個任務,所以大約有2,3千行任務期號數據,還要發給很多個區縣的監測中心,因此數據庫寫操作量很大,更別說同時發佈的併發操作),由於業務邏輯的處理比較複雜和往數據庫的寫操作量交大,所以在沒有采用消息隊列時點擊“發佈”按鈕後往往需要等待1分鐘左右的時間才提示“發佈成功”,用戶體驗極不友好。

這時,我們就可以使用消息隊列的思想來重構這個發佈模塊,在用戶點擊“發佈”按鈕後,系統只需要把往數據庫插入的這個事務信息插入到指定的任務發佈消息隊列裏邊去(入隊操作,這裏一般有一臺獨立的消息隊列服務器來單獨存儲和處理),然後系統就可以立即對用戶的這個發佈請求進行響應(比如給出一個發佈成功的操作提示,這裏暫不考慮消息隊列服務操作失敗的情形,如果失敗了,可以考慮採用給用戶發送郵件、短信或站內消息,讓其重新進行發佈操作)。
隊列結構
最後,消息隊列服務器中有一個進程單獨對消息隊列進行處理,首先判斷消息隊列中是否有待處理的消息,如果有,則將其取出(出隊操作,堅持“先進先出”的順序,保證事務的準確性)進行相應地處理(比如這裏是進行保存數據的操作,將數據插入到數據庫服務器中的指定數據庫裏邊,實質還是文件的IO操作)。就這樣,通過消息隊列將高併發用戶請求進行異步操作,然後一一對消息隊列進行出隊的同步操作,也避免了併發控制的難題。
說到這裏,大家可能會想到這尼瑪不就是 生產者消費者模式 麼?對的,麼麼嗒,消息隊列就是生產者消費者模式的典型場景。簡單地說,客戶端不同用戶發送的操作請求就是生產者,他們將要處理的事務存儲到消息隊列中,然後消息隊列服務器的某個進程不停地將要處理的單個事務從消息隊列中一個一個地取出來進行相應地處理,這就是消費者消費的過程。
下面我們將以異常日誌爲案例,介紹在.Net中如何採用消息隊列的思想解決併發問題。當然,消息隊列只是解決併發問題的其中一種方式,在實際中往往需要結合多種不同的技術方式來共同解決,比如負載均衡、反向代理、集羣等方案。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章