.Net 7 輕鬆上手Dapr之服務呼叫

2023-03-29 15:00:59

前言

對於Dapr ,在專案中也有用過一段時間,優缺點並存,但是瑕不掩瑜,目前隨著版本的迭代和第三方團隊對它的支援也使得我們用得更加得心應手,所以藉此也回顧一下Dapr的相關知識以及分享一下專案中用到的第三方庫MASA.Framework 對Dapr的完美支援。然後本文只是個人學習與分享,不喜勿噴,謝謝!

什麼是Dapr?

Dapr 是 Distributed Application Runtime (分散式應用執行時)的縮寫。
Dapr是一種可移植的,serverless的,事件驅動的執行時,它使開發人員可以輕鬆構建彈性,無狀態和有狀態微服務,這些服務執行在雲和邊緣上,幷包含多種語言和開發框架。
Dapr 的概念模型圖:

官方介紹

Dapr 環境設定

網上對於dapr自託管模式下的環境設定的教學也比較多了,所以這裡就只簡單介紹介紹幾個需要注意的地方。首先在安裝Dapr之前你或許需要能夠進行科學的上網,如果發現衝浪速度不理想的話,那就或許需要在夜深人靜的時候偷波塔了,當然你也可以選擇離線安裝,也比較簡單,相信聰明的你們都能夠一一搞定。

安裝 Dapr CLI

執行命令:

powershell -Command "iwr -useb https://raw.githubusercontent.com/dapr/cli/master/install/install.ps1 | iex"

此命令會安裝最新的 windows Dapr cli 並將$Env:SystemDrive\dapr此目錄新增到使用者 PATH 環境變數
然後通過重新啟動終端/命令提示字元並執行 dapr 命令來驗證 CLI 是否已安裝:

dapr


也可以在C槽和系統環境變數中檢視驗證

詳細步驟可以參考 安裝 Dapr CLI

安裝 Docker Desktop

然後因為Dapr CLI預設會在Docker內啟動 redis、zipkin、placement。所以我們可以安裝個Docker Desktop來增加dapr的體驗性。安裝完成後預設開啟WSL2。

詳細步驟可以參考 安裝 Docker Desktop
當然還可以參考大佬的文章手把手教你學Dapr - 3. 使用Dapr執行第一個.Net程式

初始化 Dapr

初始化dapr後,我們可以

  • 在本地獲取並安裝 Dapr sidecar 二進位制檔案。
  • 使用 Dapr 建立一個簡化應用程式開發的開發環境。

Dapr初始化包括:

  1. 執行Redis 容器範例以用作本地狀態儲存和訊息代理。
  2. 執行Zipkin 容器範例以實現可觀察性。
  3. 使用上述元件定義建立預設元件資料夾。
  4. 執行Dapr 放置服務容器範例以支援本地參與者。

首先我們如果只使用dapr的服務呼叫的話,就可以只安裝精簡版

dapr init --slim

如果想體驗dapr完整功能支援的話,可以執行

dapr init

這裡會從外網上拉取一些二進位制檔案,如果網路不好的話可能需要等待一段時間,如果長時間未能完成或出現網路相關錯誤的話,可以多嘗試幾次或者選擇離線安裝。
離線安裝這裡稍微介紹:
執行上述dapr初始化命令後,無論最後是否成功,都會在C:\Users\Administrator.dapr生成一些檔案 如:

然後如果最後失敗的話,可能會導致bin檔案中拉取的內容不完整。正常情況是這樣:

所以我們離線安裝的話,可以先使用命令

Dapr uninstall //刪除bin資料夾 (這裡選擇此命令)
Dapr uninstall --all //刪除 C:\Users\Administrator\.dapr 

就可以自己去dapr 的GitHub上下載對應版本的檔案壓縮包,然後把檔案放入bin資料夾中即可。一般情況下,會自動解壓縮。

  • dashboard_windows_amd64.zip
  • daprd_windows_amd64.zip

安裝完成後可以執行命令驗證:

dapr -v


詳細步驟可以參考初始化 Dapr

專案准備

  • dotNet 7
  • Docker Desktop
  • Visual Studio 2022
  • Dapr

專案搭建

我們先準備一個使用者端專案-DaprClientWeb與兩個伺服器端專案-ServiceAServiceB

然後先在兩個伺服器端專案中分別增加一個測試介面
ServiceA 專案範例

接下來我們先用dapr cli 請求介面驗證一下環境可行性
使用命令列工具,跳轉到ServiceA的原始碼目錄,執行命令:

 dapr run --app-id service-a --app-port 5001 dotnet run

這個命令會呼叫基礎 Dapr 執行時,並使應用程式和 Dapr sidecar一起執行

然後輸入以下命令檢視 Dapr sidecar是否啟動成功:

dapr list


最後接著輸入以下命令存取介面:

dapr invoke --app-id service-a --method GetServiceA --verb GET


OK,環境到此驗證完畢,專案也基本上搭建完成,下面會藉助使用者端專案-DaprClientWeb 通過Dapr .Net SDK來分別請求ServiceAServiceB的介面 演示Dapr的服務呼叫。

Dapr 服務呼叫

Dapr 服務呼叫的工作原理

  1. 服務A 向服務B發起一個HTTP/gRPC的呼叫。呼叫轉到了原生的Dapr sidecar
  2. Dapr使用名稱解析元件發現服務B的位置
  3. Dapr 將訊息轉發至服務 B的 Dapr sidecar
  4. 服務B 的 Dapr sidecar將請求轉發至服務B 上的特定端點 (或方法) 。 服務B 隨後執行其業務邏輯程式碼
  5. 服務B 傳送響應給服務A。 響應將轉至服務B 的Dapr sidecar
  6. Dapr 轉發響應至服務A 的 Dapr sidecar
  7. 服務 A 接收響應

: Dapr sidecar之間的所有呼叫都通過gRPC來提高效能。 僅服務與 Dapr sidecar之間的呼叫可以是 HTTP或gRPC

注:Dapr sidecar使用可插入的名稱解析元件來解析服務 B 的地址。在自託管模式下,Dapr 使用 mdns 來查詢它。 在 Kubernetes 模式下執行時,由 Kubernetes DNS 服務決定地址。

關於自託管模式下的mDNS:

綜上我們可以得知:
Dapr是通過向每個計算單元注入了一個Sidecar容器/程序,然後運用Sidecar與事件觸發器進行互動,並通過標準HTTP或gRPC協定與計算單元進行通訊的

專案實戰

我們在DaprClientWeb專案中增加兩個介面分別用來請求ServiceA服務的/GetServiceA介面與ServiceB服務的/GetServiceB
同時需要在DaprClientWeb專案中引入Dapr.Client Nuget包
程式碼:

注意:此處DaprClient是從DaprClinetBuilder Build出來的
ServiceA

ServiceB

執行命令:

 dapr run --app-id service-a --app-port 5001 dotnet run
 dapr run --app-id service-b --app-port 5002 dotnet run
 dapr run --app-id dapr-client-web --app-port 5003 dotnet run

檢視效果:

然後我們通過DaprClientWeb專案 請求介面



到這裡我們已經可以使用dapr進行服務之間的通訊了。但是每次都需要通過
dapr run
命令啟動dapr sidecar這樣豈不是太不優雅了,其中還包括幾個APPID,DAPR_HTTP_PORT,AppPort,DAPR_GRPC_PORT需要管理,到時候服務一多肯定會十分頭疼。其實這些問題都已經被一些大佬解決了,比如MASA團隊就為此提供了很好地支援,我們只需在我們的專案中引入一個包就甚至可以通過一行程式碼就能夠讓專案輕鬆的使用Dapr了。

MASA DaprStarter

首先我們先在專案中引入 Masa.Contrib.Development.DaprStarter.AspNetCore
當前我用的版本是1.0.0-preview.22並且都在一直更新,還是比較穩定的,聽說他們有全職的開源團隊在維護與迭代,所以我們可以放心使用。

然後在各自專案的Program.cs中增加一行程式碼就可以了

builder.Services.AddDaprStarter(builder.Configuration.GetSection("DaprOptions"));

DaprClientWeb 範例:

當然需要在appsettings.Development.json檔案中加入設定

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "DaprOptions": {
    "AppId": "service-a",//不指定的話會自動根據AppId + AppIdDelimiter('-') + AppIdSuffix 規則生成
    "AppPort": 5001,
    "AppIdSuffix": "",//當前機器網路卡地址
    "DaprHttpPort": 8082,
    "DaprGrpcPort": 8083
  }
}

最後我們就只需直接啟動專案就可以了,其他的就不用操心了。
看看效果:

細心的同學會發現這幾個埠都變成我們在專案的appsettings.Development.json 檔案中設定的了

然後這裡需要注意的是,這種用法只是在自託管模式下方便與本地開發偵錯使用,在生產環境上有基於k8s的另外一套用法,這裡就不做多概述,感興趣的同學可自行研究。

如果想了解 Masa.Contrib.Development.DaprStarter.AspNetCore 這個包的到底幫我們做了那些工作,可以去看看大佬的文章 一行程式碼讓你的專案輕鬆使用Dapr
到此,基於dapr的服務呼叫已經差不多大功告成了,如果
MASA
的包用的爽了,記得去GitHub Star 一下。
贈人玫瑰,手留餘香

結尾

由於文章篇幅有限,涉及到知識內容也不是很深入,感興趣的同學可以自行研究。
然後本文都是基於我的個人理解,然後也有參考官網以及大佬的文章和視訊,文章如有什麼不妥的地方歡迎指正,共同進步。後續有時間還會繼續學習相關技術知識,歡迎Star與關注。感謝閱讀