隨著互聯(lián)網(wǎng)金融業(yè)務和相關技術的不斷發(fā)展,傳統(tǒng)金融行業(yè)為滿足業(yè)務快速發(fā)展需求,正在積極引入各類開源技術,以快速搶占市場。那么,以金融和科技作為雙驅動的平安銀行在開源技術的引入方面是如何評估,運用到哪些業(yè)務場景,以及面對復雜的網(wǎng)絡環(huán)境,是如何去部署的呢? 本文將以 Apache RocketMQ 為例,和您一起了解平安銀行在開源技術選型方面的思考和實踐。 ?? RocketMQ 在平安銀行的應用場景; ?? 復雜網(wǎng)絡環(huán)境下的部署實踐; ?? 多隔離區(qū)場景下的部署情況; ?? 多 IDC 場景下的部署情況; ?? 改造實踐和遇到的小插曲; RocketMQ 在平安銀行的應用場景 目前,平安銀行通過 RocketMQ 解決了數(shù)據(jù)預加、信息通知和狀態(tài)變化方面的業(yè)務需求,接下來,我們通過 App 登錄、資產總覽和工資理財 3 個應用場景來展開講下。 App 登錄: 當用戶打開平安銀行 App 的時候,系統(tǒng)會根據(jù)用戶的登錄 ID 去加載相應的用戶數(shù)據(jù),比如銀行卡、信用卡和理財產品等,以及一些系統(tǒng)通知。這個場景下,我們用到了 RocketMQ 的異步處理能力,即預加載需要使用的數(shù)據(jù),提升用戶體驗。 資產總覽: 進入平安銀行 App 資產總覽的頁面,頁面顯示賬戶余額、各類理財產品(黃金、基金和股票等),以及貸款等方面的信息。平安銀行對接了各類基金、黃金和股票等來自不同金融主體、不同系統(tǒng)的數(shù)據(jù),具有種類多、異構系統(tǒng)多和變化快的特點。我們的目標就是讓資產總覽數(shù)據(jù)盡可能準確,不同種類的資產變動的時候發(fā)出通知,資產系統(tǒng)收到通知后,根據(jù)變化的數(shù)據(jù)來計算出用戶當前的資產總覽。 工資理財: 工資理財是指每月工資下發(fā)到銀行卡后,系統(tǒng)可以實現(xiàn)自動買入用戶設置好的理財產品,例如買一些定投類的理財產品。這里信息的傳遞流程是:
那么,在這些場景中,我們對消息引擎會有哪些要求呢?
在技術選型的過程中,RocketMQ 符合我們在這些典型使用場景中對消息產品的需求,在引入的過程中,平安銀行也對社區(qū)做了相應的貢獻。 復雜網(wǎng)絡環(huán)境下的部署實踐 多測試子環(huán)境下的服務調用場景 平安銀行有多套測試子環(huán)境,用來對不同的feature進行測試,即圖中的 FAT、FAT001?FAT002?FAT003等。傳統(tǒng)銀行系統(tǒng)由大型機時代向更面向互聯(lián)網(wǎng)用戶的零售時代轉型過程中,不可避免微服務化,傳統(tǒng)較集中式系統(tǒng)會被劃分為較多的微服務,正常的情況如下圖,服務 A 調用服務 B,服務 B 調用服務 C,服務 C 調用服務 D。 隨著業(yè)務的需求,新的 feature,我們需要對服務 A 和 B 進行改動。相比在FAT環(huán)境里去部署測試,更合適的方式是另起一套 FAT 環(huán)境,這里我們命名為 FAT001,把服務A和B部署上去,A 調用 B,B會調用原來 FAT 環(huán)境里的 C 和 D。 此時,另一個新的需求,需要對服務 A 和 C 進行改動。如果直接發(fā)布到FAT 或 FAT001 肯定是不對的,會影響正在進行的測試,此時,我們會再起一套測試環(huán)境,命名為FAT002,發(fā)布服務 A 和 C。由于 FAT002 里沒有服務 B,所以服務A要調用服務 B 就需要去 FAT 環(huán)境(FAT 定義為較穩(wěn)定的測試子環(huán)境)。服務 B 調用服務 C 的時候,就不應該調用本環(huán)境的 C了,而是調動 FAT002 的 C 才能實現(xiàn)測試功能。 再假設,系統(tǒng)同時還會有另外一個 feature 在測試 C 和 D,此時的調用邏輯也是一樣的,系統(tǒng)調用服務 A 和 B 的時候是在 FAT,調用服務 C 和 D 的時候會到 FAT003 的環(huán)境。 以上的服務調用場景是可以通過微服務框架解決的,進行全鏈路測試,但在生產環(huán)境中,用戶的真實請求比測試環(huán)境中會更復雜一些。 真實的用戶請求過程 我們看一下真實的用戶請求。 APP發(fā)起一個請求請求,進入網(wǎng)關,需要知道請求哪一個測試環(huán)境。通常的做法是:測試人員需要在APP上選好子環(huán)境,例如選擇 FAT001,我們可以直接把請求 FAT001 的網(wǎng)關(每個環(huán)境網(wǎng)關單獨部署),或者在requestheader上添加標識,讓網(wǎng)關去區(qū)分它來源于哪一個環(huán)境(網(wǎng)關統(tǒng)一部署)。假如網(wǎng)關判斷請求來源于 FAT002,那就會把分發(fā)給 FAT002環(huán)境進行處理。 消息層面,如何處理這類用戶請求 以上是服務調用的請求路徑,比較好理解,但到了消息隊列上,問題會變得復雜些,假如一個 feature 只是更改了消費者,那如何把這條消息傳遞到改的消費者應用上去進行測試,而不被其它環(huán)境的消費者消費掉,這是我們需要去考慮的問題。 來看下具體的情況,集群部署了 Broke A 和 Broke B,TopicA 分別部署在這兩個Broker上。 此時,Producer Group A 向 Topic A 中寫數(shù)據(jù),Consumer Group A去消費,這種情況下是不會有任何問題。 但如果新增一套 FAT001 的環(huán)境,要求 FAT001 發(fā)布的消息,只能由 FAT001 來消費,F(xiàn)AT 不能消費,這種情況下我們該怎么解決?
我們想一下,多個 feature 同時進行測試,DB 會部署一套還是多套? 首先一個 feature 不會更改所在的應用,一般來說 DB 是部署一套的,在數(shù)據(jù)庫里面添加字段,來識別數(shù)據(jù)是來源于哪一個子環(huán)境,如果多套部署,不更改的應用取不到新部署的 DB 數(shù)據(jù),無法進行全鏈路測試,所以同樣的,我們也沒有在每個子環(huán)境都部署一套 RocketMQ,而是部署統(tǒng)一部署,通過 RPC 路由把請求路由到正確的生產者集,改造消息路由算法把消息路由到正確的消費者進行處理。 真實的用戶請求過程 生產者變更 在上圖中生產者變更的場景下,默認的場景 FAT發(fā)送,F(xiàn)AT 消費 ,沒有問題的,假設 FAT001 的生產者發(fā)布了,需要 FAT001 發(fā)送到MQ集群,F(xiàn)AT 是可以直接消費。 生產者、消費者同時變更 在上圖生產者和消費者同時變更的場景下,如果消費者在 FAT001也部署了應用,需要FAT消費者不能消費由FAT001產生的消息,而是由 FAT001的消費者去消費。我們的處理方式是在邏輯上把Topic A下面的Queue進行分組,相當于加了邏輯分組,如果消費者在 FAT001 有部署,我們會把 Queue 的分組擴大,在其默認設置的情況下再翻一倍,新增的 Queue 就是給到 FAT001 進行消費的。 只有消費者變更 再來看看只有消費者變更的場景,如上圖。 假設有個feature只需要更改消費者,部署在 FAT001。也是可以通過邏輯分組的方式,實現(xiàn)生產者根據(jù)請求來源來發(fā)送消息到隊列 FAT001 邏輯分組內的 Queue,從而只讓部署在 FAT001 的消費者消費。 通過以上 3 個場景,我們了解到添加邏輯分組的必要性,實現(xiàn)過程并不復雜。主要做了以下調整:???
我們選擇了動態(tài)創(chuàng)建的方式,這個過程中,我們添加了 Meta Server 進行元數(shù)據(jù)管理,進行動態(tài)創(chuàng)建:
多隔離區(qū)場景下的部署實踐 由于對安全上的重視,金融行業(yè)的網(wǎng)絡環(huán)境相比其他行業(yè)會更復雜。整個隔離區(qū)分為以下幾個部分:
外網(wǎng)可以直接訪問,用于放置網(wǎng)關;
面向的是用戶手機,或者網(wǎng)頁上可以看到的功能應用;
包含核心的調用邏輯功能,和交易、訂單相關的核心應用,例如 DB 和存儲;
用于訪問外網(wǎng),有時候也會部署一些 Poxy 代理,因為內網(wǎng)不能直接訪問外網(wǎng),需要通過代理去訪問外網(wǎng);
對接基金、三方存管等外部系統(tǒng)。在金融行業(yè),如果某個系統(tǒng)是閉環(huán)的,那必須要去做隔離;
是指對整個區(qū)域的應用要進行集中管理,且數(shù)據(jù)流動是單向的,只能取數(shù)據(jù),不能通過管理區(qū)把某區(qū)域的數(shù)據(jù)推送到另一區(qū)域。 此外,從安全的角度出發(fā),所有的區(qū)域在生產環(huán)境下都通過防火墻進行隔離,這就給我們部署 RocketMQ 帶來了很大的實施難度。如果只部署一套,面對這么多的防火墻,生產者消費者到集群的的流量跨墻,會給網(wǎng)絡帶來極大的不穩(wěn)定,遇到瓶頸,防火墻幾乎無法在線平滑擴容;如果每個子環(huán)境都部署一套,又帶來運維復雜度,而且還是存在數(shù)據(jù)同步和跨墻消費的問題。 最終,我們采用的是折中的辦法,即統(tǒng)一部署加分隔離區(qū)部署,這樣做的益處是:??
多IDC場景下的部署實踐 同城多IDC,可以認為近似局域網(wǎng),比較好處理,但異地多IDC多活場景,目前我們還沒有特別好的解方案,多活不可避免面臨數(shù)據(jù)分片、數(shù)據(jù)合并和數(shù)據(jù)沖突的解決等問題。 如果 Topic 下數(shù)據(jù)有多活需求,我們暫時通過復制方式來處理。但這類手工模擬消費者消費數(shù)據(jù)寫入新集群的復制方式,會存在一些問題,即復制到另一個集群之后 offset 會改變,處理邏輯就會有偏差。我們通過 pull 的方式自定義的去根據(jù) offset 去進行消費。當故障轉移到新的集群需要去消費的時候,需要獲取到新集群里面正確的offset 值。此時,這個值和之前集群里的已經(jīng)不一樣了,需要根據(jù)時間得到新集群里正確的offset 值,再去進行消費。在沒有更好的解決方案前,治理就顯得很關鍵了。 不過,我們注意到,在 RocketMQ 最新發(fā)布的版本里,提供了 DLedger 的特性,DLedger 定位的是一個工業(yè)級的 Java Library,可以友好地嵌入各類 Java 系統(tǒng)中,滿足其高可用、高可靠、強一致的需求。我們會盡快對這一特性進行集成和測試。 改造實踐和遇到的小插曲 我們在對 RocketMQ 的使用過程中,添加了以下功能或特性:?? A. 為生產者提供消息的堆積能力。 B. 將所有配置管理部署到配置中心,并做云端化處理,以滿足動態(tài)修改的需求。 C. 在 4.3 版本還未提供事務處理能力前,我們在本地數(shù)據(jù)庫里去建一張消息表,數(shù)據(jù)庫更改數(shù)據(jù)狀態(tài)的時候,會同步將數(shù)據(jù)寫入消息表。若發(fā)送失敗,則進行補償。并在客戶端里進行封裝。 D. 實現(xiàn)統(tǒng)一的消息者冪等處理。 E. 添加身份認證和消息認證(注:RocketMQ 4.3 版本中已經(jīng)實現(xiàn)身份認證功能) 當然,也遇到了一些小插曲,基本都是使用上的小問題,可能大家也會碰到:?? A. 一個應用使用多個RocketMQ集群時,未加載到正確的配置。在Client 端,如果沒有對instancename 進行配置,一個應用連多個集群會失敗。 B. 在大數(shù)據(jù)的場景下,內存溢出。訂閱的 Topic 越多,每個 Queue 在本地緩存的 message 也會越多,默認每個 Queue 1000條,可能會把內存打爆,可根據(jù)實際情況調整。 C. 刪除數(shù)據(jù)時 IO 抖動,默認每天凌晨4點刪除數(shù)據(jù),量上來后出現(xiàn) IO 抖動,配置了消息刪除策略,默認逗號分隔開,多配幾個時間刪除就可以了。 D. Broker上日志報延遲消息找不到數(shù)據(jù)文件。在主備切換的演練過程中,出現(xiàn)了延遲消息在Broker 上處理異常的情況。當主切換到備端時,延遲消息在 Broker 上保存的文件被自動刪除,再切回主,由于延時消息的元數(shù)據(jù)感覺在,會查詢文件進行處理,此時已找不到文件。 E. 掛 NAS 的時候,IP 獲取了 NAS 的私網(wǎng)地址,并被提交給了服務端。 以上就是我們在部署過程中遇到的一些小插曲,基本都是可以很快定位原因,解決的。 總的來看,RocketMQ 對平安銀行的消息系統(tǒng)建設的幫助是非常大的,尤其是滿足了數(shù)據(jù)持久化、順序消費和回溯的需求,此外,在消息的查詢方面,也比我們之前使用的消息引擎好很多。最后再分享一點自己對中間件的一點感悟:中間件使用重在治理,規(guī)范不先行,開發(fā)兩行淚。 本文作者: |
|