摘要 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 Concepts and Designing

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),不過我覺得是可以期待與投資研究的。

下一篇將直接用實作案例整理學習筆記。


延伸閱讀

相關文章

Dapr

Dapr community call

參考資料




Comments