Dapr 在阿里雲原生的實踐


簡介: Faas 場景下,比較吸引用戶的是成本和研發效率,成本主要通過按需分配和極致的彈性效率來達成。而應用開發者期望通過 FaaS 提供多語言的編程環境,提升研發效率,包括啟動時間、發布時間、開發的效率。​

作者|曹勝利

什么是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 解決的痛點

1.png

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

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

Istio 介紹

2.png

在 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 遇到的挑戰

3.png

用戶在雲上部署業務的形態主要有普通應用類型和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 在這兩塊還是不能給客戶帶來額外的的價值。

分布式應用的需求

4.png

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

Multiple Runtime 理念推導

5.png

在傳統的中間件模式下,應用和分布式能力是在一個進程中,以 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 版本,現在已經接近生產的能力。

6.png

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

Dapr 特性

7.png

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

Dapr 社區里已經集成了 70+ 的 components 實現,應用開發者可以快速進行選擇和使用。相似能力的組件的替換,可以通過 Dapr 里完成,應用側可以做到無感知。

Dapr 核心模塊

8.png

我們從 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 等。

9.png

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

Dapr 整體架構

10.png

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 年左右的發展,在微軟內部的落地情況是怎么樣的呢?

11.png

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 的能力,同時能給函數開發者帶來多語言的相對簡單一致的編程體驗。

12.png

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 方法即可以做到,方便編程的同時,整個可運行包也無需引入多余的依賴包,而是可控的。

14.png
image.png

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

15.png

在 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業務能部署在阿里雲公有雲或者華為專有雲上。而且客戶期望底層依賴的技術是開源的或者標准的雲廠商的商業化產品。
16.png

以阿里一個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業務多雲部署形態帶來了極大的便利。

17.png

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

Dapr展望

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

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

18.png

從這個歷史中,我們可以發現,軟件架構新的訴求越來越多,原先底層基礎設施無法完成只能交給應用側富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 的事實標准。

原文鏈接

本文為阿里雲原創內容,未經允許不得轉載。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM