心酸部署dapr經歷,最後一步莫名的遺憾

星仔007發表於2023-02-18

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看看這幾個服務在不在。

 安裝 Dapr CLI 腳手架工具 | Dapr 文件庫

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

 

相關文章