隨着互聯網金融業務和相關技術的不斷髮展,傳統金融行業爲知足業務快速發展需求,正在積極引入各種開源技術,以快速搶佔市場。那麼,以金融和科技做爲雙驅動的平安銀行在開源技術的引入方面是如何評估,運用到哪些業務場景,以及面對複雜的網絡環境,是如何去部署的呢?算法
本文將以 Apache RocketMQ 爲例,和您一塊兒瞭解平安銀行在開源技術選型方面的思考和實踐。數據庫
RocketMQ 在平安銀行的應用場景;緩存
複雜網絡環境下的部署實踐;安全
多隔離區場景下的部署狀況;網絡
多 IDC 場景下的部署狀況;架構
改造實踐和遇到的小插曲;框架
目前,平安銀行經過 RocketMQ 解決了數據預加、信息通知和狀態變化方面的業務需求,接下來,咱們經過 App 登陸、資產總覽和工資理財 3 個應用場景來展開講下。運維
App 登陸:異步
當用戶打開平安銀行 App 的時候,系統會根據用戶的登陸 ID 去加載相應的用戶數據,好比銀行卡、信用卡和理財產品等,以及一些系統通知。這個場景下,咱們用到了 RocketMQ 的異步處理能力,即預加載須要使用的數據,提高用戶體驗。微服務
資產總覽:
進入平安銀行 App 資產總覽的頁面,頁面顯示帳戶餘額、各種理財產品(黃金、基金和股票等),以及貸款等方面的信息。平安銀行對接了各種基金、黃金和股票等來自不一樣金融主體、不一樣系統的數據,具備種類多、異構系統多和變化快的特色。咱們的目標就是讓資產總覽數據儘量準確,不一樣種類的資產變更的時候發出通知,資產系統收到通知後,根據變化的數據來計算出用戶當前的資產總覽。
工資理財:
工資理財是指每個月工資下發到銀行卡後,系統能夠實現自動買入用戶設置好的理財產品,例如買一些定投類的理財產品。這裏信息的傳遞流程是:
那麼,在這些場景中,咱們對消息引擎會有哪些要求呢?
A、高可用、高可靠和高性能,這是金融行業引入開源技術的基本要求;
B、堆積能力,代發工資的用戶不少,一個公司的員工會在某個時間點集中發放;
C、順序能力,即帳戶變更在先,發出通知在後;
D、事務性能力,若是沒有事務性,有可能會出現帳戶變更了,但沒有觸發購買理財產品的狀況;
E、重試和延遲消息功能,好比工資發放的時候,多是在晚上,這時候系統會自動把購買理財的動做放在次日白天去操做,再發出通知;
F、消息回溯能力,就是出現問題的時候,咱們能夠把這個消息進行回溯,從新進行消息的處理,提供完整的消息軌跡;
在技術選型的過程當中,RocketMQ 符合咱們在這些典型使用場景中對消息產品的需求,在引入的過程當中,平安銀行也對社區作了相應的貢獻。
多測試子環境下的服務調用場景
平安銀行有多套測試子環境,用來對不一樣的feature進行測試,即圖中的 FAT、FAT001、FAT002、FAT003等。傳統銀行系統由大型機時代向更面向互聯網用戶的零售時代轉型過程當中,不可避免微服務化,傳統較集中式系統會被劃分爲較多的微服務,正常的狀況以下圖,服務 A 調用服務 B,服務 B 調用服務 C,服務 C 調用服務 D。
隨着業務的需求,新的 feature,咱們須要對服務 A 和 B 進行改動。相比在FAT環境裏去部署測試,更合適的方式是另起一套 FAT 環境,這裏咱們命名爲 FAT001,把服務A和B部署上去,A 調用 B,B會調用原來 FAT 環境裏的 C 和 D。
此時,另外一個新的需求,須要對服務 A 和 C 進行改動。若是直接發佈到FAT 或 FAT001 確定是不對的,會影響正在進行的測試,此時,咱們會再起一套測試環境,命名爲FAT002,發佈服務 A 和 C。因爲 FAT002 裏沒有服務 B,因此服務A要調用服務 B 就須要去 FAT 環境(FAT 定義爲較穩定的測試子環境)。服務 B 調用服務 C 的時候,就不該該調用本環境的 C了,而是調動 FAT002 的 C 才能實現測試功能。
再假設,系統同時還會有另一個 feature 在測試 C 和 D,此時的調用邏輯也是同樣的,系統調用服務 A 和 B 的時候是在 FAT,調用服務 C 和 D 的時候會到 FAT003 的環境。
以上的服務調用場景是能夠經過微服務框架解決的,進行全鏈路測試,但在生產環境中,用戶的真實請求比測試環境中會更復雜一些。
真實的用戶請求過程
咱們看一下真實的用戶請求。
APP發起一個請求請求,進入網關,須要知道請求哪個測試環境。一般的作法是:測試人員須要在APP上選好子環境,例如選擇 FAT001,咱們能夠直接把請求 FAT001 的網關(每一個環境網關單獨部署),或者在requestheader上添加標識,讓網關去區分它來源於哪個環境(網關統一部署)。假如網關判斷請求來源於 FAT002,那就會把分發給 FAT002環境進行處理。
以上是服務調用的請求路徑,比較好理解,但到了消息隊列上,問題會變得複雜些,假如一個 feature 只是更改了消費者,那如何把這條消息傳遞到改的消費者應用上去進行測試,而不被其它環境的消費者消費掉,這是咱們須要去考慮的問題。
來看下具體的狀況,集羣部署了 Broke A 和 Broke B,TopicA 分別部署在這兩個Broker上。 此時,Producer Group A 向 Topic A 中寫數據,Consumer Group A去消費,這種狀況下是不會有任何問題。
但若是新增一套 FAT001 的環境,要求 FAT001 發佈的消息,只能由 FAT001 來消費,FAT 不能消費,這種狀況下咱們該怎麼解決?
這些都不能解決咱們的問題。️
一方面成本過高,另外一方面若是這個feture測試完成了,須要把相關的
應用再切回 FAT 進行處理,實現太過複雜。️
咱們想一下,多個 feature 同時進行測試,DB 會部署一套仍是多套?
首先一個 feature 不會更改所在的應用,通常來講 DB 是部署一套的,在數據庫裏面添加字段,來識別數據是來源於哪個子環境,若是多套部署,不更改的應用取不到新部署的 DB 數據,沒法進行全鏈路測試,因此一樣的,咱們也沒有在每一個子環境都部署一套 RocketMQ,而是部署統一部署,經過 RPC 路由把請求路由到正確的生產者集,改造消息路由算法把消息路由到正確的消費者進行處理。
真實的用戶請求過程
在上圖中生產者變動的場景下,默認的場景 FAT發送,FAT 消費 ,沒有問題的,假設 FAT001 的生產者發佈了,須要 FAT001 發送到MQ集羣,FAT 是能夠直接消費。
在上圖生產者和消費者同時變動的場景下,若是消費者在 FAT001也部署了應用,須要FAT消費者不能消費由FAT001產生的消息,而是由 FAT001的消費者去消費。咱們的處理方式是在邏輯上把Topic A下面的Queue進行分組,至關於加了邏輯分組,若是消費者在 FAT001 有部署,咱們會把 Queue 的分組擴大,在其默認設置的狀況下再翻一倍,新增的 Queue 就是給到 FAT001 進行消費的。
再來看看只有消費者變動的場景,如上圖。
假設有個feature只須要更改消費者,部署在 FAT001。也是能夠經過邏輯分組的方式,實現生產者根據請求來源來發送消息到隊列 FAT001 邏輯分組內的 Queue,從而只讓部署在 FAT001 的消費者消費。
經過以上 3 個場景,咱們瞭解到添加邏輯分組的必要性,實現過程並不複雜。主要作了如下調整:️
咱們選擇了動態建立的方式,這個過程當中,咱們添加了 Meta Server 進行元數據管理,進行動態建立:
因爲對安全上的重視,金融行業的網絡環境相比其餘行業會更復雜。整個隔離區分爲如下幾個部分:
此外,從安全的角度出發,全部的區域在生產環境下都經過防火牆進行隔離,這就給咱們部署 RocketMQ 帶來了很大的實施難度。若是隻部署一套,面對這麼多的防火牆,生產者消費者到集羣的的流量跨牆,會給網絡帶來極大的不穩定,遇到瓶頸,防火牆幾乎沒法在線平滑擴容;若是每一個子環境都部署一套,又帶來運維複雜度,並且仍是存在數據同步和跨牆消費的問題。
最終,咱們採用的是折中的辦法,即統一部署加分隔離區部署,這樣作的益處是:
同城多IDC,能夠認爲近似局域網,比較好處理,但異地多IDC多活場景,目前咱們尚未特別好的解方案,多活不可避免面臨數據分片、數據合併和數據衝突的解決等問題。
若是 Topic 下數據有多活需求,咱們暫時經過複製方式來處理。但這類手工模擬消費者消費數據寫入新集羣的複製方式,會存在一些問題,即複製到另外一個集羣以後 offset 會改變,處理邏輯就會有誤差。咱們經過 pull 的方式自定義的去根據 offset 去進行消費。當故障轉移到新的集羣須要去消費的時候,須要獲取到新集羣裏面正確的offset 值。此時,這個值和以前集羣裏的已經不同了,須要根據時間獲得新集羣里正確的offset 值,再去進行消費。在沒有更好的解決方案前,治理就顯得很關鍵了。
不過,咱們注意到,在 RocketMQ 最新發布的版本里,提供了 DLedger 的特性,DLedger 定位的是一個工業級的 Java Library,能夠友好地嵌入各種 Java 系統中,知足其高可用、高可靠、強一致的需求。咱們會盡快對這一特性進行集成和測試。
咱們在對 RocketMQ 的使用過程當中,添加了如下功能或特性:
A. 爲生產者提供消息的堆積能力。
B. 將全部配置管理部署到配置中心,並作雲端化處理,以知足動態修改的需求。
C. 在 4.3 版本還未提供事務處理能力前,咱們在本地數據庫裏去建一張消息表,數據庫更改數據狀態的時候,會同步將數據寫入消息表。若發送失敗,則進行補償。並在客戶端裏進行封裝。
D. 實現統一的消息者冪等處理。
E. 添加身份認證和消息認證(注:RocketMQ 4.3 版本中已經實現身份認證功能)
固然,也遇到了一些小插曲,基本都是使用上的小問題,可能你們也會碰到:
A. 一個應用使用多個RocketMQ集羣時,未加載到正確的配置。在Client 端,若是沒有對 instancename 進行配置,一個應用連多個集羣會失敗。
B. 在大數據的場景下,內存溢出。訂閱的 Topic 越多,每一個 Queue 在本地緩存的 message 也會越多,默認每一個 Queue 1000條,可能會把內存打爆,可根據實際狀況調整。
C. 刪除數據時 IO 抖動,默認天天凌晨4點刪除數據,量上來後出現 IO 抖動,配置了消息刪除策略,默認逗號分隔開,多配幾個時間刪除就能夠了。
D. Broker上日誌報延遲消息找不到數據文件。在主備切換的演練過程當中,出現了延遲消息在 Broker 上處理異常的狀況。當主切換到備端時,延遲消息在 Broker 上保存的文件被自動刪除,再切回主,因爲延時消息的元數據感受在,會查詢文件進行處理,此時已找不到文件。
E. 掛 NAS 的時候,IP 獲取了 NAS 的私網地址,並被提交給了服務端。
以上就是咱們在部署過程當中遇到的一些小插曲,基本都是能夠很快定位緣由,解決的。
總的來看,RocketMQ 對平安銀行的消息系統建設的幫助是很是大的,尤爲是知足了數據持久化、順序消費和回溯的需求,此外,在消息的查詢方面,也比咱們以前使用的消息引擎好不少。最後再分享一點本身對中間件的一點感悟:中間件使用重在治理,規範不先行,開發兩行淚。
本文做者:吳建峯,GitHub ID @devilfeng,來自平安銀行平臺架構部基礎框架團隊。
本文爲雲棲社區原創內容,未經容許不得轉載。