Categories
程式開發

金融巨頭Capital One的無服務器實踐


金融巨頭Capital One的無服務器實踐 1

你是否想過,在月底結賬時,你才發現自己的賬戶有錯誤交易?也許你遇到過這種事,並且印象深刻。數字化革命讓你可以隨時隨地獲取自己的信息。無疑,我們離未來世界不遠了。在這個世界,相關信息可以在有需要時出現,你無需去尋找。

Capital One正致力於使我們做的幾乎所有事實時化。通過改進云計算和大數據工程工具,它不斷為解決方案增加實時特性。我們的團隊一直專注於為客戶帶來與其相關的、實時的個性化洞察。我們試圖找出客戶消費行為中非常特殊的交易,例如餐廳消費高得離譜、重複賬單的增加、全新免費試用的開始和多次重複交易等等。

經過多年發展,Spark框架逐漸發展成大規模實時流和批處理需求的首選技術。但是,伴隨強大計算能力而來的是更高的操作和維護成本,我們開始體會到為滿足實時流需求而運營Spark基礎設施帶來的痛苦。

所有,我們團隊接受挑戰,找到一個更簡單、維護少且高度可伸縮的模式,並且圍繞其設計一個無服務器流解決方案。

為何Apache Spark並非所有實時流用例中的”銀彈”?

據Databricks的博客,Apache Spark是處理大規模批處理和流數據的最快開源引擎之一。這點顯而易見。既然Spark性能如此出色,為什麼我們還要考慮使用其他的東西?

金融巨頭Capital One的無服務器實踐 2

圖片來自Databricks blog

然而,讓我們根據應用程序的需求評估下,比如:

  • 應用程序每秒加載記錄是多少?如果它每秒低於幾千,那Spark可能多餘;
  • 為實現高彈性,應用程序所需的驅動程序和工作容器的最小數量是多少?如果在雲上,請考慮將其分佈到多個可用區和區域;
  • 安裝像Zookeeper這樣的資源管理器來維護Spark集群需要多少容器? ;
  • 你是否考慮過雲或數據中心的區域故障?如果是,那你可能已經體驗過讓Spark集群跨區域可用的架構複雜性;
  • 你的工作負載每天是否是固定的?如果是就太棒了,這對你的生意有好處。但是,大多數實時系統在每天、每周和每年都有周期性的工作負載,所以一定要考慮在非高峰時間系統的利用率;
  • Spark作業在任何時候都可能失敗。你考慮過作業的錯誤處理、監控和自動恢復嗎?要實現這一點,需要很大的開發工作量;

不要忘記開發成本,這是所有成本中最大的一部分。考慮工程師在開發Spark基礎設施時所需的所有特殊技能,比如像Scala或Python這樣的編程語言、安裝和管理Spark基礎設施的腳本知識以及Spark緩存等。

儘管Apache Spark有著令人印象深刻的效果,但是如果你關心Apache Spark的運營開銷,那麼無服務器流解決方案可能是更好的選擇。事實上,大多數實時流用例的加載速度都低於每秒1000個事務。

不必因為小的工作負載而去應對Spark基礎設施的複雜性。相反,使用無服務器流解決方案來簡化你的代碼,可以極大降低成本和復雜性。

一個架構良好的流解決方案包含哪些?

在實現幾個與流相關的用例後,我認為理想的流解決方案應滿足以下需求:

伸縮

在現代應用程序架構中,自動伸縮被視為基本的設計考慮因素之一。在雲計算時代,你可以根據需求獲得無限的計算能力,因此不需要因為峰值負載進行擴展並支付額外費用。

雖然你能規劃好主要的周期性工作負載,但是,在傳統的基於服務器的基礎設施中,你很難在一分鐘內對其進行優化。理想情況下,應用程序應該能在請求出現較大峰值時自動修復以及自動伸縮。

限流

通常,流應用程序被設計成每秒接收成千上萬個請求,並最終降到一個更易於管理的範圍。當出現意料之外的峰值時,流應用程序可以橫向擴展,但是下游的阻塞調用(API、DB等)可能無法擴展。

因此,限流成為任何流應用程序的基本需求之一。記住——你係統的好壞取決於最薄弱的環節。

容錯

應用程序總是與其他資源(如API、數據庫等)相連接。相關係統難免出現故障,但同時,我們也希望保護應用程序不受這些問題的影響。

在流應用程序中,容錯是關鍵需求之一,因為你不希望在後端系統宕機時丟失數據。

重用

與重新創建解決方案相比,我們常常更關注重用。重用的程度取決於組件的模塊化和大小,而微服務是重用的最佳示例。通過使流解決方案的構建塊更小且可配置,我們可以加強跨多個應用程序的組件重用。

監控

想像一下,數百萬條消息/事件流經你的應用程序,你能跟踪每一條消息並了解該消息究竟發生了什麼。當你構建面向客戶的關鍵應用程序時,這一點變得更加重要,並且需要查明特定的客戶事件究竟發生了什麼。

因此,對於同步或異步系統來說,監控都非常重要。

我們是如何構建無服務器流架構的?

那麼,我們如何構建我們的解決方案?

我們的無服務器流架構是基於事件驅動的微服務架構建模的,其中每個微服務使用消息總線彼此連接。

金融巨頭Capital One的無服務器實踐 3

本質上,事件驅動的架構提供了我們需要的流解決方案的所有功能。基於雲服務商提供的託管服務實現事件驅動架構,就可以構建無服務器的流解決方案。

對於上述模式,如果你將託管服務(如AWS Lambda)作為微服務,AWS Kinesis作為消息總線,就可以使用無服務器技術棧實現事件驅動的架構。

我們將整個架構分為三層——源、接收(Sink )和處理。

  • :在這一層中,微服務只負責從源獲取數據。可以將其視為事件進入流應用程序的入口。例如:從Kafka集群讀取事件。
  • 處理:該層負責處理從源層獲得的事件。你還可以將其視為一個能擁有具體應用程序邏輯的層。例如:過濾事件或調用API來針對事件做出決策。你可以有一個或多個處理層來映射、縮減或增加你的消息。
  • 接收:這是應用程序的最後一層,在這裡對事件進行最後操作。例如:將事件存儲到數據存儲中,或者通過API調用觸發其他進程。

下面是從消息驅動架構到AWS服務的映射。

金融巨頭Capital One的無服務器實踐 4

在上圖中,你可能會覺得有很多重複動作,特別是從Lambda到從Kinesis寫/讀的動作。你可以發揮創造力,針對重複的功能構建某種類型的庫。

在Capital One,我們正是這樣做的。我們構建了內部SDK來抽象重複任務。 SDK有以下特點:

  • 從消息總線讀寫:從消息總線(Kinesis或將來的其他服務)讀寫事件。
  • 異常處理和重試:主要有兩種重試,阻塞和非阻塞。當後端應用程序失敗時,你可以阻塞錯誤重試,直到它恢復。當你只希望特定事件重試而對其他事件沒有任何影響時,使用非阻塞重試。
  • 秘密管理:當你不希望在無服務器函數中存儲憑據時,將需要此功能。你可以選擇企業秘密管理工具,並將它們集成為你的庫的一部分。
  • 監控:我們創建了自定義的消息信封,其中包含幫助我們跟踪每條消息的元數據。 SDK可以替開發人員承擔這些工作,在每個微服務進入/退出時插入/刪除信封。
  • 日誌記錄:為實現跨所有微服務的統一體驗,你可以在SDK中構建日誌記錄模式。
  • 消息去重:我們知道,大多數分佈式快速數據系統保證至少一次傳遞。當你想要過濾掉重複的消息時,可以考慮將其抽象為庫的一部分。你能使用哈希或其他方法來實現具有亞毫秒延遲的消息去重。

它如何滿足我們的流解決方案需求

正如我們前面所討論的,任何無服務器流解決方案都需要解決伸縮、節流、重用、容錯和監控等問題。這是如何實現的呢?

伸縮

這種架構模式與天生可伸縮的雲和服務相結合,讓這一切成為可能。

  • 該模式使用Lambdas實現微服務,並通過Kinesis進行連接。我們只需要擴展具有高TPS的Lambdas,隨著消息被過濾掉,相應地調整規模配置。
  • 按照設計,無服務器函數是可自動伸縮的。例如:如果你使用Lambdas和Kinesis,你可以擴展Kinesis,如果你的消息吞吐量從2MB/秒增加到4MB/秒,這也將擴展與Kinesis相關的Lambda函數。

金融巨頭Capital One的無服務器實踐 5

限流

限流的基本功能是,如果你的輸入請求速率遠遠高於下游所能支持的速率,則需要保存你的請求。在這裡,消息總線持久化特性能幫助我們,因為你只能選擇一次可以處理的消息數量,並保存其他消息。

例如:如果你使用Kinesis作為消息總線,則能指定你在函數中處理的批次大小。

重用

如果我們可以構建source微服務和sink微服務,讓它們不具有任何業務功能,並且是基於配置的,那麼就可以多個團隊都使用它們來消費事件。

例如:如果你能構建源函數來消費來自Kafka的事件,這些事件可以對主題名稱、代理地址等進行配置,那麼任何團隊都可以根據需要使用該函數並將其部署到他們的棧中,而無需更改任何代碼。

以上可以幫助我們實現代碼級的重用。另一種重用是流本身的重用。如果你為自己架構選擇的消息總線是基於發布/訂閱的總線,那麼你能有多個訂閱者來訪問相同事件。例如:你可以將事件fan out到兩個微服務,而無需單獨編寫額外代碼。

容錯

同樣,消息總線在這裡也可以對我們提供幫助。考慮一下,如果你的後端服務出現錯誤,你可以將所有/失敗的消息保存到消息總線中,然後重試,直到後端調用開始成功。

監控

作為SDK的一部分,記錄元數據有效負載能幫助我們實現跨不同功能的日誌一致性。你還可以構建一個可重用的函數,該函數能將你的日誌轉發到首選的監控解決方案。

金融巨頭Capital One的無服務器實踐 6

這聽起來就像說無服務器流解決方案是銀彈,我不需要Spark

並非如此。 Apache Spark是一個分佈式計算平台,在大規模分佈式數據處理負載上表現出色。當涉及高容量計算和批處理時,數據和計算功能可以採用分佈式,並且能並行執行,Spark仍然是首選工具。典型例子包括機器學習用例的重量級計算需求,涉及幾百個文件的Map/Reduce範式,或者處理PB級數據的長時間運行的進程等等。 Spark也能作為實時流領域的首選工具,但前提是流量非常大,每秒執行數十萬個事務。

在Capital One,我們使用多種多樣的大數據工程工具。在我的團隊中,我使用了無服務器流來處理大容量的用例,比如根據每秒數千個事件的客戶交易生成有意義的警報,以及處理每秒數十個事件的小容量用例,比如補卡。我還使用Spark來處理大型交易文件,使用機器學習模型生成客戶的消費檔案。這完全取決於具體的需要。

英文原文:

Scaling to Billions of Requests-The Serverless Way at Capital One