天天看點

一行代碼讓你的項目輕松使用Dapr

介紹

Dapr簡化了雲原生開發,讓開發可以把焦點放在應用的業務邏輯上,進而讓代碼簡單、可移植,那作為一個.Net開發者,我們也希望項目可以快速用上dapr,那究竟應該如何做呢?

Dapr提出了Sidecar(邊車)的概念,在啟動項目時再額外啟動一個Sidecar, 通過Sidecar可以解決程序間通信,為此官方提供了兩種部署方式:

  1. 自托管方式下運作Dapr
  2. 在 Kubernetes 模式中部署和運作 Dapr

其中Kubernetes模式部署是通過Kubernetes來完成的,在開發中我們更多的是通過自托管模式使用Dapr,那自托管模式是怎麼做的呢?

使用指令行工具,在項目根目錄輸入:

dapr run --app-id assignment-server --app-port 5038 dotnet run
           
詳細文檔參考:手把手教你學Dapr - 3. 使用Dapr運作第一個.Net程式

參考以上詳細文檔操作後,我們就可以在指令行工具中執行

dapr invoke --app-id assignment-server --method hello

或者Http請求來調用對應的應用的方法

看似好像也不是很複雜,但如果你需要調試dotnet項目呢?再複雜一點的需要啟動多個項目進行調試呢?端口一多起來的确會顯得很麻煩。

有沒有什麼辦法可以解決呢?有,docker-compose。

但我還不想用這麼重的東西,我想像平時開發項目一樣直接在windows上運作可不可以?

Masa.Utils.Development.Dapr.AspNetCore 它來了

協助管理dapr程序,用于開發時減少對docker compose的依賴

瞌睡了就有人送枕頭,一句話讓我們了解到了它的作用,正好解決了我們需要通過指令行來啟動dapr的問題,那下面我們看看這個怎麼用:

入門

本着絕對不多寫一行代碼的心态,我們準備出發了……

  1. 從大佬doddgu的部落格的連結中發現一份源碼位址,為防止後期文檔調整,先fork一份到自己倉庫
    git clone https://github.com/zhenlei520/dapr-study-room.git
               
  2. 使用指令行工具打開目錄dapr-study-room\Assignment03,然後執行指令
    dotnet add package Masa.Utils.Development.Dapr.AspNetCore --version 0.4.0-preview.3
               
    或使用Visual Studio打開解決方案Assignment03,選中Assignment.Server并安裝Masa.Utils.Development.Dapr.AspNetCore
  3. 打開

    Program.cs

    ,并添加DaprStarter(注意看有注釋的那一行)
    using Masa.Utils.Development.Dapr.AspNetCore;
    
    var builder = WebApplication.CreateBuilder(args);
    builder.Services.AddDaprStarter();//添加DaprStarter即可
    var app = builder.Build();
    
    app.Map("/hello", () => Console.WriteLine("Hello World!"));
    
    app.Run();
               
  4. 使用指令行工具執行指令驗證dapr是否啟動成功
    dapr invoke --app-id Assignment-Server-00D861D0C0B7 --method hello
               

此時會有小夥伴問了,為什麼app-id是Assignment-Server-00D861D0C0B7?

檢視文檔後發現

Masa.Utils.Development.Dapr.AspNetCore

的app-id生成規則為:

AppId + AppIdDelimiter + AppIdSuffix

,其中

  • AppId預設:項目名.Replace(".","-")
  • AppIdSuffix預設:網卡位址

由于我們的項目名為Assignment.Server,目前電腦的網卡位址是00D861D0C0B7,是以dapr最終的appid為Assignment-Server-00D861D0C0B7,到這裡,Masa.Utils.Development.Dapr.AspNetCore的使用講解已經完成了

冷知識,為什麼 . 要換成 - ?

因為Dapr的AppId采用FQDN:(Fully Qualified Domain Name)全限定域名:同時帶有主機名和域名的名稱。(通過符号“.”)

為什麼要加網卡位址作為字尾?

因為目前自托管預設采用mDNS,會導緻區域網路内使用者的AppId互相污染。你的同僚和你一起在開發,都啟動了A應用,你倆就自動負載了,那後果自然就是請求也到處跑了。

進階

如果我希望自己指定AppId而不是使用預設的規則怎麼辦呢?目前支援三種寫法:

  • 根據規則(配置預設裝配)
  • 根據規則 + 代碼指定(配置自定義裝配)
  • 根據配置檔案(根據IConfiguration配置生成)

配置預設裝配(也是上面介紹的一行代碼的方式)

修改

Program.cs

檔案

// 省略上述代碼
builder.Services.AddDaprStarter(); 
           

根據規則 + 代碼指定(配置自定義裝配)

修改

Program.cs

檔案

// 省略上述代碼
builder.Services.AddDaprStarter(opt =>
{
    opt.AppId = "masa-dapr-test";
    opt.AppPort = 5001;
    opt.AppIdSuffix = "";
    opt.DaprHttpPort = 8080;
    opt.DaprGrpcPort = 8081;
});
           
基于預設裝配的更新版,在預設裝配基礎上通過指定特殊參數完成特殊需求,未配置的參數将使用預設值

根據IConfiguration配置生成

  1. 修改

    appsettings.json

{
  "DaprOptions": {
    "AppId": "masa-dapr-test",
    "AppPort": 5001,
    "AppIdSuffix": "",
    "DaprHttpPort": 8080,
    "DaprGrpcPort": 8081
  }
}
           
  1. 修改

    Program.cs

builder.Services.AddDaprStarter(builder.Configuration.GetSection("DaprOptions"));
           
優勢:更改appsettings.json配置後,dapr sidecar會自動更新,項目無需重新開機

Masa.Utils.Development.Dapr.AspNetCore的設計思路

設計思路基于兩個方面,其一本機自動啟動dapr sidecar還可以正常調試.Net項目,其二簡化配置

技術選型

我們有兩種啟動dapr sidecar的方式:

  1. dapr run
  2. daprd

兩者之間的差别如下所示:

完整的對比可檢視:https://docs.dapr.io/reference/arguments-annotations-overview/

通過對比我們發現,我們的目标使用daprd與Dapr CLI都可以實作,那為什麼Masa.Utils.Development.Dapr選擇的是Dapr CLI,而不是daprd呢?

核心的原因是dapr可以通過dapr list指令很簡單的就擷取到目前運作的所有dapr程式,而daprd無法擷取。如果使用daprd,那我們就需要使用C#代碼通過操作dll擷取具體執行的dapr指令,且多平台支援不好,是以暫時用了Dapr CLI

更優秀的Dapr管理需要做到什麼?

  • 使用簡單
  • 參數可配置
  • 功能支援選擇性啟動
  • Dapr保活
  • 配置支援動态更新

為了能更友善的使用,我們做了以下約定:

  1. 針對dapr的非必填項,預設關閉不啟用,手動配置參數後開啟
  2. 針對dapr的必填項: app-id、app-port、dapr-http-port、dapr-grpc-port 自動生成并配置

app-id 生成規則

其中dapr的app-id預設生成規則為:

AppId + AppIdDelimiter + AppIdSuffix

,其中

  • AppId預設:項目名.Replace(".","-")
  • AppIdDelimiter預設:-
  • AppIdSuffix預設:目前機器網卡位址

當AppIdSuffix指派為空字元串,dapr的AppId的生成規則為:

AppId

app-port 擷取

private ushort GetAppPort(DaprOptions options)
{
  var server = _serviceProvider.GetRequiredService<IServer>();
  var addresses = server.Features.Get<IServerAddressesFeature>()?.Addresses;
  if (addresses is { IsReadOnly: false, Count: 0 })
      throw new Exception("Failed to get the startup port, please specify the port manually");

  return addresses!
      .Select(address => new Uri(address))
      .Where(address
          => (options.EnableSsl is true && address.Scheme.Equals(Uri.UriSchemeHttps, StringComparison.OrdinalIgnoreCase))
          || address.Scheme.Equals(Uri.UriSchemeHttp, StringComparison.OrdinalIgnoreCase))
      .Select(address => (ushort)address.Port).FirstOrDefault();
}
           
為了防止啟動過程中修改端口,過早的擷取到被棄用的端口。是以我們使用背景任務啟動dapr sidecar

dapr-http-port、dapr-grpc-port擷取

因為支援使用者配置,是以我們遵循下面的順序

  1. 如果指定端口,被占用則自動kill port所在程序,保證可以sidecar可以正常啟動

    為什麼端口占用就要先kill,複用不行嗎?

    因為sidecar有初始化配置,程式調整的代碼影響到sidecar配置變更我們無法檢測,是以啟動時保證是最新的是比較合适的選擇

  2. 如果未指定端口,則交還給dapr,通過Dapr CLI的規則生成對應的http-port或grpc-port

Dapr保活

為了保證dapr程序是活躍的,我們在庫中建立了一個心跳檢查任務用來檢測目前的dapr程序是否是活躍的,當dapr程序意外停止後會被重新開機,且配置資訊與上一次成功的dapr配置保持不變

如果不需要保活機制的話可以将EnableHeartBeat改為false,則不啟用dapr保活機制

配置支援動态更新

我們通過IOptionsMonitor的OnChange方法來監聽配置的變更,當配置變更後我們會通過IDaprProcess 提供的Refresh方法來重新開機dapr程序,并重新調整環境變量資訊

本章源碼

Assignment03

https://github.com/zhenlei520/dapr-study-room

開源位址

MASA.BuildingBlocks:https://github.com/masastack/MASA.BuildingBlocks

MASA.Contrib:https://github.com/masastack/MASA.Contrib

MASA.Utils:https://github.com/masastack/MASA.Utils

MASA.EShop:https://github.com/masalabs/MASA.EShop

MASA.Blazor:https://github.com/BlazorComponent/MASA.Blazor

如果你對我們的 MASA Framework 感興趣,無論是代碼貢獻、使用、提 Issue,歡迎聯系我們

本文來自部落格園,作者:磊_磊,轉載請注明原文連結:https://www.cnblogs.com/zhenlei520/p/16157625.html

本文版權歸作者和部落格園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連結,否則保留追究法律責任的權利

繼續閱讀