1. 程式人生 > 其它 >Dapr 在阿里雲原生的實踐

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


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

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

Istio 介紹


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


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

分散式應用的需求


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

Multiple Runtime 理念推導


在傳統的中介軟體模式下,應用和分散式能力是在一個程序中,以 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 是 Multiple 的最佳實踐者,那麼 Dapr 的執行機制也是基於 Mulitple Runtime 的理念來構建的。Dapr 對分散式能力進行了抽象,定義了一套分散式能力的 API,而且這些 API 是基於 Http 和 gRPC 來構建的,這種抽象和能力在 Dapr 中被稱為 Building Block;Dapr 為了支援開源產品和商業化等不同型別的產品對 Dapr中的分散式能力進行擴充套件,內部擁有一套 SPI 擴充套件機制,這種 SPI 機制叫 Components 。應用開發者在使用 Dapr 之後,只需要針對各種分散式能力的 API 來進行程式設計,而無需過多關注具體的實現,而 Dapr 中根據 Yaml 檔案可以自由啟用對應的元件。

Dapr 特性

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

Dapr 社群裡已經集成了 70+ 的 components 實現,應用開發者可以快速進行選擇和使用。相似能力的元件的替換,可以通過 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 等。

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

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

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


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


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

以阿里一個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 Sidecar之後,遮蔽了底層相似能力的中介軟體實現。但是釘釘還有自己的業務痛點,釘釘通用的業務元件是強業務繫結,需要具體的業務進行一些定製,這樣同時導致了複用度很低,所以釘釘期望通過將部分業務元件能力下沉到Dapr。這樣可以讓不同業務有相同的程式設計體驗,而元件維護者只需要維護好Components實現。

Dapr展望

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

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

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

原文連結

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