天天看點

Dapr 在阿裡雲原生的實踐

作者|曹勝利

什麼是Service Mesh?

從 2010 年的時候,SOA 架構就已經在中大型網際網路公司中開始流行,阿裡也在2012 年開源了 Dubbo 。而之後微服務架構開始流行,大量網際網路和傳統企業都投身到微服務的建設中。在國内逐漸形成了Dubbo 和 Spring Cloud 兩大微服務陣營。在2016 年的時候,微服務領域一個更具有前沿性,更加符合容器和 Kubernetes 的微服務方案正在孕育,這個技術被稱為 Service Mesh。時至今日,Service Mesh 理念已經得到了大範圍普及,很多公司都在 Service Mesh 領域有了落地。

Service Mesh 定義

Service Mesh 是一個基礎設施層,主要圍繞服務間通信來進行。現在的雲原生應用的服務拓撲結構非常複雜,Service Mesh 可以在這種複雜拓撲結構中實作可靠的請求傳送。Service Mesh 是以 Sidecar 的方式運作,應用旁邊會運作一個獨立的 Service Mesh 程序,Service Mesh 負責遠端服務的通信。軍用三輪機車和 Service Mesh 非常相像,軍用三輪機車上一個士兵負責開車,一個士兵負責對人發起射擊。

Service Mesh 解決的痛點

Dapr 在阿裡雲原生的實踐

傳統的微服務架構大都以 RPC 通信架構為基礎,在 RPC SDK 中提供了服務注冊/發現,服務路由,負載均衡,全鍊路跟蹤等能力。應用業務邏輯和 RPC SDK 在同一個程序中,這種方式給傳統微服務架構帶了很多挑戰:中間件能力相關代碼侵入到了業務代碼中,耦合性很高;推動 RPC SDK 的更新成本非常高,進而也導緻了 SDK 版本分化非常嚴重。同時這種方式對應用開發者的要求比較高,需要有豐富的服務治理的運維能力,有中間件的背景知識,使用中間件的門檻偏高。

通過 Service Mesh 方式将一些 RPC 的能力進行下沉,這樣可以很好的實作關注點分離、職責邊界的明确。随着容器和 Kubernetes 技術的發展,Service Mesh 已經成為雲原生的基礎設施。

Istio 介紹

Dapr 在阿裡雲原生的實踐

在 Service Mesh 領域中, Istio 毫無疑問是當中的王者。Istio 由控制面和資料面構成,在 ServiceMesh 中,不同的 Service 之間,通過 Proxy Sidecar 進行通信。Istio 最核心功能是流量管理,通過資料面和控制面協調完成。Istio 是由 Google 聯合IBM,Lyft 一起發起的,是 CNCF 生态版圖 Service Mesh 領域的最純正血統,有望成為Service Mesh事實标準。

Istio 的資料面預設使用 Envoy,Envoy 是社群裡預設的最佳資料面。Istio 資料面和控制面的互動協定是 xDS。

Service Mesh 小結

最後,對 Service Mesh 做下小結:

  • Service Mesh 定位就是提供服務間通信的基礎設施,社群裡主要支援 RPC 和http 。
  • 采用 Sidecar 方式部署,支援部署在 Kubernetes 和虛拟機之上。
  • Service Mesh 采用原協定轉發,是以 Service Mesh 也被稱為網絡代理。正是由于這種方式方式,是以可以做到對應用的零侵入。

什麼是Dapr?

Service Mesh 遇到的挑戰

Dapr 在阿裡雲原生的實踐

使用者在雲上部署業務的形态主要有普通應用類型和FaaS類型。Faas 場景下,比較吸引使用者的是成本和研發效率,成本主要通過按需配置設定和極緻的彈性效率來達成。而應用開發者期望通過 FaaS 提供多語言的程式設計環境,提升研發效率,包括啟動時間、釋出時間、開發的效率。

Service Mesh 的實作,本質是原協定轉發,原協定轉發可以給應用帶來零侵入的優勢。但是原協定轉發也帶來了一些問題,應用側中間件SDK還需要去實作序列化和編解碼工作,是以在多語言實作方面還有一定成本;随着開源技術的不斷發展,使用的技術也在不斷疊代,如果想從 Spring Cloud 遷移到 Dubbo ,要麼應用開發者需要切換依賴的 SDK,如果想借助Service Mesh來達到這個效果,Service Mesh 需要進行協定轉換,成本較高。

Service Mesh 更加聚焦于服務間的通訊,而對其他形态的 Mesh 的支援上非常少。比如 Envoy, 除了在 RPC 領域比較成功外,在 Redis、消息等領域的嘗試都未見成效。螞蟻的 Mosn 中支援了 RPC 和消息的內建。整體多 Mesh 形态的需求是存在的,但是各個 Mesh 産品各自發展,缺少抽象和标準。如此多形态的 Mesh ,是共用一個程序嗎?如果是共用一個程序,那麼是共用一個端口嗎?許多問題都沒有答案。而控制面方面,從功能角度來看的話,大都圍繞流量來展開。看過 xDS 協定裡的内容,核心是圍繞發現服務和路由來展開。其他類型的分布式能力,在 Service Mesh的控制面中基本沒有涉及,更談不上抽象各種類似 xDS 的協定去支援這些分布式能力。

因為成本和研發效率等原因,FaaS 受到了越來越多客戶的選擇,FaaS 對多語言和程式設計 API 的友好性上有了更多訴求,那麼 Service Mesh 在這兩塊還是不能給客戶帶來額外的的價值。

分布式應用的需求

Dapr 在阿裡雲原生的實踐

Bilgin Ibryam 是 Kubernetes Patterns 的作者,是 RedHat 的首席中間件架構師,在 Apache 社群裡非常活躍。他發表了一篇文章對目前分布式的一些困難和問題進行了抽象,将分布式應用需求分成了 4 個大種類:生命周期、網絡、狀态、綁定。每種類型下面還有一些子能力,如 Point-to-Point, pub/sub, Caching 等比較經典的中間件能力。應用對分布式能力有如此多的需求,而 Service Mesh 顯然不能滿足應用的目前的需求。Biligin Ibryam 還在文章中提出了 Multiple Runtime 的理念來解決Service Mesh 的困境。

Multiple Runtime 理念推導

Dapr 在阿裡雲原生的實踐

在傳統的中間件模式下,應用和分布式能力是在一個程序中,以 SDK 方式進行內建。随着各種基礎設施下沉,各種分布式能力從應用中移到了應用外。如 K8s 負責了生命周期相關的需求,Istio、Knative 等都負責一些分布式能力。如果将這些能力都移動到獨立的 Runtime 中,那麼這種情況無論從運維層面還是資源層面來看,都是沒辦法接受的。是以這時候肯定需要将部分 Runtime 進行整合,最理想的方式肯定是整合成一個。這種方式被定義成 Mecha ,中文意思是機甲的意思,就像日本動漫裡主人公變身穿上機甲,機甲的每個部件就像一個分布式能力,機甲裡的人對應的是主應用,也叫 Micrologic Runtime 。 這兩個 Runtime 可以是一對一的 Sidecar 方式,這種非常适合傳統的應用;也可以是多對一的 Node 模式,适合邊緣場景或者網管模式下。

那麼對于将各種分布式能力進行整合的 Mecha Runtime 這一目标本身問題不大,那麼怎麼整合呢?對 Mecha 有什麼要求呢?

  1. Mecha 的元件能力是抽象的,任何一個開源産品可以快速進行擴充和內建。
  2. Mecha 需要有一定的可配置能力,可以通過 yaml/json 進行配置和激活。這些檔案格式最好能和主流的雲原生方式對齊。
  3. Mecha 提供标準的 API ,和主應用之間的互動的網絡通信基于此 API 來完成,不再是原協定轉發,這樣對于元件擴充和 SDK 的維護都能帶來極大的便利性。
  4. 分布式能力中的生命周期,可以将部分能力交接過底層的基礎設施,比如 K8s。當然有些複雜的場景,可能需要 K8s、APP、Mecha Runtime 一起來完成。

既然最理想隻剩下一個 Runtime , 那麼為什麼還叫 Multiple Runtime 呢?因為應用本身其實也是一個 Runtime ,再加上 Mecha Runtime ,是以至少是兩個 Runtime 。

Dapr 介紹

前面的 Multiple Runtime 介紹地比較抽象,可以來從 Dapr 來重新了解下 Multiple Runtime 。Dapr 是 Multiple Runtime 的一個很好的踐行者,是以 Dapr 肯定和應用共存的,要麼是 Sidecar 模式,要麼是 Node 模式。Dapr 這個詞其實是不是造出來的,而是 Distributed Application Runtime 的首字母拼接而成,Dapr 這個圖示可以看出來是一個帽子,這個帽子其實是一個服務生的帽子,表示的含義是要為應用做好服務。

Dapr 是由微軟開源的,阿裡巴巴深度參與合作。目前的 Dapr 已經釋出 1.1 版本,現在已經接近生産的能力。

Dapr 在阿裡雲原生的實踐

既然 Dapr 是 Multiple 的最佳實踐者,那麼 Dapr 的運作機制也是基于 Mulitple Runtime 的理念來建構的。Dapr 對分布式能力進行了抽象,定義了一套分布式能力的 API,而且這些 API 是基于 Http 和 gRPC 來建構的,這種抽象和能力在 Dapr 中被稱為 Building Block;Dapr 為了支援開源産品和商業化等不同類型的産品對 Dapr中的分布式能力進行擴充,内部擁有一套 SPI 擴充機制,這種 SPI 機制叫 Components 。應用開發者在使用 Dapr 之後,隻需要針對各種分布式能力的 API 來進行程式設計,而無需過多關注具體的實作,而 Dapr 中根據 Yaml 檔案可以自由激活對應的元件。

Dapr 特性

Dapr 在阿裡雲原生的實踐

應用開發者使用各種多語言的 Dapr SDK 就可以直接擁有各種分布式能力。當然開發者也可以自己基于 HTTP 和 gRPC 來完成調用。Dapr 可以運作在大部分環境裡,包括你自己電腦的環境,或者任何 Kubernetes 環境下,或者邊緣計算場景,或者阿裡雲、AWS、GCP 等雲廠商。

Dapr 社群裡已經內建了 70+ 的 components 實作,應用開發者可以快速進行選擇和使用。相似能力的元件的替換,可以通過 Dapr 裡完成,應用側可以做到無感覺。

Dapr 核心子產品

Dapr 在阿裡雲原生的實踐

我們從 Dapr 産品子產品緯度來解析下,看為什麼 Dapr 是 Mulitiple Runtime 的一個很好實踐。

Component 機制確定了可以快速擴充能力的實作,現在社群已經有的 Components實作已經有 70 個以上,不隻包含開源産品,還包含雲上的商業化産品。

Building Block 表示的的分布式能力,現在隻支援 7 個,後續需要更多的分布式能力能夠進來。BuildingBlock 現在支援了 HTTP 和 gRPC 這兩種開放,而且普及度已經非常高的協定。而 Dapr 中 Building Block 下具體那些 Components 會被激活,需要依賴 YAML 檔案來進行。正因為 Dapr 中采用了 HTTP、gRPC 的方式暴露能力,是以在應用側想要支援多語言的标準的API程式設計界面就變得更為容易了。

Dapr 核心:Component & Building Block

Dapr Component 是 Dapr 插件擴充的核心,是 Dapr 的 SPI 。現在支援的 Components 有 Bindings 、Pub/Sub、Middleware、ServiceDiscovery、Secret Stores、State。擴充點裡有些是功能緯度的如Bindings,pub/sub,state 等,有些是橫向的如 Middleware。假設你想實作Redis的Dapr內建,你隻需要去實作 Dapr 的State Component。Dapr Building Block是Dapr提供出來的能力,支援 gRPC 和 HTTP 方式。現在支援的能力有 Service Invocation,State,Pub/Sub 等。

Dapr 在阿裡雲原生的實踐

一個 Building Block 由 1 個或多個 Component 組成,Binding的Building Block 包含 Bindings 和 Middleware 兩個 Component 。

Dapr 整體架構

Dapr 在阿裡雲原生的實踐

Dapr 和 Istio 一樣,也有資料面和控制面。控制面有 Actor Placement,Sidecar Injector, Sentry, OPerator。Actor Placement 主要為 Actor 服務,Sentry 做安全和證書相關的工作,Sidecar Injector 主要負責 Dapr Sidecar 的注入。Dapr 裡激活某個元件實作是通過 YAML 檔案來完成的,YAML 檔案可以通過兩種方式來指定:一種是本地指定運作時參數,另外一種是通過控制平面 Operator 來完成,将元件激活的檔案以 K8s CRD 方式存儲并下發到 Dapr的Sidecar 中。控制面的 2 個核心元件都依賴于 K8s 來運作。現在的 Dapr Dashboard 功能還很弱,短期還不到增強的方向,現在各個元件的內建之後,各個元件的運維還需要在原來的控制台裡完成,Dapr 控制平面不參與具體元件實作的運維。

Dapr 标準運作形式是和應用在同一個 Pod 中,但分屬于兩個容器。Dapr 的其他内容,前面已經做了足夠的介紹,這裡不做介紹了。

Dapr 微軟落地場景

Dapr 經曆了 2 年左右的發展,在微軟内部的落地情況是怎麼樣的呢?

Dapr 在阿裡雲原生的實踐

Dapr 的 github 上有兩個項目:workflows 和 Azure Functions Dapr extensions。Azure Logic App 是微軟的一個基于雲上的自動工作流平台。而 Workflows,就是整合了 Azure Logic App 和 Dapr。Azure Logic App 中有幾個關鍵的概念,Trigger 和 Connector 和 Dapr 非常契合。Trigger 可以使用 Dapr 的 Input Binding 來完成,依賴 Dapr 的 Input Binding 的大量元件實作,可以擴大流量入口的類型。而 Connector 和 Dapr 的 Output Binding 或者 Service Invocation 的能力非常比對,可以快速通路外部資源。Azure Functions Dapr extensions 則是基于Azure Function extension 做的 Dapr 支援,可以讓 Azure Function 快速使用上Dapr 的各種 Building Block 的能力,同時能給函數開發者帶來多語言的相對簡單一緻的程式設計體驗。

Dapr 在阿裡雲原生的實踐

Azure API Management Service和上面提到的兩個落地場景的角度不太一緻,它是前提是應用之間已經通過Dapr Sidecar方式進行通路,應用的提供的服務通過Dapr來進行暴露。這時候如果非K8s的應用或者跨叢集的應用想要通路目前叢集的服務,就需要一個網關,這個網關可以直接暴露Dapr的能力,在網關中會增加一些安全和權限的控制。目前支援3種Building Block:Service Invocation、pub/sub、resource Bindings。

Dapr 小結

Dapr 提供的面向能力的 API ,能夠給開發者帶來支援多語言的一緻的程式設計體驗,同時這些 API 的SDK相對比較輕量級。這些特性非常适合 FaaS 場景。而随着 Dapr 內建生态的不斷完善,開發者面向能力程式設計的優勢将進一步擴大,通過 Dapr 可以更加友善地将 Dapr 元件的實作進行替換,而無需開發者做代碼的調整。當然原來的元件和新的元件實作,必須是相同類型的分布式能力。

和 Service Mesh 差異點:

提供能力:Service Mesh 專注服務調用;Dapr 提供的分布式能力範圍更廣,覆寫多種分布式原語。

工作原理:Service Mesh 采用原協定轉發做到零侵入;Dapr 采用多語言SDK + 标準API + 各種分布式能力。

面向領域:Service Mesh 對傳統微服務的無侵入更新支援很友好;Dapr 對面向應用的開發者提供了更加友好的程式設計體驗。

阿裡在 Dapr 上的探索

阿裡在 Dapr 的發展路線

2019 年 10 月,微軟開源了 Dapr,釋出了 0.1.0 的版本。這時候,阿裡和微軟正好因為 OAM 已經展開一些合作,了解到了 Dapr 這個項目,是以就開始對其進行評估。在 2020 年初的時候,阿裡和微軟在阿裡巴巴線下做了一輪 Dapr 的溝通,了解到了微軟對 Dapr 的看法、投入,以及後續的發展計劃。此時阿裡已經認定 Dapr 這個項目具有較大的價值。一直到 2020 年中,才開始圍繞 Dapr 開始投入工作。到 10 月份,Dapr 在函數計算場景下開始線上灰階部分功能,到今天為止,函數計算相關的 Dapr 的所有功能的灰階已經基本完成,開始開放公測。到 2021 年 2 月份,終于釋出了 1.0 版本。

阿裡雲函數計算內建 Dapr

除了極緻彈性等運維側的好處之外,函數計算差別于中台應用的地方還在于,函數計算更加關注能夠給開發者帶來更好的研發體驗,提升整體的研發效率。而 Dapr 能夠給函數計算的價值就是提供多語言的統一的面向能力的程式設計界面,而開發者無需關注具體的産品。像 Java 語言如果要使用阿裡雲上的 OSS 服務,需要引入 maven 依賴,同時需要寫一些 OSS 代碼,而通過 Dapr 你隻需要調用 Dapr SDK 的 Binding 方法即可以做到,友善程式設計的同時,整個可運作包也無需引入多餘的依賴包,而是可控的。

Dapr 在阿裡雲原生的實踐
Dapr 在阿裡雲原生的實踐

函數計算英文名是 Function Compute,簡稱為 FC。FC 的架構包含的系統比較多,和開發者相關的主要包括 Function Compute Gateway和函數運作的環境。FC Gateway主要負責承接流量,同時會根據承接的流量的大小,目前的 CPU、記憶體使用情況,對目前函數執行個體進行擴縮容。函數計算運作時環境部署在一個 Pod 中,函數執行個體在主容器中,dapr 則是在 sidecar 容器中。當有外部流量通路函數計算的服務時,流量會先走到 Gateway ,Gateway 會根據通路的内容将流量轉發到提供目前服務的函數執行個體中,函數執行個體接收到請求之後如果需要通路外部資源,就可以通過Dapr 的多語言 SDK 來發起調用。這時候 SDK 會向 Dapr執行個體發起gRPC請求,而在dapr 執行個體中回根據請求的類型和 body 體,選擇對應的能力群組件實作,進而向外部資源發起調用。

Dapr 在阿裡雲原生的實踐

在 Service Mesh 場景下,Mesh 以 Sidecar 形式存在,和應用部署在同一個 Pod 的兩個容器裡,可以很好滿足 Service Mesh 的需求。但是在函數計算場景下,Dapr作為獨立容器方式運作過于消耗資源,而且多個函數執行個體本身部署在一個 Pod 中以便節省資源開支和秒級彈性。是以在函數計算場景下,需要将函數執行個體和Dapr程序部署在同一個容器下,但是以兩個程序方式存在。

函數計算場景下,可以設定預留執行個體數,表示目前函數最小執行個體數。如果有預留的執行個體,但是這些執行個體長久沒有流量通路需要進入暫停/休眠狀态,這種方式和 AWS 的方式是一緻的。進入休眠狀态的函數,執行個體内的程序或者線程需要停止運作。函數運作時中增加了 Extension 結構,來支援 Dapr 生命周期的排程。當函數執行個體進入休眠狀态時,extension 通知 Dapr 進入休眠狀态;當函數執行個體恢複運作之後,extension 通知 Dapr 重新恢複之前運作的狀态。Dapr 内部的元件實作需要能支援這種方式的生命周期管理,以 Dubbo 為例,Dubbo 的注冊中心 nacos 需要定時往 Nacos server 發送心跳保持了解,同時 Dapr 內建的Dubbo Consumer也需要往Dubbo Provider 發送心跳。當進入暫态之後,心跳都需要退出;當恢複運作之後,整個運作狀态需要恢複。

上面講到的函數計算和 Dapr 結合的點,都是基于對外的流量,那麼流入的流量呢?消息的流量是否可以直接流入到 Dapr ,而無需經過 Gateway 呢?要做到這一點,還需要在 Dapr Sidecar 将一些性能資料及時上報給 Gateway ,友善 Gateway 可以做到資源的彈性。

SasS 業務上雲

随着阿裡内部孵化的SaaS業務越來越多,SaaS業務對外服務的訴求非常強烈。而SaaS業務對多雲部署的訴求非常強烈,客戶期望SaaS業務能部署在阿裡雲公有雲或者華為專有雲上。而且客戶期望底層依賴的技術是開源的或者标準的雲廠商的商業化産品。

Dapr 在阿裡雲原生的實踐

以阿裡一個SaaS業務上雲來說明,左側是阿裡内部原來的系統,右側是改造之後的系統,改造的目标是将依賴的阿裡内部的系統切換成開源軟體,Ali RPC切換到Dubbo,而阿裡内部的Cache,Message,Config分别切換到Redis、RocketMq和Nacos。期望通過Dapr來實作最小代價的切換。

既然想用Dapr來完成這個使命,那麼最簡單粗暴的方法肯定是讓應用依賴Dapr的SDK,但是這種方式改造成本太高,是以我們在保持原來API不變的情況下,将底層實作适配到Dapr SDK。通過這種方式,應用就可以直接使用原來的API通路Dapr,隻需要更新對應的依賴JAR包版本。改造之後,開發者還是面向原來的SDK進行程式設計,但是底層已經被替換成了Dapr的面向能力程式設計,是以在遷移過程中,應用可以使用一套代碼,而無需為每個雲環境或者不同技術維護不同的分支。集團内部用Dapr Sidecar的時候,會使用rpc.yaml、cache.yaml、msg.yaml、config.yaml來激活元件實作,而在公有雲上回通過dubbo.yaml、redis.yaml、rocketmq.yaml、nacos.yaml檔案來激活适合阿裡雲環境的元件實作。這種通過不同yaml檔案激活不同元件來屏蔽元件實作的方式給SaaS業務多雲部署形态帶來了極大的便利。

Dapr 在阿裡雲原生的實踐

釘釘是Dapr的重要合作夥伴和推動者,和雲原生團隊合作推進Dapr在釘釘落地。通過将一些中間件能力下沉到Dapr Sidecar之後,屏蔽了底層相似能力的中間件實作。但是釘釘還有自己的業務痛點,釘釘通用的業務元件是強業務綁定,需要具體的業務進行一些定制,這樣同時導緻了複用度很低,是以釘釘期望通過将部分業務元件能力下沉到Dapr。這樣可以讓不同業務有相同的程式設計體驗,而元件維護者隻需要維護好Components實作。

Dapr展望

基礎設施下沉成為軟體發展趨勢

軟體架構的發展曆史及其精彩。回顧阿裡巴巴系統架構演進的曆史,能讓人了解國内甚至全球的軟體架構的發展曆史。淘寶最開始成立的時候,是單體應用;随着業務規模的發展,系統首先對硬體進行更新這種Scale Up的方式;但是很快發現這種方式遇到了各種各樣的問題,是以在2008年開始引入了微服務的解決方案;SOA的解決方案是分布式的,對于穩定性,可觀測性等方面,需要引入熔斷、隔離、全鍊路監控等高可用方案;接下來面臨的問題是怎麼在機房、IDC層面來讓業務達到99.99%以上可用的SLA,這時候就有了同城雙機房、異地多活等解決方案。而随着雲技術的不斷發展,阿裡巴巴擁抱和引導雲原生技術的發展,積極擁抱雲原生技術,以K8s為基礎,積極開展雲原生技術的更新。

Dapr 在阿裡雲原生的實踐

從這個曆史中,我們可以發現,軟體架構新的訴求越來越多,原先底層基礎設施無法完成隻能交給應用側富SDK去完成,在K8s和容器逐漸成為标準之後,重新将微服務和一些分布式能力還給基礎設施。未來的趨勢是以Service Mesh和Dapr為代表的分布式能力下沉,釋放雲和雲原生技術發展的紅利。

雲原生場景下的應用開發者的訴求

未來的應用開發者,應該期望能夠面向能力,無言無關,不和具體雲廠商和技術綁定的開發體驗,同時通過雲技術的紅利能夠做到極緻的彈性帶來的成本優勢。我相信這個理想還是有可能實作的一天的,從目前的角度出發,怎麼樣才能完成這個目标呢?

  1. Multiple Runtime理念能夠真正落地,并且能夠持續發展;
  2. 以Dapr為例,期望能将Dapr面向分布式能力的API推動成為一個行業标準,并且這個标準是需要持續發展的;
  3. K8s和Serverless技術的持續發展,未來可以将彈性做到極緻。

Dapr 社群方向

最後來看下Dapr的社群發展:

1.推動 API 标準化,內建更多分布式能力;

2.更多Component內建,Dapr 生态完善;

3.更多公司落地,拓展産品邊界和打磨 Dapr 産品, 達到生産可用;

4.進入 CNCF, 成員雲原生的 Multiple Runtime 的事實标準。

點選

https://developer.aliyun.com/community/cloudnative

,了解更多雲原生内容