微眾銀行的金融級消息服務平台建設實踐和思考
導讀:
近年來,隨著微服務架構的流行,分散式消息引擎在物聯網、分散式事務、實時計算和大規模緩存同步等場景中的應用日益增多。本文將分享微眾銀行基於RocketMQ構建消息服務平台的實踐,並通過添加諸多高級特性來解決消息收發過程中遇到的各種問題,通過此文,您將了解到:
金融行業服務架構的演進歷程
微眾銀行的消息服務架構
基於RocketMQ定製的消息高級特性
銀行應用架構的演進歷史
不管是銀行的系統還是其他一些傳統企業的系統,他們在最早的時候都使用到了服務匯流排,即ESB或者某種形式存在於SOA架構中,目的是把所有的服務都串起來,讓服務之間能夠形成一個調用。但這類服務架構其實是比較重的,所有的服務架構都要經過匯流排,匯流排成為了架構上的瓶頸。很多商業化的ESB匯流排大家可能都用過,像Oracle、IBM等都有。從服務調用的維度來看,銀行的應用架構的演進經歷了以下3個階段。
第一階段:90年代中後期分散式架構
這個階段的架構具有以下3個特點:
1. 將總行的集中式系統在各個省分行分別都部署一套,每天晚上再以批量處理的方式將各省數據進行集中。
2. 這種架構的方式能夠最快的解決聯機性能問題, 但存在跨省轉賬交易無法實時到賬的問題。
3. 系統發布的實時性是硬傷。
第二階段:2000-2010年集中式匯流排架構
這個階段引入了ESB匯流排的理念:
ESB匯流排為渠道、核心和外圍系統建立了一座橋樑,提供完全統一的介面標準協議,提升了系統發布的實時性。但同時,ESB成為了最大的單點,要支持大並發高TPS低延時,所以HA和性能要求非常高,變更需要相當謹慎。
第三階段:2010年之後的互聯網金融服務架構
到了2012年以後,隨著Facebook、Amazon等開放平台獲得的巨大成功,BAT都逐步將自己的介面開放出來,並實施了開放平台生態圈戰略,從而推動了SOA服務化的快速發展。
左邊是之前的傳統銀行集中式匯流排架構,右邊是互聯網服務化架構,包含了開放平台、服務註冊和發現,以及服務化產品系統。
通過開放平台對外提供介面暴露,可以發現這種架構在保障傳統銀行系統穩定性的同時也可以滿足互聯網金融需求的快速迭代實施,並且也使用了新興的互聯網分散式技術,來降低開發和運維的成本。
微眾銀行的消息服務架構
微眾銀行的消息服務架構
微眾銀行基於Apache RocketMQ構建了自己的分散式消息服務架構,我們以RMB(Reliable Message Bus)為接入層,以基於Apache RocketMQ定製開發的WeMQ(WeBank Message Queue)為消息服務核心,通過GSL(Global Service Location)進行服務定位,通過SGS(Service Governance System)進行服務請求和服務響應的服務治理,整個分散式鏈路的追蹤日誌會上報到Log中。
接下來,我們來看看我們基於RocketMQ改造使用到的常見的消息服務模式:
單播/多播pub-sub模式
Consumer可以是一個或者多個,但是一個消息會被多個不同系統的其中一個consumer收到。
廣播pub-sub模式
多個在線的Consumer會同時收到廣播消息。
Active/Standby消費模式
生產者只有一個,消費者有多個,但是作為HA,只有一個Active,其他都是StandBy。當Active掛掉一個,Standby會迅速接管。
request-reply模式
發送請求-等待響應結果。在發送方做了一個線程的等待,要等待結果的notify。
在分散式消息系統的構建過程中,基於業務的需求,我們在RocketMQ的消息系統中添加了多項高級特性,包括多中心多活、灰度發布、熔斷機制、消息存活期、流量的權重、消息去重、驚群效應問題的解決、背壓模式、消息服務治理、MQTT消息服務等。
基於RocketMQ添加的一些消息高級特性
同城多活
DC級別的多活希望解決的問題是,不僅消息不能丟,還要保證服務不能中斷。這裡有兩個層面的故障,一個是應用全部宕機,那麼希望被其他IDC的應用能夠迅速來接管消息,另外一個是消息中間件宕機,那麼希望生產者能夠切換到其他IDC的中間件進行發送,並且這個中間件的消息在其他IDC有備份,能夠進行消費。微眾已經通過IDC斷網演練檢驗同城多活能力。
灰度發布
灰度發布希望解決的問題是,同一個消費組內不同的實例有監聽不一樣的topic時,能保證不同topic的消息被正確的實例消費。
灰度發布示意圖
熔斷機制
當希望消息的堆積到一定程度時,可能是消費者出現了故障,我們希望能夠提醒生產者。
熔斷機制示意圖
流量權重(自動伸縮Q)
說到流量的權重,有一個問題是,Topic的Q值是在使用過程中手動設置的,當實例的數量超過Q的數量,那麼超過部分的實例是收不到消息的。但是,如果你的實例數量小於Q的話,它們之間會由於負載均衡分Q。根據負載均衡演算法,分到的Q可能是不一致的。比如有的分到2個,有的分到3個。在這種集群消費的情況下,就會出現處理的不對等。比如當大流量到來的時候,分到3個Q的那個實例可能會出現一些問題,比如掛掉了。
所以我們希望,不同的實例拿到的消息量應該是對等的。所以,流量權重希望解決的問題是,隨著實例數的動態增加和減少,能夠動態調整consumeQueue的數量,不至於出現流量不均勻的情況。因此,我們做了一個自動伸縮Q的功能。默認Topic建成時,Q的數量是1,當啟動一個新的實例的時候,會自動擴展一個,停掉一個實例的時候會自動縮一個。從而達到Q個數量和實例的數量是一一對等的。這解決了實例和消息量不對等的問題。
消息去重
在負載均衡的一個很短時間內,當新上一個實例的時候,由於大家分到的Q都是相同的,當前一個分到Q的還在繼續拉消息,下一個實例由於負載均衡很快做完,也分到Q,就會去拿這個Q的消息,這個時候就會出現消息的重複。此時,通常會通過Redis等緩存方式進行去重,也可以在Broker上做一個簡單的處理,例如用互斥鎖,在競爭消費的短時間內,對其進行加鎖,搶到鎖的才能進行消費,同時佔有鎖的時間有限制,從而解決消息去重的問題。
消息服務去重原理圖
消息的背壓消費模式
背壓模式示意圖
在一些特殊場景下,需要對消息引擎做一些加強,例如背壓模式。當消息拉到本地的消費線程池時,會出現一個問題。當要做一些例如DB的寫的操作導致出現線程卡死,處理能力會下降,服務出現降級,但是消息還在不停地往本地拉。
這個時候,我們希望達到一種效果,能夠根據後續服務的治理能力決定拉的消息數量。當然RocketMQ的ProcessQ也能達到這個效果,但是還不夠精細化。因為在金融場景下,交易一旦出現不一致或者超時,會很麻煩。所以我們希望在實時的交易鏈路上去解決這個問題。於是我們做了一個類似Reactor框架的背壓處理,能夠根據處理能力實時拉取消息。
消息存活期
當對消息的有效期有要求時,可以在消費消息時對存活時間進行判斷,超時則丟棄。
內存模式
對於存活期非常短和對延時要求比較低的消息,我們通過內存模式(不落盤)進行加速,降低延時。
驚群效應問題
因為負載均衡演算法在客戶端,客戶端的連接和斷開都會觸發消費組內的所有實例會收到notification做負載均衡。比較理想的情況是,一個實例的掉線不能影響到其他實例,當監聽的topic比較多時,會出現負載均衡慢的問題,因此我們希望負載均衡收斂到服務端來做,客戶端只需要關注topic,不需要關注consumeQueue。
目前,我們團隊已經參與到Apache RocketMQ的社區建設中,並對自用的消息服務以社區分支的形式在維護,希望各行業更多的開發者可以一起參與進來,以打造適用範圍更廣、更好用的分散式消息引擎。
作者介紹
陳廣勝,Apache RocketMQ資深Contributor,曾就職於IBM和華為,現任職於微眾銀行,曾參與過運營商雲和大數據平台的建設,以及銀行的基礎架構建設等。
※微軟或收購Mellanox,加強雲服務
※華為澄清5G不實報道或被錯誤解讀:在德國5G業務一切正常,積極參法國5G建設
TAG:雲技術之家 |