摘要 Dapr 的設計與概念
前面兩篇先從體驗 Dapr 開始,從 Self-Hosted 到實際 Run on K8s 的體驗,大概了解的 Dapr 實際上怎麼用。Dapr 背後實際上把 分散式系統概念
與 微服務架構實踐的挑戰
、以及 K8s
圍繞這三個主題做了全面性的考慮與設計,特別是 Kubernetes Patterns 一書的作者 Bilgin Ibryam 提出 Multi-Runtime Microservices Architecture 的概念之後,加上 Dapr 這樣的分散式應用框架的出現,我感覺到下一個世代的來臨。
Bilgin Ibryam 的 The Evolution of Distributed Systems on Kubernetes、Multi-Runtime Microservices Architecture (簡中翻譯),還有 Kubernetes Patterns 這些資料很直得一讀。
本文整理在 Study Dapr 過程中,整理背後設計的思路與概念。
摘要 Dapr 的設計與概念
Dapr 設計的考量幾乎與前述 Multi-Runtime 幾乎不謀而合,其中我整理幾個非常核心的設計想法:
- Sidecar
- Building Block & Component
- Service Invocation
- Middleware
- State
基於上述這些核心設計,讓 Dapr 有了 Multi-Runtime Architecture 的特性,以此延伸出底下的重要功能,或者說設計模式:
- Security
- Observability: tracing, metrics, logs and health
- Pub / Sub / Batch Process
- Actors
- Secret Management
Sidecar
下圖是 Sidecar 與 Microservice 之間搭配後,多個服務的關係圖,這樣的結構形成了 Service Mesh 的概念。在 Dapr 裡, Sidecar 由 Dapr 透過配置的方式,動態產生,隨後伴隨著 App,一組 Dapr Sidecar + App 的組合稱為 Dapr App
。
把鏡頭拉近一點,Dapr App 的概念透在 K8s 實踐就是這樣:
Pod = (App_Container + Sidecar_Container)
如下圖:
同樣的概念,如果不是跑在 K8s,也就是 Self-Hosted 的概念,如下圖:
每個 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 把最核心的 Component 提供基於分散式系統的 最佳實踐 (Best Practice)
與 設計模式 (Design Patterns)
,提供了以下的核心實作分類:
- 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 ..
- Pub / Sub:
- 全部列表:Supported pub/sub brokers
- 著名實作:Hazelcast, Redis Streams, NATS, Kafka, Azure Service Bus, RabbitMQ, Azure Event Hubs, GCP Pub/Sub, MQTT
- Middleware: Dapr 的特殊 Components,後述。
- Service discovery name resolution: Dapr 的特殊 Components,後述。
- State Stores
- 全部列表:Supported state stores
- 著名實作:Hazelcast, Memcached, MongoDB, MySQL, PgSQL, Redis, AWS DynamoDB
- 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 的概念,如下圖:
摘要一些特性:
- Component 裡面的 Pipeline
- Component 裡面可以傳遞參數
- 透過 Dapr Configuration 宣告用哪一個 Middleware
- Middleware 目前沒有開放動態新增,新增種類要透過 PR,發到這裡:原始碼
- Dapr 透過 fasthttp, FastAPI 實作 Middleware。但有一些 fasthttp 的設定陸續在開放中,類似議題:
Q and A
Q: Dapr is not a service mesh
Dapr 整個架構倚賴 Sidecar Pattern,Study 過程,腦袋聲音一直出來。我整理了過去對於相關技術的學習脈絡:
- Sidecar: 設計模式 在翻譯 分散式系統設計 時就有著墨
- Service Mesh: 2018 年整理的概念,特別是與 API Gateway 比較。
- Service Mesh Interface, SMI: 2019 年社群發起的開放標準規格
- Open Service Mesh: 輕量的實作
2017 年誕生的 Service Mesh,當時曾經關注一陣子,直到後來 Envory、Istio 等框架出現後,發現這概念很重要,但是要真的落地到現場難度很高,工作上一直也都沒用到。倒是 API Gateway 廣泛應用。
Dapr 本身不處理 Service Mesh 的事情,定位真的就是 App 的 Sidecar,下圖是 Dapr community call 31 的介紹,直接與 Istio 整合的概念:
圖源:Dapr community call 31 - 2/9/2021
整理這篇文章的時候, Dapr v1.1.0
Release 了,官網的 Concepts 直接解釋 Dapr 與 Service Meshes 的範圍,如下圖。Dapr 處理的是藍底色的,而 Service Meshes 則是灰底色的:
結語
分散式架構大概都要面對一些複雜的基礎架構議題,底下是我常思考要解決的問題:
服務治理
:包含 Service Invocation、Service Trusted and Authorization (服務的信任、認證與授權)、通訊模式 (HTTP / gRPC)、通訊機制 (Push / Pull)、狀態管理 (State Machine)維運基礎
:高可用、擴展機制、Log 處理、Distributed Tracing、Metric安全性
:Data Encryption、Secret Management、KMS、Auth 整合效能與可靠度
:Rate Limit、降級、熔斷 …擴充架構
:Extendable Service Architecture如何提升開發團隊工作效能
:上述的東西,一個有經驗的、資深的軟體工程師,如何在一台資源為數不多的狀況之下,可以快速開發、容易測試,是很多技術主管說不出的痛。
這些問題個別來看,都有相當成熟的系統、或者生態圈,如果個別看,或者是個別從頭開始其實都不難,有很多現成的實踐可以參考。而對於既有的系統架構而言,如果要放入上述單一個功能,往往都要割肉、放血,傷筋動骨,讓技術主管、或者是架構師傷透腦筋,往往要面對新舊技術的整併,同時也要面對現場團隊對於新技術的排擠或者學習門檻。
對於開發應用程式的開發人員來講,滿足業務需求的開發已經夠頭痛了,還要考慮這麼多系統架構面的東西,這種事是靠熱情無法填補的。
也因此,很多文章在講 microservice 失敗的案例,或者在談分散式系統落地的難度:
- To Microservices and Back Again - Why Segment Went Back to a Monolith, 2020/08
- 11 Reasons Why You Are Going To Fail With Microservices
- Distributed Systems Are Hard
Dapr 出現時,我並沒有特別注意。直到去年我在思考幾個議題,像是 多租戶架構
、擴充服務架構 (Extendable Service Architecture)
、授權與認證
…. 等,看到 Dapr 的概念,似乎可以解決一些本質上的問題,今年春節連假就開始研究。
下圖是 技術採用生命週期 (Technology Adoption Lifecycle)
,Dapr 現在版本是 v1.1.0 階段,還在 Innovators (New Things),不過我覺得是可以期待與投資研究的。
下一篇將直接用實作案例整理學習筆記,先從 Secret Store 開始。
延伸閱讀
Dapr 系列文章
- 摘要 Dapr 的設計與概念
- Experience Dapr - Hello World
- Experience Dapr - Run on K8s
- Experience Dapr - Secret Store
- Experience Dapr - Pub/Sub
相關文章
- Service Mesh
- 演講:邁向 API 經濟 - API Gateway 導入之旅
- 分散式系統設計 - 正體中文版翻譯記事
- Overview API Gateway
- 摘要密碼學與資訊安全
- Service Catalog
分散式系統系列文章
- 聊聊分散式系統
- 分散式一致性問題與共識演算法
- CAP Theorem
- Distributed Message Systems
- Eventually Consistent 與 Dynamo NWR 模型
- 淺談分散式交易
- Design Patterns for Distributed Systems
- 分散式系統設計 - 正體中文版翻譯記事
Dapr 官方文件
- Dapr at 20,000 feet
- Dapr reference application
- A visual guide to Dapr
- Dapr and service meshes - 2021/04/01 Updated
- Book: Practical Microservices with Dapr and .NET
Dapr community call
- Dapr community call 23 - 2020/09/30: Dapr and Azure API Management integration, Service invocation access lists, Secret scoping
- Dapr community call 22 - 2020/09/18: Declarative pub/sub subscriptions, Cross namespaces for service invocation, Batch processing sample demo, Tracing using the Java SDK
- Dapr community call 24 - 2020/10/14: eShop .NET demo
- Dapr community call 27 - 2020/11/25: Dapr observability with New Relic, Rate limiting your app with Dapr, Dapr Discord server
- Dapr community call 30 - 2021/01/26: State sharing strategies between services with Dapr, Message TTL in Pub/Sub
- Dapr community call 31 - 2021/02/09: Running Dapr with Istio, Context for tracing in the Java SDK
- Dapr community call 34 - 2021/03/23: The Dapr-Mesh, gRPC and Pub/Sub, Dapr project insights, community health and v1.0 momentum
參考資料
- The Evolution of Distributed Systems on Kubernetes
- Multi-Runtime Microservices Architecture (簡中翻譯)
- The Kubernetes Effect
- Dapr v1.0展望:从servicemesh到云原生
- Mecha:将Mesh进行到底
- Towards continuous resilience
- 通过 Dapr 实现一个简单的基于 .net 的微服务电商系统, Code