摘要 Dapr 的設計與概念


前面兩篇先從體驗 Dapr 開始,從 Self-Hosted 到實際 Run on K8s 的體驗,大概了解的 Dapr 實際上怎麼用。Dapr 背後實際上把 分散式系統概念微服務架構實踐的挑戰 、以及 K8s 圍繞這三個主題做了全面性的考慮與設計,特別是 Kubernetes Patterns 一書的作者 Bilgin Ibryam 提出 Multi-Runtime Microservices Architecture 的概念之後,加上 Dapr 這樣的分散式應用框架的出現,我感覺到下一個世代的來臨。

Bilgin IbryamThe Evolution of Distributed Systems on KubernetesMulti-Runtime Microservices Architecture (簡中翻譯),還有 Kubernetes Patterns 這些資料很直得一讀。

本文整理在 Study Dapr 過程中,整理背後設計的思路與概念。


摘要 Dapr 的設計與概念

Dapr 設計的考量幾乎與前述 Multi-Runtime 幾乎不謀而合,其中我整理幾個非常核心的設計想法:

  1. Sidecar
  2. Building Block & Component
  3. Service Invocation
  4. Middleware
  5. State

基於上述這些核心設計,讓 Dapr 有了 Multi-Runtime Architecture 的特性,以此延伸出底下的重要功能,或者說設計模式:

  1. Security
  2. Observability: tracing, metrics, logs and health
  3. Pub / Sub / Batch Process
  4. Actors
  5. Secret Management

Sidecar

下圖是 Sidecar 與 Microservice 之間搭配後,多個服務的關係圖,這樣的結構形成了 Service Mesh 的概念。在 Dapr 裡, Sidecar 由 Dapr 透過配置的方式,動態產生,隨後伴隨著 App,一組 Dapr Sidecar + App 的組合稱為 Dapr App

圖源:Dapr at 20,000 feet
圖源:Dapr at 20,000 feet

把鏡頭拉近一點,Dapr App 的概念透在 K8s 實踐就是這樣:

Pod = (App_Container + Sidecar_Container)

如下圖:

圖源:Dapr at 20,000 feet
圖源:Dapr at 20,000 feet

同樣的概念,如果不是跑在 K8s,也就是 Self-Hosted 的概念,如下圖:

圖源:Dapr at 20,000 feet
圖源:Dapr at 20,000 feet

每個 Dapr App 都透過 Sidecar 溝通,在通訊之前,Dapr App 要知道的是對方在哪?所以 Service invocation and Service discovery 是 Dapr App 要處理的第一個議題。知道彼此在哪,然後是通訊模式,Dapr 通訊模式支援 HTTP / gRPC 兩種。預設 Dapr App 之間的通訊使用 gRPC,也就是如果使用 HTTP 呼叫 Dapr API,之後內部服務之間的通訊也會轉成 gRPC。

Dapr Sidecar 有了 Service Invocation, Service Discovery, Communitation 之後, 定義了 Building Block 的概念,允許使用宣告式的方式,定義多個 Component 擴充 Sidecar 的功能,這些功能處理大部分分散式架構需要面對的問題。

而 Sidecar 模式有它的好處,當然也會衍生出問題,像是如何管理這些 Sidecar 的狀態?他們如何找到彼此?怎麼 Debug ?效能議題?安全性 … etc.

Building block and Components

Buiding Block 是每個 Dapr Sidecar 可以擴充的概念,每個 Block 由數個 Components 組成,開發者可以自行設計、擴充 Component,貢獻給社群。

下圖是微軟基於 Dapr 實作的應用範例:eShop (Source),圖中每個標示 dapr 的區塊都是一個 Dapr App,而圖中綠色標記數字的區塊就是 Component。圖中標記了六種 Component:


圖源:Dapr reference application

基於這樣的設計,Dapr 把最核心的 Component 提供基於分散式系統的 最佳實踐 (Best Practice)設計模式 (Design Patterns),提供了以下的核心實作分類:

  1. Input/Output Bindings:
    • 全部列表:Supported external bindings
    • 著名實作:APN (Apple Push Notification), HTTP, InfluxDB, K8s Event, Kafka, MQTT, MySQL, PgSQL, Redis, RabbitMQ, SMTP, AWS DnyamoDB, S3, SNS, SQS ..
  2. Pub / Sub:
    • 全部列表:Supported pub/sub brokers
    • 著名實作:Hazelcast, Redis Streams, NATS, Kafka, Azure Service Bus, RabbitMQ, Azure Event Hubs, GCP Pub/Sub, MQTT
  3. Middleware: Dapr 的特殊 Components,後述。
  4. Service discovery name resolution: Dapr 的特殊 Components,後述。
  5. State Stores
    • 全部列表:Supported state stores
    • 著名實作:Hazelcast, Memcached, MongoDB, MySQL, PgSQL, Redis, AWS DynamoDB
  6. Secret Stores
    • 全部列表:Supported secret stores
    • 著名實作:AWS SSM Parameter Store, Secret Management, Local, HashiCorp Vault, K8s Secret

這些 核心 的設計,可以從原始碼中了解背後運作的,下圖是原始碼的位置:


原始檔位置:dapr/pkg/components

GitHub: components-contrib 是 Dapr 官方開放的 Component ,開發者可以透過 PR 提交擴充的 Component 貢獻給社群,目前已經有 70 個 Components 可以使用,不過要注意版本的階段性是在 Alpha / Beta / GA 自行做風險評估。

Service Invocation and Service Discovery

這幾年我一直在做一件事情:服務治理 (Service Governance),也就是在龐大的系統架構中,如何有效地治理這些服務。服務治理就像是管理一個國家的行政區,要先有明確的邊界劃分、省縣級別、名稱、關係、通訊模式、各自的業務範圍、成本、資安、可靠、維運 … 等議題。

網路治理 最基本的技術方案就是 IP + DNS

那服務治理的基本技術方案是什麼?就是 Service Catalog / Service Discovery ,讓兩個服務溝通的機制則稱為 Service Invocation。Dapr 作為一個分散式應用框架,多個 Dapr App 怎麼麽知道彼此的存在、透過什麼方式溝通?這就是服務治理要做的事情。

除了網路治理,2000 年的 SOA 架構也是有類似的概念。

Dapr 的 Service Discovery 機制,依照架構的方式 (Self-Hosted, K8s) 有不同的實作,概念如下圖:

摘錄一些設計概念:

  • Dapr 命名有 Namespace 概念,基本格式為 FQDN
  • Dapr 的 Service Invocation 則支援 gRPC / HTTP 兩種方式,預設 Service to Service 使用 gRPC 通訊。
  • Service to Service 使用 mTLS 做傳輸層加密 (in-transit)
  • 支援 Service 的 ACL,可以個別控制每個 API 與 Method 的操作
  • 支援 Retry 機制
  • 可以使用其他 service discovery 實作
  • RR load balancing with mDNS
  • 支援 tracing and metric

官方這張圖,解釋了 Service Invocation 整個過程會經過的事情:


圖源:Service invocation overview

Middleware

如同一般程式語言支援透過 middleware 處理 HTTP request / response 完成一些 Cross-Cutting (AoP) 的功能,Dapr 也支援 Middleware 的概念,如下圖:

摘要一些特性:


Q and A

Q: Dapr is not a service mesh

Dapr 整個架構倚賴 Sidecar Pattern,Study 過程,腦袋聲音一直出來。我整理了過去對於相關技術的學習脈絡:

2017 年誕生的 Service Mesh,當時曾經關注一陣子,直到後來 Envory、Istio 等框架出現後,發現這概念很重要,但是要真的落地到現場難度很高,工作上一直也都沒用到。倒是 API Gateway 廣泛應用。

Dapr 本身不處理 Service Mesh 的事情,定位真的就是 App 的 Sidecar,下圖是 Dapr community call 31 的介紹,直接與 Istio 整合的概念:

Dapr + Istio
圖源:Dapr community call 31 - 2/9/2021

整理這篇文章的時候, Dapr v1.1.0 Release 了,官網的 Concepts 直接解釋 Dapr 與 Service Meshes 的範圍,如下圖。Dapr 處理的是藍底色的,而 Service Meshes 則是灰底色的:

Dapr + Istio


結語

分散式架構大概都要面對一些複雜的基礎架構議題,底下是我常思考要解決的問題:

  1. 服務治理:包含 Service Invocation、Service Trusted and Authorization (服務的信任、認證與授權)、通訊模式 (HTTP / gRPC)、通訊機制 (Push / Pull)、狀態管理 (State Machine)
  2. 維運基礎:高可用、擴展機制、Log 處理、Distributed Tracing、Metric
  3. 安全性:Data Encryption、Secret Management、KMS、Auth 整合
  4. 效能與可靠度:Rate Limit、降級、熔斷 …
  5. 擴充架構:Extendable Service Architecture
  6. 如何提升開發團隊工作效能:上述的東西,一個有經驗的、資深的軟體工程師,如何在一台資源為數不多的狀況之下,可以快速開發、容易測試,是很多技術主管說不出的痛。

這些問題個別來看,都有相當成熟的系統、或者生態圈,如果個別看,或者是個別從頭開始其實都不難,有很多現成的實踐可以參考。而對於既有的系統架構而言,如果要放入上述單一個功能,往往都要割肉、放血,傷筋動骨,讓技術主管、或者是架構師傷透腦筋,往往要面對新舊技術的整併,同時也要面對現場團隊對於新技術的排擠或者學習門檻。

對於開發應用程式的開發人員來講,滿足業務需求的開發已經夠頭痛了,還要考慮這麼多系統架構面的東西,這種事是靠熱情無法填補的。

也因此,很多文章在講 microservice 失敗的案例,或者在談分散式系統落地的難度:

Dapr 出現時,我並沒有特別注意。直到去年我在思考幾個議題,像是 多租戶架構擴充服務架構 (Extendable Service Architecture)授權與認證 …. 等,看到 Dapr 的概念,似乎可以解決一些本質上的問題,今年春節連假就開始研究。

下圖是 技術採用生命週期 (Technology Adoption Lifecycle),Dapr 現在版本是 v1.1.0 階段,還在 Innovators (New Things),不過我覺得是可以期待與投資研究的。

下一篇將直接用實作案例整理學習筆記,先從 Secret Store 開始。


延伸閱讀

Dapr 系列文章

相關文章

分散式系統系列文章

Dapr 官方文件

Dapr community call

參考資料




Comments