dapr大概的瞭解,個人理解他就是一個分散式服務的管理,把微服務常用的元件(快取,訊息中介軟體、分散式鎖、安全id4等)和監控以及服務註冊、發現等等一系列功能以一個很抽象的方式管理起來。
可能我們部署微服務用consul、ocelot、polly套件、orleans等去實現,但是不可避免的會遇到服務之間的呼叫等問題,更不用說服務本身的一些列騷操作,dapr剛好幫助我們解決了這些,
服務之間呼叫Dapr.AspNetCore庫,客戶端呼叫的都是dapr管理庫Dapr.Client,netcore使用就這兩大庫,再加上各種yaml配置等,當然它是不侷限語言限制。
下面用一個簡單的例子來揭露一下他的真面目,專案也很直白,一個client對外,server就是提供服務的一方。
至於程式碼更是簡單的出奇,服務端就只需要一行注入的程式碼,業務程式碼不需要做任何改動。
namespace Server { public class Program { public static void Main(string[] args) { var builder = WebApplication.CreateBuilder(args); // Add services to the container. builder.Services.AddControllers().AddDapr(); //關鍵的服務註冊,只需要引入Dapr.AspNetCore包 // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(); var app = builder.Build(); // Configure the HTTP request pipeline. if (app.Environment.IsDevelopment()) { app.UseSwagger(); app.UseSwaggerUI(); } //app.UseHttpsRedirection(); app.UseAuthorization(); app.MapControllers(); app.Run(); } } }
using Microsoft.AspNetCore.Mvc; namespace Server.Controllers { [ApiController] [Route("[controller]")] public class WeatherForecastController : ControllerBase { private static readonly string[] Summaries = new[] { "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching" }; private readonly ILogger<WeatherForecastController> _logger; public WeatherForecastController(ILogger<WeatherForecastController> logger) { _logger = logger; } [HttpGet(Name = "GetWeatherForecast")] public IEnumerable<WeatherForecast> Get() { return Enumerable.Range(1, 5).Select(index => new WeatherForecast { Date = DateTime.Now.AddDays(index), TemperatureC = Random.Shared.Next(-20, 55), Summary = Summaries[Random.Shared.Next(Summaries.Length)] }) .ToArray(); } } } namespace Server { public class WeatherForecast { public DateTime Date { get; set; } public int TemperatureC { get; set; } public int TemperatureF => 32 + (int)(TemperatureC / 0.5556); public string? Summary { get; set; } } }
下面就是客戶端呼叫的程式碼,只需要引入包Dapr.Client包,當然consul作為服務之間呼叫就是httpclient呼叫了。
namespace Client { public class Program { public static void Main(string[] args) { var builder = WebApplication.CreateBuilder(args); // Add services to the container. builder.Services.AddControllers(); // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(); var app = builder.Build(); // Configure the HTTP request pipeline. if (app.Environment.IsDevelopment()) { app.UseSwagger(); app.UseSwaggerUI(); } //app.UseHttpsRedirection(); app.UseAuthorization(); app.MapControllers(); app.Run(); } } }
using Dapr.Client; using Microsoft.AspNetCore.Mvc; namespace Client.Controllers { [ApiController] [Route("[controller]")] public class WeatherForecastController : ControllerBase { private readonly ILogger<WeatherForecastController> _logger; public WeatherForecastController(ILogger<WeatherForecastController> logger) { _logger = logger; } [HttpGet(Name = "GetWeatherForecast")] public IEnumerable<WeatherForecast> Get() { //服務之間沒有用httpclient呼叫,用特有的dapr呼叫。 var daprClient = new DaprClientBuilder().Build(); var content = daprClient.InvokeMethodAsync<IEnumerable<WeatherForecast>>(HttpMethod.Get, "getwf", "WeatherForecast").Result; _logger.LogInformation($"獲取wf成功:{content.ToArray().ToString()}"); return content.ToArray(); } } } namespace Client { public class WeatherForecast { public DateTime Date { get; set; } public int TemperatureC { get; set; } public int TemperatureF => 32 + (int)(TemperatureC / 0.5556); public string? Summary { get; set; } } }
這個例子僅僅只說明了用Dapr微服務之間的呼叫,這個不是很服務,但是部署和配置等一系列操作就需要docker基礎了。
首先要有虛擬機器,linux系統,安裝好docker,本文沒有用到任何yaml檔案,所以沒用docker-compose。
dapr的安裝看官網,還有初始化,安裝完docker ps看看這幾個服務在不在。
aspnetcore釋出程式碼掠過,下面是釋出後的程式碼,我直接複製到我的虛擬機器home目錄下面。
開三個視窗,開啟Server
、Client資料夾,分別在對應資料夾執行命令, --app-id 後面就是dapr內部指定的唯一識別,相當於httpclient的IP地址, --dapr-http-port就是dapr的地址埠,--app-port就是dapr服務提供給外部的呼叫地址埠。
打個比方一個dapr利弊一個docker,部署一個服務起一個docker,服務之間通訊那麼也就成了docker之間的通訊,而且他負責自己服務的一切事情。
看呼叫程式碼getwf就是Server在dapr起的唯一名字--app-id, WeatherForecast就是控制器,類似於httpclient的 http://*:port/weatherforecast get呼叫。
dapr run --app-id clientservice --dapr-http-port 5882 --app-port 5883 dotnet Client.dll
dapr run --app-id getwf --dapr-http-port 5880 --app-port 5881 dotnet Server.dll
//服務之間沒有用httpclient呼叫,用特有的dapr呼叫。 var daprClient = new DaprClientBuilder().Build(); var content = daprClient.InvokeMethodAsync<IEnumerable<WeatherForecast>>(HttpMethod.Get, "getwf", "WeatherForecast").Result; _logger.LogInformation($"獲取wf成功:{content.ToArray().ToString()}");
檢視dapr list可以看到有兩個服務在執行中。正常情況我們呼叫虛擬機器ip:5883/weatherforecast就可以了正常訪問客戶端拿到資料,但是很不幸我失敗了,而且還沒找到原因。
部署的server服務後會有下面的列印資訊,而且我是可以透過5096埠訪問的,這說明問題出在dapr上,而不是我們部署的問題。
官方文件介紹的不是很多,而且我也只是近期才研究這個,所以這個問題如果有能解答的萬分感謝!
配置檔案appsettings.json需要指定埠,否則兩個以上服務部署會預設5000衝突。
以上的部署僅僅體現它的服務之間是怎麼呼叫的程式碼實現。
它的其他核心功能狀態管理、快取、非同步通訊、分散式鎖、鏈路、監控、安全等一系列中介軟體幾乎涵蓋了微服務的零零碎碎。
以前一直以為這個是運維的管理工具,去研究實踐才認識到程式碼層面也是需要大量時間學習,就是各種中介軟體的使用。作為開發不去學習確實有點跟不上時代了。從docker、k8s 到dapr,對於面試開發也挺不容易。
後續來了,一天後查資料發現問題所在。dapr 的--app-port需要跟dotnet啟動服的埠保持一致。比較看好dapr,netcore微服務架構是個不錯的選擇,還有未來也很看好。部署沒問題了,後面就是學習微服務中運用dapr的間件。
w