在這篇文章中,咱們將討論流式處理所面臨的挑戰、Keystone 的設計原則、思惟模式、架構總覽、咱們的願景以及 Keystone 爲 Netflix 所帶來的核心價值。後端
單個流式做業:網絡
經過平臺管理這些做業:架構
流式處理的挑戰1. 伸縮app
Netflix 爲來自 190 多個國家的 1.3 億用戶提供服務。流式處理平臺天天處理數萬億個事件和 PB 級別的數據,以支持平常的業務需求。隨着用戶數量的持續增加,整個平臺須要進行伸縮。框架
2. 多樣化的用例機器學習
Keystone 路由服務:這個服務負責根據用戶的配置將事件路由到託管接收器上。每一個傳遞線路都經過並行流式處理做業來實現。用戶能夠定義可選的過濾器或投影聚合。事件最終被傳遞給存儲接收器,便於後續的批處理或流式處理(這些處理實現了至少一次語義)。用戶能夠在延遲和重複處理之間作出權衡。分佈式
流式處理即服務:SPaaS 平臺只在生產環境中運行了大約一年時間,但咱們已經遇到了各類各樣的需求。如下是一些常見的問題和權衡。ide
做業狀態:從徹底無狀態並行處理到須要數十 TB 本地狀態存儲的做業。微服務
做業複雜性:從將全部 operator 連接在一塊兒的並行做業,到具備多個 shuffle 階段和複雜會話邏輯的複雜做業 DAG。工具
窗口 / 會話:窗口大小從幾秒鐘(即捕獲事務的開始 / 結束事件)到數小時的自定義會話窗口。
流量模式:不一樣用例的流量模式存在很大差別。它們多是突發的,也可能保持在 GB/ 秒級別不變。
故障恢復:有些用例須要秒級的低故障恢復延遲,看成業持有很大的狀態並涉及 shuffle 時,就變得至關具備挑戰性。
回填(backfill)和回放(rewind):某些做業須要從批處理數據源重放數據或從先前的檢查點回放數據。
資源爭用:做業可能會在任何物理資源上產生瓶頸:CPU、網絡帶寬或內存等。用戶依賴平臺提供的用於進行性能調整的看法和指導。
重複與延遲:應用程序在重複與延遲方面可能有不一樣的權衡偏好。
事件排序:大多數用例不依賴嚴格的排序,但有些確實會依賴排序。
傳遞和處理語義:某些用例容許管道中丟失一些事件,而其餘用例可能要求更高的持久性保證。某些有狀態的流式做業指望具有剛好一次處理保證,計算狀態須要始終保持一致。
用戶受衆:咱們的用戶羣十分普遍,從技術嫺熟的分佈式系統工程師到業務分析師,有些團隊選擇基於咱們的平臺產品構建特定領域的平臺服務。
3. 多租戶
Keystone 支持數千個流式做業,從數據傳輸、數據分析,一直到支持微服務架構模式。由於流式做業的多樣性,爲了向每一個用戶提供有意義的服務級別保證,基礎設施須要提供運行時和運營隔離,同時還要最小化共享平臺開銷。
4. 彈性
儘管大多數流都具備固定的流量模式,咱們仍然須要讓系統可以應對突發狀況(流行的節目上線或意外故障引發的流量爆發),並且可以自動適應並對這些狀況作出響應。
5. 雲原生彈性
Netflix 的微服務徹底是在雲端運行的。雲具備彈性、持續變化、更高的故障率等特色,所以咱們須要讓系統可以監控、檢測和容忍故障,包括網絡不穩定、實例故障、區域故障、集羣故障、服務間擁塞或回壓、區域災難故障等。
6. 運營開銷
咱們的平臺目前爲數千個路由做業和流式應用程序提供服務。若是依靠平臺團隊手動管理全部流,成本會很高。所以,應該由用戶負責聲明做業的生命週期,同時基礎設施應該儘量自動化。
7. 敏捷性
咱們但願可以進行快速的開發和部署,天天能夠進行屢次部署。咱們也但願可以保持用戶使用平臺的敏捷性。
平臺思惟與設計原則1. 可實施性
這個平臺的主要目標之一是讓其餘團隊可以專一於業務邏輯,讓流式處理做業的實驗、實現和運營變得更容易。經過平臺將「難啃的硬骨頭」抽離出來,消除用戶的複雜性,這將極大提高團隊的敏捷性並促進產品的創新。
咱們努力讓用戶可以:
快速發現數據和開展試驗,經過數據驅動的創新來推進產品的發展;
快速的流式處理解決方案原型設計;
充滿信心地進行服務的生產和運營;
深刻了解性能、成本、做業生命週期狀態等,以便可以作出明智的決策;
進行自助服務。
2. 構建塊
爲了可以讓用戶專一於業務邏輯而沒必要擔憂分佈式系統的複雜性或某些預先存在的解決方案的通常性細節,咱們須要爲用戶提供一組能夠輕鬆接入到流式做業 DAG 的可組合 operator。
此外,流式做業自己也能夠成爲其餘下游服務的構建塊。咱們與一些合做夥伴團隊合做,構建「託管數據集」和其餘特定領域的平臺。
咱們還努力經過利用其餘構建模塊(如容器運行時服務、平臺動態配置、通用注入框架等)與 Netflix 軟件生態系統深度集成。這不只有助於咱們基於其餘現有解決方案構建出新的服務,還讓咱們的用戶更加熟悉開發和運營環境。
3. 可調整的權衡
任何一個複雜的分佈式系統自己都有必定的侷限性,所以在設計這種系統時須要考慮到各類權衡,如延遲與重複、一致性與可用性、嚴格排序與隨機排序等。某些用例還可能涉及各類權衡組合,因此平臺必須提供調整入口,爲我的用戶提供定製的可能性,讓他們能夠聲明對系統的需求。
4. 故障是頭等公民
在大規模分佈式系統中,故障是一種常態,在雲環境中就更是如此。任何設計合理的雲原生系統都應該將故障視爲一等公民。
如下是影響咱們設計的一些重要方面:
假設網絡是不可靠的;
信任底層運行時基礎設施,但須要自動修復能力;
實現多租戶的做業級別隔離;
出現故障時減小影響範圍;
出現組件狀態漂移或發生災難故障時可以進行自動調節;
正確處理和傳播回壓。
5. 關注點分離
在用戶和平臺之間:用戶應該可以經過平臺 UI 或 API 聲明「目標狀態」。目標狀態被保存在單個事實源當中,應該由平臺做業流程負責處理從「當前狀態」到「目標狀態」的變化。
在控制平面和數據平面之間:控制平面負責做業流程編排和協調,數據平面負擔處理繁重的任務,以確保一切處在目標狀態內。
在不一樣的子組件之間:每一個組件負責本身的做業和狀態。每一個組件的生命週期都是獨立的。
運行時基礎設施:流式處理做業部署在開源的 Netflix Titus Container 運行時服務上,該服務提供配置、調度、資源級別的隔離(CPU、網絡、內存)、高級網絡等。
咱們的方法
考慮到上述的挑戰和設計原則,咱們幾乎完成了一個聲明式的調和架構,用以實現自助服務平臺。這個架構容許用戶經過 UI 聲明所需的做業屬性,平臺將編排和協調子服務,以確保儘快達到目標狀態。
如下部分介紹了平臺的架構和平臺設計的各個方面。
1. 聲明式調和
聲明式調和協議被用在整個架構棧上,從控制平面到數據平面。從邏輯上講,利用這個協議的目的是將用戶聲明的目標狀態的單個副本保存爲持久的事實來源,其餘服務基於這些事實來源進行調和。當出現狀態衝突時,無論是臨時故障致使仍是正常的用戶觸發動做,這些事實來源都應該被視爲權威,其餘全部版本的狀態應該被視爲當前視圖。整個系統最終須要將事實來源做爲調和目標。
事實來源存儲是一種持久的存儲,用於保存全部須要的狀態信息。咱們目前使用的是 AWS RDS,它是整個系統的惟一事實來源。例如,若是 Kafka 集羣由於 ZooKeeper 狀態損壞而出現故障,咱們能夠根據事實來源從新建立整個集羣。相同的原則也適用於流式處理層,這使得持續自我修復和自動化運營成爲可能。
這個協議的另外一個好處是操做的冪等性。這意味着從用戶傳給控制平面再傳給做業集羣的控制指令和不可避免的故障條件不會形成長時間的對立面效應。這些服務最終會自行調和,同時也帶來了運營的敏捷性。
2. 部署編排
控制平面經過與 Netflix 內部的持續部署引擎 Spinnaker 發生交互來編排做業流程。Spinnaker 對 Titus 容器運行時集成進行了抽象,控制平面能夠以不一樣的權衡方式來協調部署。
Flink 集羣由做業管理器和任務管理器組成。咱們經過爲每一個做業建立獨立的 Flink 集羣來實現完整的做業隔離。惟一的共享服務是用於達成共識協調的 ZooKeeper 和用於保存檢查點狀態的 S3 後端。
在從新部署期間,無狀態應用程序能夠在延遲或重複處理之間作出權衡。對於有狀態應用程序,用戶能夠選擇從檢查點 / 保存點恢復或重新狀態從新開始。
3. 自助工具
對於路由做業:用戶能夠經過自助服務請求生成事件(可聲明過濾器或投影聚合),而後將事件路由到託管接收器(如 Elasticsearch、Hive)或者讓下游實例進行實時的消費。自助服務 UI 從用戶那裏獲取輸入,並將其轉換爲最終指望的系統狀態。咱們所以能夠構建一個可以實現目標狀態的編排層,還能夠抽離出用戶可能不關心的某些信息(例如要發送到哪一個 Kafka 集羣或某些容器的配置),並在必要的時候提供靈活性。
對於自定義 SPaaS 做業,咱們提供了命令行工具用於生成 Flink 代碼模板存儲庫和 CI 集成等。
在用戶簽入代碼後,CI 自動化流程將開始構建 Docker 鏡像,並經過平臺後端註冊鏡像,用戶能夠執行部署和其餘操做。
4. 流式處理引擎
咱們目前正在基於 Apache Flink 爲 Keystone 的分析用例構建一個生態系統。咱們計劃集成和擴展 Mantis 流式處理引擎。
5. 鏈接器、託管 operator 和應用程序抽象
爲了幫助咱們的用戶提升開發敏捷性和創新,咱們提供了全方位的抽象,包括託管鏈接器、讓用戶能夠接入處理 DAG 的 operator,以及與各類平臺服務的集成。
咱們爲 Kafka、Elasticsearch、Hive 等提供了託管鏈接器。這些鏈接器抽象出了自定義連線格式、序列化、批處理 / 限定行爲以及接入處理 DAG 的便利性。咱們還提供動態數據源 / 接收器 operator,用戶能夠在不一樣的數據源或接收器之間切換,而無需從新構建。
其餘託管的 operator 還包括過濾器、投影聚合和易於理解的數據衛生自定義 DSL。咱們將繼續與用戶合做開發更多的 operator,並讓更多團隊可使用這些 operator。
6. 配置和不可變部署
多租戶配置管理有必定的挑戰性。咱們但願提供動態且易於管理的配置體驗(用戶無需從新提交和構建代碼)。
託管的配置和用戶定義配置都保存在應用程序的屬性文件中,這些配置能夠被環境變量覆蓋,也能夠經過自助 UI 覆蓋這些屬性。這種方法適用於咱們的調和架構,用戶經過 UI 聲明想要的配置並部署編排,確保運行時的最終一致性。
7. 自我恢復
在分佈式系統中,故障是不可避免的。咱們徹底相信故障會在任什麼時候候發生,因此咱們的系統被設計成具備自我恢復能力,這樣就沒必要在半夜醒來處理事故。
從架構上看,平臺組件服務被隔離出來,以便在發生故障時減小影響範圍。調和架構還經過持續調和來確保系統級別的自我恢復能力。
單個做業遵循相同的隔離模式,以減小故障影響。可是,爲了處理故障並從故障中恢復,每一個託管流式做業都配有健康監視器。健康監視器是運行在 Flink 集羣中的內部組件,負責檢測故障狀況並執行自我修復:
集羣任務管理器漂移:當 Flink 容器資源視圖與容器運行時視圖不匹配時就會出現漂移,經過主動終止受影響的容器,能夠自動糾正漂移。
暫停做業管理器首領:若是未能選舉出首領,集羣就會進入無腦狀態,此時須要對做業管理器執行糾正措施。
不穩定的容器資源:若是某個任務管理器出現不穩定的模式(如按期重啓 / 故障),它將被替換。
網絡分區:若是容器遇到網絡鏈接問題,它將自動終止。
8. 回填和回放
由於故障是不可避免的,因此有時候用戶可能須要回填或回放處理做業。
對於備份到數據倉庫中的源數據,咱們在平臺中構建了相應的功能,用來動態切換數據源而無需修改和從新構建代碼。這種方法有必定的侷限性,建議將它應用在無狀態做業上。
或者,用戶能夠選擇回到以前自動保存的檢查點開始從新處理。
9. 監控和警報
全部單個的流式做業都配有個性化的監控和警報儀表盤。這有助於平臺 / 基礎設施團隊和應用程序團隊監控和診斷問題。
10. 可靠性和測試
隨着平臺和底層基礎設施服務不斷創新,提供愈來愈多的新功能和改進,快速採用這些變化的壓力是自下而上的(架構層面)。
隨着應用程序的開發和發佈,可靠性的壓力是自上而下的。
因而,壓力在中間相遇了。爲了得到信任,咱們須要讓平臺和用戶可以有效地測試整個技術棧。
咱們堅持爲全部用戶進行單元測試、集成測試、金絲雀運營。咱們正在這方面取得進展,但仍然有不少問題須要解決。
如今和將來
在過去的一年半中,Keystone 流式處理平臺天天能夠處理萬億個事件。咱們的合做夥伴團隊已經用它構建各類流式分析應用。此外,咱們也看到了一些創建在 Keystone 之上的更高級別的平臺。
可是,咱們的故事並未就此結束。要實現咱們的平臺願景,還有很長的路要走。如下是咱們正在研究的一些有趣的事項:
模式(schema)
讓平臺交互變得更靈活的服務層
提供流式 SQL 和其餘更高級別的抽象,爲不一樣的用戶提供價值
分析和機器學習用例
微服務事件溯源架構模式