文章深度解讀了某商業(yè)銀行做消息隊列選型時考慮的因素,包括關(guān)鍵需求、選型要點、選型原則等,同時給出了選型建議、產(chǎn)品對比以及典型場景和二次封裝的建議。本文作者在自己豐富實踐經(jīng)驗基礎(chǔ)上抽象出一些方法論,供讀者在做消息隊列技術(shù)選型時參考。 本文主要內(nèi)容包括以下方面: 1 概述 2 為什么引入消息隊列
3 消息隊列選型
4 二次封裝建議 5 典型場景
6 經(jīng)驗總結(jié)和建議 作為金融企業(yè)對公眾提供服務(wù)一定要保證其可用性,盡量做到更多個9(一般SLA中描述的高可用性99.99%,中的9越多代表全年服務(wù)可用時間越長服務(wù)更可靠,停機時間越短),隨著軟件系統(tǒng)的復(fù)雜度越來越高,故障是不可避免的。這就需要企業(yè)實現(xiàn)整體的彈性架構(gòu)(Resilient Architecture),為應(yīng)對故障而設(shè)計。 然而,常見的RPC、RMI企業(yè)集成技術(shù),因為是同步請求,常因為執(zhí)行方失敗、超時等因素而影響最終用戶體驗,而且很多故障是無法徹底消除的。而且RPC和RMI調(diào)用需要服務(wù)的消費方和服務(wù)的提供方同時在線,并且雙方需要通過某種機制確認(rèn)彼此的調(diào)用關(guān)系,因為存在這些弊端,就導(dǎo)致了面向消息的中間件(MOM)的產(chǎn)生,通過在企業(yè)架構(gòu)中引入消息中間件,確保在故障發(fā)生時,受此影響的系統(tǒng)部分在一個很小的范圍內(nèi)。 消息中間件就是在分布式系統(tǒng)中間引入一個透明的中間層,隔離服務(wù)的提供方和消費方。 2.1 何為消息隊列消息隊列(Message Queue,MQ)是一種不同應(yīng)用程序之間(跨進(jìn)程)的通信方法,用于上下游應(yīng)用程序之間傳遞消息。我們拆分來看:
這樣就實現(xiàn)了上游與下游之間的解耦,上游向MQ發(fā)送消息,下游從MQ接收消息,上游下游互不依賴,它們只依賴MQ。因為有隊列的存在,MQ可在上下游之間進(jìn)行緩沖,把上游信息先緩存起來,下游根據(jù)自己的能力從MQ中拉取信息,起到削峰的作用。 2.2 消息隊列的優(yōu)勢1 解耦1)什么是耦合 高內(nèi)聚低耦合,是軟件工程中的概念,這里的低耦合是指各個組件之間,盡可能相互獨立。通俗一點的理解就是,增加模塊間調(diào)用透明化,最高的透明度就是不用知道彼此的存在,因此減少接口的復(fù)雜性、規(guī)范調(diào)用的方式及傳遞的信息,降低產(chǎn)品各模塊的依賴,提高重用程度。 2)如何解耦 在企業(yè)整體架構(gòu)中解耦,主要設(shè)計兩個方面:一是簡化減少交互,二是增加一個中間層實現(xiàn)兩方的隔離,MQ就是其中的中間層(如下圖所示)。引入MQ后生產(chǎn)者和消費者不必知道彼此的存在也不必同時在線,主要交互流程如下:
2 削峰填谷 由于系統(tǒng)閑忙分布不均,QPS常相差幾十倍甚至更高,特別是在遇到營銷活動時,瞬間流量很可能超過后端系統(tǒng)的承載能力,這就要考慮通過消息中間件來緩沖,MQ客戶端實例根據(jù)自己的處理能力從MQ服務(wù)器拉取消息,以此來減輕或消除后端系統(tǒng)的瓶頸。 (圖片來源:https://github.com/alibaba/Sentinel/wiki/Sentinel-為-RocketMQ-保駕護(hù)航) 3 異構(gòu)集成由于各種原因,我們在企業(yè)信息化建設(shè)過程中,都會面臨軟件產(chǎn)品來自不同的廠家只解決某特定領(lǐng)域的問題,這些產(chǎn)品因為封閉的架構(gòu)無法對外提供服務(wù)或缺少核心開發(fā)而無法做大的改造,這就造成了彼此之間很難集成。通過引入MQ可以部分解決該問題,只需要在某個環(huán)節(jié)生產(chǎn)一條消息,或者根據(jù)消息做出具體的響應(yīng),只需與MQ對接,不必與其他系統(tǒng)做一對一的對接。 4 異步隔離為了提供金融服務(wù)的整體彈性,需要隔離內(nèi)部、外部系統(tǒng)間的依賴。如支付通知分為兩種,一種是同步通知,這時API調(diào)用會因為網(wǎng)絡(luò)故障而超時,因為服務(wù)提供方處理能力限制而得不到及時響應(yīng)等多種因素影響,另一種是異步通知,在一定時效范圍內(nèi)最終通知到即可,從而提供提高最終用戶的體驗和交易成功率,提高業(yè)務(wù)的整體生產(chǎn)率。 2.3 消息隊列的不足凡有收益必有代價,MQ也有其不足:
所以在軟件的正常功能開發(fā)中,并不需要去刻意的尋找消息隊列的使用場景,而是當(dāng)出現(xiàn)性能瓶頸時,去查看業(yè)務(wù)邏輯是否存在可以異步處理的耗時操作,如果存在的話便可以引入消息隊列來解決。否則盲目的使用消息隊列可能會增加維護(hù)和開發(fā)的成本卻無法得到可觀的性能提升,那就得不償失了。 但凡選擇就會受到主觀和客觀兩個因素的影響。我們?nèi)绾伪M量客觀的進(jìn)行架構(gòu)和框架選型,而避免先有結(jié)果而后找理由的文字游戲,下面我分享下我們做MQ選型的過程(這里不是說主觀就是不好的,但作為工程師凡事做結(jié)構(gòu)化和量化還是有必要的)。 3.1 關(guān)鍵需求
3.2 其他需要考慮的因素
3.3 選型要點及原則
3.4 選型建議 為未來最少三年或五到十年來選擇,因為TedNeward在JAVA 消息服務(wù)的序言中總結(jié)了技術(shù)熟悉的過程4個階段(門外漢、探索者、熟手、大師)。選型到全范圍推廣結(jié)束一年左右的時間就過去了,到大家熟悉和精通又一年過去了,誰都不想在剛熟悉還沒用好,當(dāng)前的產(chǎn)品就不滿足要求了,又要重新來過。 區(qū)分關(guān)注點,確保只針對核心關(guān)注點進(jìn)行選擇。給出選擇的deadline,并按時進(jìn)入到項目實戰(zhàn)準(zhǔn)備,再多的理論分析,都不如真正使用過后的感受深入,產(chǎn)品需要成長、團(tuán)隊成員同樣需要成長,既然路在遠(yuǎn)方就趕緊起程。 3.5 候選產(chǎn)品比較1 產(chǎn)品特性比較
2 測試建議功能測試:建議搭建POC環(huán)境進(jìn)行驗證,除驗證相關(guān)功能性指標(biāo)有沒有,還要驗證好不好用。所以在測試時要基于MQ提供的功能構(gòu)建使用場景進(jìn)行業(yè)務(wù)功能實現(xiàn)的驗證。性能測試:其實性能測試涉及的各方面因素比較多,如:基于什么樣的環(huán)境,做了哪些配置,采用什么樣的壓測腳本和報文來做壓力測試?比較指標(biāo):除TPS(發(fā)送者TPS、消費者最終處理業(yè)務(wù)的TPS)、延時、支持多少同時在線鏈接(生產(chǎn)者數(shù)據(jù)量、消費者數(shù)據(jù)量)、Topic配置(Topic數(shù)量以及每個Topic隊列數(shù)量與生產(chǎn)者、消費者數(shù)據(jù)量的關(guān)系)、服務(wù)器的性能指標(biāo)(cpu、內(nèi)存、磁盤io、網(wǎng)絡(luò)io)如何等也是需要考量的。 疲勞測試:在一定壓力下持續(xù)運行24小時、一周或更長時間。要重點關(guān)注穩(wěn)定性、服務(wù)器的各項指標(biāo)、是否有緩慢增長的趨勢等。 重啟或故障演練:分別對注冊中心NameServer、Broker、Producer、Consumer的實例進(jìn)行部分重啟(或直接kill)或全部重啟(或直接kill)、磁盤故障、網(wǎng)絡(luò)故障等,查看應(yīng)用的影響,如:在RocketMQ服務(wù)是否可以恢復(fù),生產(chǎn)者消費者是否可以恢復(fù)服務(wù),消息是否有丟失,消息是否有重復(fù)等。 3.6 選擇RocketMQ的原因
我們最終選擇RocketMQ的主要原因如下:
封裝主要是對業(yè)務(wù)、技術(shù)和數(shù)據(jù)進(jìn)行抽象和封裝,封裝具有如下優(yōu)點:
將規(guī)范封裝到基礎(chǔ)代碼中以便在企業(yè)內(nèi)部統(tǒng)一交互標(biāo)準(zhǔn),具體的規(guī)范包括:
通過賦義編碼規(guī)范可以通過名稱定位到所屬項目、模塊等業(yè)務(wù)場景,以便在出現(xiàn)未知問題時可以快速協(xié)調(diào)人員進(jìn)行處理,當(dāng)然對topic、生產(chǎn)者、消費者等原數(shù)據(jù)管理也是必要的,畢竟命名規(guī)范能保留的信息有限。通過命名規(guī)范還可以避免沖突,比如topic的沖突會或誤會導(dǎo)致消息無法正常消費或者業(yè)務(wù)流轉(zhuǎn)等問題,消費者GroupID沖突會導(dǎo)致消息丟失等問題。 通過封裝和定制化增強管理功能如批量信息查詢、批量信息重發(fā)、消息對賬等。 RocketMQ是提高整體服務(wù)彈性的重要基礎(chǔ)中間件,在個類金融交易中承擔(dān)著重要的角色。4.1 支付場景 下面以活期賬戶轉(zhuǎn)出服務(wù)場景為例來講解。
這樣各服務(wù)回歸到本來應(yīng)該的樣子,賬戶轉(zhuǎn)出服務(wù)不用關(guān)注于其它系統(tǒng)對它的依賴,只需要產(chǎn)生賬戶轉(zhuǎn)出事件的消息,有需要的服務(wù)各自去訂閱這個消息就好了,相互不受影響。 4.2 第三方延時調(diào)用場景在與銀行外部系統(tǒng)對接的時候,會有需要在發(fā)送服務(wù)請求N秒后,去獲得響應(yīng)結(jié)果的異步請求。在使用RocketMQ的延時消息前,都是通過將數(shù)據(jù)落地到數(shù)據(jù)庫或Redis緩存中,然后通過定時輪詢?nèi)蝿?wù)來操作。這樣做有以下缺點:
使用RocketMQ后有以下優(yōu)點:
不過,當(dāng)前版本還不支設(shè)置時間精度,只能按照特定的messageDelayLevel來設(shè)置,這就要在搭建RocketMQ時提前最好延時級別的規(guī)劃或者對RocketMQ延時源碼進(jìn)行擴(kuò)展以支持指定時間精度。
當(dāng)故障是不可避免的,就需要在應(yīng)用程序設(shè)計的時候考慮通過一系列機制具備自我管理、自我恢復(fù)、自我配置等自治功能,隨著云原生架構(gòu)的流行,面對負(fù)載的加重和不斷發(fā)生的各類故障,MQ不會是彈性系統(tǒng)設(shè)計的唯一選擇,但也許是一個不錯的選擇,值得一試。 聲明:文章謹(jǐn)代表作者觀點,與所在平臺無關(guān)。 作者簡介:金融業(yè)老兵,十余年金融行業(yè)工作經(jīng)驗,愛思考和分享,維護(hù)公眾號【聊聊金融】(dhjr_it)。 |
|
來自: 劉振東 > 《RocketMQ實踐》