本文首發自 InfoQ 《告別傳統金融訊息架構:Apache Pulsar 在平安證券的實踐》。
作者:王東鬆,陳翔
在金融場景中,伴隨著業務的擴充套件,應用系統也相應地增加更多的場景,這些新場景對訊息系統提出更多樣的需求,導致原有架構面臨一系列挑戰。在嘗試使用 Apache Pulsar 後,平安證券決定在生產環境中進行實踐。本文介紹了平安證券選擇 Apache Pulsar 的原因,使用 Apache Pulsar 的場景,Apache Pulsar 實踐應用中遇到的問題,以及使用 Apache Pulsar 的未來規劃。
背景介紹
傳統金融公司或券商一般會使用統一接入服務或元件來處理對外業務。接收到使用者請求後,根據相應的業務規則將請求轉到對應業務系統 / 模組。有些請求會轉發給訊息佇列,請求寫入後,下游業務系統從訊息佇列中獲取請求,並在處理後通過訊息佇列原路返回給客戶,整個請求過程封閉執行,功能有限。
訊息佇列下傳統架構帶來的挑戰
平安證券採用的就是上述的傳統架構,目前只支援訊息佇列。雖然我們有一定的開發能力,但也難以獲取到該訊息佇列的細節資訊。同時,由於是定製開發的系統,支援的語言比較有限。現有的訊息佇列對業務發展和業務創新等有以下不足:
- 黑盒系統,難以觀測:訊息佇列是一個黑盒系統,我們難以觀測到架構的細節;
- 直接交換(Direct Exchange),無法路由:由於架構目前只支援訊息佇列,無法支援需要路由的場景;
- 弱校驗接入,安全風險高:現有系統的密碼認證、校驗等檢驗較弱,安全風險較高;
- 定製系統,有限語言支援:定製系統接入語言的支援有限,導致我們選擇範圍少,難以在原有系統基礎上進行改革。
隨著業務擴充套件和架構改進,公司現有的訊息佇列系統 / 元件面臨著一系列挑戰,而系統存在的許多問題如安全性等在金融場景中刻不容緩。
金融場景的業務需求
我們的業務需求主要分為三類:身份識別 & 安全控制、路由分發、審計。
身份識別 & 安全控制
身份識別主要用於確定接入訊息佇列的客戶端和接入者的身份資訊,指定相應的安全規則,拒絕不合法接入者,進而實現預期的安全要求。從最基礎的層面看,需要識別控制接入的系統、IP,根據業務場景及特定需求,進行許可權限制。
路由分發
路由分發指訊息根據相應的規則由寫入佇列路由至對應的佇列。現有的訊息佇列支援的場景有限,若想要支援更多場景,需要投入大量的時間和精力來進行開發(涉及上下游系統的改造),同時會引入其他問題。較好的解決方案是訊息佇列系統原生支援更多模式及特性,比如 TOPIC 模式、流式訊息處理。如果訊息佇列系統可以支援路由,那麼系統的接入複雜度就會大大降低,可以通過更優的方式對接入層進行操作,每個系統只需要對接一組 topic,路由負責分發;也可以更有針對性地優化效能(路由、轉發、協議轉化都是消耗效能的操作)。
原有系統架構通訊機制是點對點,封閉執行,請求訊息無法共享,只能間接採用介面卡或日誌採集方式實現分發,此類做法難以有效滿足實時性要求。
審計
訊息的釋出者 / 接收者都屬於整個系統的參與者,並且是重中之重。系統安全性的主要影響因素就是系統的所有參與者;因此,從安全形度出發,對訊息的審計要求相對較高。另一項比較急迫的需求是對訊息流向進行控制。如果可以進行身份識別和安全控制,則可以在審計時完善和優化安全資訊,進而保證在業務入口處拒絕無效、非法請求,保證內部系統健壯。此外,記錄接入的訊息釋出者 / 接收者的資訊還可以用於異常情況監控、稽核審計。
新增業務的系統需求
新增業務對訊息系統提出了更高要求,主要包括可用性、訊息傳送延遲、擴縮容、訊息回溯等。
需求一:高可用、低延遲
對於網際網路行業而言,高可用低延遲是系統的基本要求。從單點到災備,到同城跨機房,再到異城跨多中心,或者是先跨城、災備,再跨城多中心(兩地三中心)的模式都已經越來越常態化,很多公司的業務系統正在或將會往這方向發展。這樣的系統對高可用、低延遲的要求比較高。因此需要考慮當系統複雜度增加(如災備、跨城等場景)時,如何將延遲降到最低。
需求二:快速擴容與恢復
對於金融業而言,業務的主要特性之一是請求可能會在某個時間段或某個週期激增,過了這個時間視窗後,流量逐漸恢復正常。這一特性要求系統可以快速橫向擴縮容,出於成本考慮,按照最高流量部署整個系統架構顯然不合理。最好的解決方案是系統可以根據單層流量合理安排系統架構或系統部署方式,在流量突然增加時,系統可以快速擴容,支撐業務。最理想的情況是系統的所有元件都有快速擴縮容、恢復能力。
需求三:訊息有序、訊息防重
在一些特殊業務場景中,需要保證訊息有序或防重。我們經常對一些介面進行冪等操作,如果可以保證上游訊息不重複,就可以減小下游的壓力。
需求四:可回溯、序列化
如果業務系統出現問題,但在測試環境中難以復現這一問題,就需要引入訊息回溯。訊息回溯指重放一遍出現問題的時間視窗中的所有請求,驗證是否能復現問題,並排查問題,這樣可以大大減輕排查問題的工作量。此外,我們還可以藉助這一功能進行灰度驗證和並行驗證。
選擇 Apache Pulsar
基於上述業務需求和系統需求,發現 Apache Pulsar 的諸多特性完美契合了我們的需求。
- 叢集模式,支援跨叢集同步。建設系統雙活,跨叢集的地域複製在客戶端無感的情況下實現訊息同步。
- 計算儲存分離。根據使用情況橫向擴充套件儲存 / 計算,客戶端對此操作無感知。基於二級儲存的功能,擴充套件訊息的使用場景,為資料分析、訊息審計提供可能。
- 客戶端接入認證模組外掛化,支援自定義開發。因業務需求,在客戶端接入時,要求鑑權、認證,有效保證訊息的來源可靠、可控。
- 完善的 Rest API,可檢視佇列情況。之前使用的訊息系統有很好的效能,但在可觀測性方面有所欠缺,給系統排障造成困難,同時訊息系統的管理方式較為原始,難以適配大規模系統管理的要求。而 Apache Pulsar 完善的 Rest API 不僅可以獲取系統執行指標,且有助於叢集的高效管理。
- 基於 Functions 可實現訊息的路由開發、過濾和統計等。
- 可設定訊息的持久化模式和過期時間,允許訊息重放。
- 多語言支援,快速便捷接入。
Apache Pulsar 在平安證券的業務場景
平安證券使用 Apache Pulsar 構建統一訊息平臺,期望整合客戶、交易、行情、資金四大資料流,應用於行情分發、實時風控等。本文主要介紹如何將 Apache Pulsar 應用於三個業務場景:請求路由、資料廣播和訊息通知,新架構的優勢和不足,以及其對開發、運維團隊的影響。
場景一:請求路由——簡化系統
我們的訊息路由流程如下圖。從 A 元件發出的請求寫入到 Topic A,然後由路由模組將 topic 中的資訊進行路由,分發到多個對應的 topic,訂閱了這些 topic 的下游元件就可以處理相關的訊息。元件 A 只需要向固定的佇列寫入訊息,不需要關注 Topic B、C、D 的資訊,下游系統只需要瞭解接收訊息的佇列,不需要關注 Topic A,從而簡化整個網路的結構。
這種訊息路由模式簡化了系統的整體架構,目前我們的路由系統仍待優化:
- 雖然路由分發的工作量得以減輕,但排查問題的步驟有所增加。比如在元件 A 傳送訊息後,元件 B 沒有收到訊息時,需要先檢查元件 A 是否寫入訊息到 Topic A、路由模組是否成功路由這一訊息,再看元件 B 是否正確訂閱了這條訊息。
- 從目前的測試效果看,由於訊息鏈路變長,時延增加。
- 由於每個佇列的訊息都會持久化,導致儲存和佇列中都出現資料冗餘。
- 路由模組是新增模組,運維的學習成本較高。
場景二:資料廣播——降低時延
資料廣播是我們使用 Apache Pulsar 的另一個業務場景。資料廣播採用傳送 / 訂閱模式,主要用於同步訊息。很久之前,我們不需要同步行情到業務系統,或是通過其他方式(如同步資料庫)實現。但隨著業務的增長,同步時效和使用者體驗的競爭度越來越激烈。如何可以讓使用者更快地看到資訊?以同步行情的場景為例,先同步資料庫再查閱的方式,時延相對較長;而在廣播模式中,業務系統只需訂閱所有需要的 Topic,查閱時即可直接讀取資料,有效降低時延。
場景三:訊息通知——安全管控
我們使用到 Apache Pulsar 的第三個場景是訊息通知。雖然訊息通知涉及到的業務相對較少,但這一業務場景十分重要。整體業務流程圖如下。由於訊號源不唯一,因此在訊息釋出到計算引擎後,計算引擎需要根據訊號源的資訊進行邏輯、安全等方面的計算。計算完成後調起 Task,再由啟用的 Task 向相關業務系統傳送業務請求,執行後將結果返回給發起訊號源的服務,該服務根據返回的結果觸發下一個訊號源。
這一場景涉及到的業務對安全和管控的要求非常嚴格,不僅需要限制訊號源傳送的訊息或訊號,截斷 / 過濾某些訊號,還需要對返回的結果進行處理:哪些可以返回,哪些需要過濾掉或轉換成其他內容。如果不使用訊息佇列方式,訊息源會直接傳送訊息給計算引擎,在計算引擎執行安全或管控策略後,將訊息傳送到 Task; 在 Task 執行完成後,其結果需要再進行一輪安全管控處理。這一部分的重複操作對效能影響較大,同時策略更新、訊號狀態檢視的時效性沒有那麼實時。
引入 Apache Pulsar 後,我們將管控審計模組剝離出來,專門針對訊號佇列和結果佇列進行過濾、審計、統計等操作,並實時輸出結果到管理端。運維或審計人員在看到這些資訊後,可以控制、更新相應策略。這一模式不僅可以精簡資料流,還可以增加資料補充渠道,也更清晰地定義了各服務模組的邊界。
問題發現與解決方案
目前我們主要在上述三個場景中探究了 Apache Pulsar 的使用,並逐步上線生產。在使用過程中,我們發現了幾個問題,並在此分享我們的解決方案以供參考。
1. 實現 REQ-REP 模式
我們遇到的第一個問題是如何實現請求 - 響應(REQ-REP)模式,我們的解決方案是通過匯流排模式進行相容。
目前常見的呼叫方式是客戶端發起呼叫請求,服務端處理完成後返回響應即可。但引入匯流排以後(同步轉非同步),在多節點的部署場景中,節點 1 發出請求,服務端收到請求後返回處理結果,所有節點都需要監聽這條處理結果,節點 2 收到歸屬節點 1 的響應訊息時應該如何處理?節點 2 需要先訂閱並獲取回包的訊息,判斷是不是自身節點發起請求的響應,如果不是,則丟棄此訊息。假如按照這種模式進行實現,則在傳送訊息時,每個節點都需要快取自身傳送的訊息 ID;服務端處理完以後,按照協議回包資料需要帶上請求的訊息 ID,每個節點都訂閱獲取所有回包,並校驗快取中是否有該訊息 ID,若不存在,則丟棄訊息。
該實現方式下存在一個非常嚴峻的問題亟待解決:節點發起一個查詢大量資料的請求時,假定 Apache Pulsar 設定一個訊息 的大小為 8M,TPS 為 1000,那是不是每個節點都要收到這麼多請求的回包流量呢?假如有 5 個節點,每個節點本應該只接收 200 個請求的回包流量就夠了,但現在的模式需要每個節點承受 1000 個請求的回包流量,而其目的僅僅是為了過濾操作。如果節點負載效能達到上限,需要擴容節點,將導致網路頻寬成倍增加。由於 Apache Pulsar 可以支援大量 Topic,雖然通過給每個節點配置一個回包佇列等方式可以解決這一問題,但我們想嘗試通過 broker 的 FILTER 功能,來解決該問題。
2. 實現讀寫分離
訊息廣播場景會涉及到讀寫分離。如果增加大量訂閱節點,最好避免將所有節點的連結集中在 Topic 的 owner broker 上。針對這個問題,可行的解決方案是合理分配使用的 Topic 和 Partition。我們目前使用的 Apache Pulsar 2.7.2 還不支援讀寫分離,計劃把 Apache Pulsar 升級到 2.8,就可以輕鬆實現讀寫分離,滿足訊息廣播場景的需求。
3. 解決多網路卡問題
基於公司網路安全考慮,內部存在多種網路分割槽及網段,不同的網路分割槽 / 網段使用不同的 IP,伺服器存在多個網路卡,供跨分割槽系統間通訊。目前如果使用 IP 註冊 broker,只能註冊某個網段的 IP;如果使用域名註冊 broker,則不同網路區域的 DNS 解析又需要進行不同的配置。如果 broker 可以支援多網路卡通訊,這些問題就不存在了。目前我們的解決方案是用 proxy 代理客戶端的請求,外部系統也只連線到 proxy,我們也會為 proxy 增加一些高可用的配置。
未來規劃
目前 ,我們在單機房、單叢集線上小規模執行 Apache Pulsar,在上線初期未考慮建設雙活。作為業務系統的基礎設施,Apache Pulsar 自身可用性極為重要。因此,我們計劃基於同城雙中心單叢集建設進行雙活規劃,如圖如示:
在測試和使用 Apache Pulsar 的過程中,我們遇到了一些問題,感謝 Apache Pulsar 社群的積極響應。我們期待更多地參與到 Apache Pulsar 的研發中,也期待為 Apache Pulsar 和 Apache Pulsar 社群做出貢獻。
作者簡介:
- 王東鬆,平安證券經紀業務事業部研發工程師。
- 陳翔,平安證券經紀事業部架構師。
加入 Apache Pulsar 中文交流群 ??