在 2021 年 11 月 12 日落地的 ArchSummit 全球架構師峰會(深圳站)上,我們邀請了微眾銀行的資深技術專家陳廣勝為大家帶來了《分布式應用提效框架 Apache EventMesh》的分享,他從 EventMesh 的特征入手,為大家深入介紹了 EventMesh 在微眾銀行的探索與實踐。本文為演講整理文章~
今天分享 Apache EventMesh 事件驅動的分布式應用運行時,這是一個比較新的概念,希望可以通過本次的分享,給大家帶來一些啟發。
我們都了解兩個概念——消息和事件,消息指的是具體事件的更新,這種更新是從一個點發送到另外一個點之后,消息就會被刪除,消息是臨時存在的狀態;而事件是指在特定時間發生的,它并沒有綁定到具體的接收者或客戶端,它往往是可以被回放、回溯和再加工。
根據 Gartner 的一份報告顯示,隨著時間的推移,數據的價值將逐漸減少。在很多實時場景下,如果能夠對事件進行實時的分析和數據挖掘,那將會帶來很大的價值,像現在非常火的流式計算 Flink、Spark 以及 ClickHouse 等,他們都非常關注數據的實時性,EventMesh 可以及時地傳遞數據。
EventMesh
我們先來了解 EventMesh 架構圖,EventMesh 的定位是事件驅動分布式應用運行時。EventMesh 可以提供非常輕量級、多語言的客戶端以及各種各樣的協議,例如 MQTT、Cloudevents、Web Socket 和 MQP,與此同時,它可以提供 gRPC、TCP 和 HTTP 等傳輸的協議。
EventMesh Runtime 是一個插件化的架構,可以對接到后端的中間件或者服務,比如事件的存儲 RocketMQ、Kafaka 以 及 Apache Pulsar 等;如果需要有一些狀態更新維護的時候,可以對接到后端的 redis、MySQL 以及 Mongo DB 等;如果需要有一些冷數據更新的時候,也是可以通過插件化的形式連接到 S3,ES 等存儲。
在控制層面,如果需要對事件的調用鏈進行跟蹤、元數據進行管理以及分布式協調性的時候,EventMesh Runtime 也可以對接到 ETCD、NACOS、 Prometheus、Zipkin、Skywalking
、OpenTelemetry 等。我們內部最常用的是 RocketMQ 以及 Redis 兩個插件,不過 EventMesh 也可以很方便地與 Kubernetes 進行集成,這是因為 EventMesh Runtime 可以作為 Sidecar 部署,也可以作為 Gateway 部署。
我們再看一下當前在微服務領域的 REST Drive 和 Event Drive,他們各自的優缺點非常明顯。就 Spring Cloud、HTTP2、gRPC 通信而言,當 REST 調用服務的時候,由于工業界非常完善的工具文檔以及開發工具客戶端,開發起來非常方便,但是 REST Drive 的所有調用都是同步的,同步則意味著阻塞。如果在一個鏈中,任何節點的服務出現緩慢調用或故障,那么便會影響到最前端的服務調用,那么當 Spring Cloud 與 Dubbo 服務建立通信的時候,需要付出更多的成本。
然而在事件驅動領域,當接入網關或進行業務層面的框架層適配的時候,它的調用是異步的,所有的狀態是最終一致的,并且可以與很多的服務以及中間層解耦。另外像 Queue 訂閱發布方式,擴容非常方便。但是它需要依賴一層中間件,中間件的復雜度需要人工處理,不過這層復雜度可以使用 EventMesh 屏蔽掉,所以對應用的開發本身而言,輕量又便捷。
SeviceMesh vs EventMesh
接下來分享一下 SeviceMesh vs EventMesh 的區別。
SeviceMesh 需要 Sidecar,所有數據層面的通信是在 Sidecar 之間的轉發,不過在 EventMesh 中,我們看到單個或多個服務可以掛在 EventMesh 的單個節點,EventMesh 具備較強的微服務編排能力,但是 EventMesh 并不能解決所有的問題,它的優勢在于事件驅動,它也可以做到 Request、Reply。
服務有同步和異步之分,同步調用可以采用 SeviceMesh,異步調用可以采用 EventMesh 。當然 EventMesh 也可以做同步調用,SeviceMes 也可以做異步調用,但是兩者本身的定位以及處理的場景不一樣,所以 SeviceMesh 與 EventMesh 可以結合使用。
例如,前端 Web App 通過 API 網關進來的調用,轉發到前置或某個業務領域的服務,它會進行內部服務之間的調用,這個過程便會產生數據,數據會進入到關系型數據庫或者 NoSQL 數據庫。但是入數據庫的這一動作,可能需要讓其他的服務訂閱或關注到,這個時候,我們可以將事件或者服務轉發給 EventMesh,讓 EventMesh 驅動關心這些事件的服務進行后續工作。
接著,我們一起看看 EventMesh 的作用。
在 DMZ 區或 ECN 區域,部署網關或者前置服務的作用是為了進行協議的轉換——從外部的 HTTP 或 HTTPS 接口協議的服務,轉換到內部不同的服務框架(例如 Dubbo、Spring Cloud)的協議。當外部、公網或者合作方流量進入此區域的時候,內部區域將會形成非常復雜網狀的結構,邊界區流量治理非常不方便。
現在的通用做法是在邊界布置網關,但是當有了 EventMesh 之后,我們只需要在外聯區和內部區域布置兩個 EventMesh(可以是集群,也可以是節點),這樣邊界區的服務只需要在 EventMesh 之間進行通訊,而且當請求到了內部服務的時候,通過內部區域的 EventMesh 可以形成很多網格,每一個 EventMesh 網格代理了向其注冊的服務。不同的 EventMesh 以及其代理的服務連接起來,形成較大的事件網格,很多復雜調用場景的治理將會變得極其簡單。
EventMesh Feature
這一部分我將會介紹幾個重要的 EventMesh Feature。
Pub/Sub+
現在有非常多各種云以及私有部署環境下的服務,服務與服務之間的連接可以通過 EventMesh 來完成。不同的區域的服務,使用的協議和語言不一樣,但是通過 Pub/Sub+的形式增加的任何協議、節點、服務,都可以統一匯聚到 EventMesh 形成的網格中。
舉個例子,當大家在亞馬遜云上發布事件之后,私有化部署 Kubernetes 的某服務節點訂閱了這個消息,消息可以跨越很多節點路由到 Kubernetes 服務。同時,當多個區域的服務訂閱了相同的主題,只要將消息發送到對應的主題,對應的服務會自動將消息接收下來。EventMesh 可以解決連接協議的多樣性、語言的多樣性,并且可以解決邊界區的連接問題。
事件總線
事件驅動架構(EDA)是一種以事件為紐帶,將不同系統進行解耦的異步架構設計模型。在 EDA 中,事件驅動的運行流程天然地劃分了各個系統的業務語義,用戶可以根據需求對事件與針對此事件做出的響應靈活定制,這使得基于 EDA 架構可以方便地構建出高伸縮性的應用。
HTTP Source 事件源是 EventMesh 支持的事件源的一種,它以 Webhook 形式暴露了發布事件的 HTTP 請求地址,用戶可以在有 URL 回調的場景配置 HTTP Source 事件源,或者直接使用最簡單的 HTTP 客戶端來完成事件的發布。HTTP Source 事件源提供了支持 HTTP 與 HTTPS,公有云 VPC 等不同請求方式、不同網絡環境的 Webhook URL,便于用戶將其集成到各類應用中。接入時無需使用客戶端,僅需保證應用可以訪問到對應 Webhook URL 即可,這使得接入過程變得簡單而高效。
在將 HTTP 請求轉換為 CloudEvent 的時候,EventMesh 會將請求的頭部和消息體部分置于 CloudEvents 字段中,其余字段會依據用戶 EventMesh 資源屬性以及系統默認規則進行填充。用戶可以在事件規則中,對所需的內容進行過濾、提取,最終按照模板拼裝成所需的消息內容投遞給事件目標。
Streaming
在當前的微服務下,當我們進行流量調度的時候,肯定需要解碼消息頭,根據消息頭的特定字段,路由到對應的服務上以便增加策略。
實際上在事件驅動中,首先我們不需要解碼報文,我們在它的消息主題設計上,可以解決類似的問題。比如可以設計非常多 Topic 層級,層級與層級之間有遞進關系,以此來實現動態的過濾。其次,當消息到達之后,可以很方便地針對消息進行報文解析,在產生的事件上面,我們可以增加非常多的 Match 處理函數,產生的消息可以實時地經過 filter chain 的處理。事件的處理都可以由 EventMesh 來完成。
編排與協調
在上圖的左邊區域,當寫入復雜的 Case、If else 條件或引入工作流之后,它的編排有很多串行的分支,但是如果采用 EventMesh 編排,看起來將會非常簡潔。
我們只需要訂閱感興趣的事件,發送對應的事件到對方主題上就可以,我們并不需要關注對方 IP 的所在地,也不需要關注服務部署在虛擬機還是在容器上,以及對方服務實例數量,當然更不需要關注對方實例掛了之后,我們是否需要進行熔斷等等。下游的 EventMesh 可以完成所有的事情,例如,當它下游的服務發生故障,消息將會自動分發到當前在線的服務實例。從上面這張圖,大家可以看出,采用 EventMesh 可以使得編排與協調過程更加清晰。
動態擴縮容
接下來是擴縮容場景,當現有的 Kubernetes 在進行擴縮容的時候,有兩個常見的場景。
首先是擴容場景,例如,在當前的 CPU 占用很高的時候,正常情況會觸發擴容事件,但我們在消息隊列中,并沒有看到特別多的消息堆積,也就是說,這個時候并不需要擴容,實際上這個擴容是浪費的;其次是縮容場景,例如在消息隊列里,當前沒有消息堆積,理論上實例是可以縮容,甚至可以縮容到零,但是因為 CPU 的使用導致無法順利縮容。
但是這兩種場景,如果在事件驅動的服務下,我們采用 Queue 隊列堆積的監控方式可以實現以下效果。首先是在資源占用很高,但隊列的任務沒有堆積的情況下,可以不進行擴容;其次,在占用當前的 CPU 的資源,但沒有任務處理的情況下,可以進行縮容。在我看來,伸縮監控的指標應該根據當前處理的任務堆積情況來判斷。
Bridge(Federated Governance)
沒有治理前,就如下圖一樣,各個不同區域之間形成了數據的孤島。
但當治理之后,就變成了下圖一樣的這樣網格狀態,清晰且簡潔。
在過去十年的大部分時間里,企業都在與數據孤島作斗爭,數據孤島是孤立的持久性存儲,擁有無數但無法訪問的知識,他們的主要武器是數據湖:一個巨大的集中式數據存儲,將 TB 級的特定于域的數據保存在一個邏輯位置。沒有領域知識的數據專?家試圖從不同的數據集中挖掘數據價值是很困難的,而且幾乎沒有動力向數據湖貢獻高質量數據的數據生產者。
EventMesh 具備實時分析、大規模數據收集、平臺無關的連接以及對開放標準的支持等能力,理想情況下,對客戶數據的任何更改都應通過事件網格之類的東西實時推送給依賴的消費者,但如果數據不太重要或不及時,數據消費者可以在需要時提取(或查詢)數據。
我們正在從數據無政府狀態過渡到聯合治理和成熟的企業數據策略——理想情況下,可以將策略有效地表示為代碼的最終狀態。聯合治理需要特定于任務的工具、事件目錄和 AsyncAPI 等標準。企業級數據策略還包括訪問控制、法規(即 GDPR)、機密性(如 PII 和 PHI)、編輯和加密等特性/功能。功能的示例可能包括強制性標頭元數據(將數據上下文化)、可觀察性要求、主題結構(用于路由)以及通過模式驗證和其他工具實現的數據質量。
EventMesh in WeBank Message Bus(DeFiBus)
在微眾銀行,已經開源的消息總線 DeFiBus 如上圖所示,這里以三個 EventMesh 的節點為例,每一個 EventMesh 節點,可以在其上面訂閱服務。當發送方發布一個事件之后,其他的 EventMesh 上的任何服務,只要訂閱了 Topic,這個事件便可以發送到對應的服務上,它能夠自動地學習和更新路由表。
EventMesh 在微眾銀行內部解決了以下問題,首先是多語言治理問題,例如 AI 計算使用 Python、很多銀行的系統使用 C 語言,EventMesh 能夠簡化接入消息總線的復雜度,同時我們知道,推動業務的 SDK 的升級非常麻煩,當 SDK 輕量簡化之后,我們只需要負責中間件層的發布,就可以節省掉應用推動升級的成本。除了應用在業務系統外,EventMesh 還應用在流量復制回放平臺,消息旁路過濾,消息多活路由,AI 聯邦學習,區塊鏈等場景,更多的場景在持續探索實踐過程中,未來有機會再分享給大家。
Summary
今天的 IT 系統正在生成、收集和處理比以往更多的數據。而且,他們正在處理高度復雜的流程(正在自動化)以及跨越典型組織邊界的系統和設備之間的集成。同時,預計 IT 系統的開發速度更快、成本更低,同時還具有高可用性、可擴展性和彈性。為了實現這些目標,開發人員正在采用架構風格和編程范式,例如微服務、事件驅動架構、DevOps 等。正在構建新的工具和框架來幫助開發人員實現這些期望。開發人員正在結合事件驅動架構 (EDA) 和微服務架構風格來構建具有極強可擴展性、可用、容錯、并發且易于開發和維護的系統。
EventMesh 作為事件基礎設施,主要負責事件的傳輸、路由和序列化。它可以提供用于處理事件流的 API。事件基礎設施提供對多種序列化格式的支持,并對架構質量(例如容錯、彈性可伸縮性、吞吐量等)產生重大影響,也可以存儲事件以創建事件存儲,事件存儲是恢復和彈性的關鍵架構模式。
了解更多軟件開發與相關領域知識,點擊訪問 InfoQ 官網:https://www.infoq.cn/,獲取更多精彩內容!