前言

上一篇咱们讲了应用HttpClient的形式调用,那么如果咱们当初须要更换为通过dapr实现服务调用,咱们须要做哪些事件呢?

Caller.Dapr 入门

如果咱们的我的项目本来应用的是Caller.HttpClient,当初心愿改为应用Caller.Dapr,那么咱们须要做什么呢?

  1. 革新Caller 服务调用 - HttpClient的中的服务端,使得服务端反对dapr调用
  2. 调整客户端代码,使客户端反对通过dapr来做到服务调用,并达到与HttpClient调用雷同的后果

筹备工作

  • 装置.Net 6.0
  1. 创立ASP.NET Core 空白解决方案Assignment03
  2. Assignment02文件夹下的Assignment.Server复制到Assignment03的文件夹下,而后将我的项目Assignment.Server增加到解决方案Assignment03
  3. 选中Assignment.Server并装置Masa.Utils.Development.Dapr.AspNetCore

    dotnet add package Masa.Utils.Development.Dapr.AspNetCore --version 0.4.0-rc1
  4. 批改Assignment.Server我的项目下的Program.cs

    //疏忽命名空间援用var builder = WebApplication.CreateBuilder(args);// 增加DaprStarter,用于服务端启动dapr sidecar,革新服务端反对dapr调用的重点(倡议在开发环境下应用,线上环境应用k8s部署)builder.Services.AddDaprStarter(option =>{    option.AppId = "Assignment-Server";    option.DaprGrpcPort = 7007;    option.DaprHttpPort = 7008;    option.AppIdSuffix = string.Empty;});var app = builder.Build();/// 疏忽路由等

    Q: 什么是DaprStarter?为什么要应用DaprStarter?
    A: DaprStarter是Masa团队开发进去用于治理Dapr sidecar的包,能够帮忙咱们在开发环境下很简略的应用dapr sidecar

    Q: 为什么要指定AppId、DaprGrpcPort、DaprHttpPort等信息?
    A: 客户端调用须要失去Dapr的AppId、设置DaprGrpcPort、DaprHttpPort是因为客户端演示我的项目没有应用dapr sidecar,如果客户端我的项目也应用dapr sidecar,此处能够不指定DaprGrpcPort、DaprHttpPort,更多信息请参考文章

  5. 创立ASP.NET Core 空我的项目Assignment.Client.DaprClientWeb作为客户端并装置Masa.Utils.Caller.DaprClient

    dotnet add package Masa.Utils.Caller.DaprClient --version 0.4.0-rc1
  6. 批改Assignment.Client.DaprClientWeb我的项目下的Program.cs

    using Masa.Utils.Caller.Core;using Masa.Utils.Caller.DaprClient;using Microsoft.AspNetCore.Mvc;var builder = WebApplication.CreateBuilder(args);builder.Services.AddCaller(option =>{    // 留神: 与Caller.HttpClient相比,须要批改的中央    options.UseDapr(masaDaprClientBuilder =>    {        masaDaprClientBuilder.Name = "userCaller"; // 以后Caller的别名(仅有一个Caller时能够不填),Name不能反复        masaDaprClientBuilder.IsDefault = true; // 默认的Caller反对注入ICallerProvider获取(仅有一个Caller时可不赋值)        masaDaprClientBuilder.AppId = "Assignment-Server";//设置以后caller下Dapr的AppId    });});var app = builder.Build();app.MapGet("/", () => "Hello HttpClientWeb.V1!");app.MapGet("/Test/User/Get", async ([FromServices] ICallerProvider callerProvider) =>{    var user = await callerProvider.GetAsync<object, UserDto>("User", new { id = new Random().Next(1, 10) });    return $"获取用户信息胜利:用户名称为:{user!.Name}";});app.MapGet("/Test/User/Add", async ([FromServices] ICallerProvider callerProvider) =>{    var dateTimeOffset = new DateTimeOffset(DateTime.UtcNow);    string timeSpan = dateTimeOffset.ToUnixTimeSeconds().ToString();    var userName = "ss_" + timeSpan; //模仿一个用户名    string? response = await callerProvider.PostAsync<object, string>("User", new { Name = userName });    return $"创立用户胜利了,用户名称为:{response}";});app.Run();public class UserDto{    public int Id { get; set; }    public string Name { get; set; } = default!;}
    相较于Assignment.Client.HttpClientWebAssignment.Client.DaprClientWeb仅仅是更改了Program.cs,将UseHttpClient改为UseDapr,其余代码无需批改
  7. 增加环境变量DAPR_GRPC_PORT,值为7007DAPR_HTTP_PORT,值为7008

    Q: 为什么要增加环境变量?
    A: 因为以后客户端并未应用dapr sidecar,若以后客户端也应用dapr sidecar,此处能够不增加环境变量

当初Caller的HttpClient版本就能够应用了,别离启动Assignment.ServerAssignment.Client.DaprClientWeb服务,浏览器拜访http://localhost:5042/Test/User/Gethttp://localhost:5042/Test/User/Add,别离输入对应的获取用户信息胜利以及创立用户胜利的提醒,则证实调用胜利了

DaprClient 最佳实际

Assignment.Client.DaprClientWeb的写法比较简单,其用法与Assignment.Client.HttpClientWeb基本一致,与Caller.HttpClient相似,DaprClient咱们举荐应用上面的写法:

  1. 创立ASP.NET Core 空我的项目Assignment.Client.DaprClientWeb.V2作为调用方V2版本
  2. 选中Assignment.Client.DaprClientWeb.V2并装置Masa.Utils.Caller.DaprClient

    dotnet add package Masa.Utils.Caller.DaprClient --version 0.4.0-rc1
  3. 增加类ServerCallerBase (对应服务端服务)

    using Masa.Utils.Caller.DaprClient;namespace Assignment.Client.DaprClientWeb.V2;/// <summary>/// 留神:ServerCallerBase是抽象类哟(抽象类不会被DI注册), 与应用Caller.HttpClient相比,须要批改的是继承的基类改为DaprCallerBase/// </summary>public abstract class ServerCallerBase : DaprCallerBase{    protected override string AppId { get; set; } = "Assignment-Server";//设置以后Caller须要申请的服务端我的项目Dapr的AppId    public ServerCallerBase(IServiceProvider serviceProvider) : base(serviceProvider)    {    }}
  4. 增加类UserCaller.cs

    namespace Assignment.Client.DaprClientWeb.V2;public class UserCaller : ServerCallerBase{    public UserCaller(IServiceProvider serviceProvider) : base(serviceProvider)    {    }    /// <summary>    /// 调用服务获取用户信息    /// </summary>    /// <param name="id">用户id</param>    /// <returns></returns>    public Task<UserDto?> GetUserAsync(int id)        => CallerProvider.GetAsync<object, UserDto>("User", new { id = id });    /// <summary>    /// 调用服务增加用户    /// </summary>    /// <param name="userName"></param>    /// <returns></returns>    public Task<string?> AddUserAsync(string userName)        => CallerProvider.PostAsync<object, string>("User", new { Name = userName });}public class UserDto{    public int Id { get; set; }    public string Name { get; set; } = default!;}
  5. 增加环境变量DAPR_GRPC_PORT,值为7007DAPR_HTTP_PORT,值为7008

最初,别离启动Assignment.ServerAssignment.Client.DaprClientWeb.V2服务,浏览器拜访http://localhost:5102/Test/User/Gethttp://localhost:5102/Test/User/Add,别离输入对应的获取用户信息胜利以及创立用户胜利的提醒,则证实调用胜利了

常见问题

在开发中咱们会遇到各种各样的问题,上面就来列举几个咱们我的项目中遇到的问题:

  • 一个我的项目在同一个k8s集群部署了两套环境,为什么会呈现代码调用凌乱(开发环境调用线上环境)?

    在于同一个K8s集群下,dapr会将服务组网,并将它们认为是同一个服务(AppId统一的服务)。
  • 如何解决同一个k8s集群中调用凌乱的问题?

    解决方案有两种:1. 将不同环境下的服务别离部署在不同的K8s集群2. 依据环境调整绝对应服务的dapr sidecar的配置,其`AppId`的命名规定:`AppId`-`环境名`。批改自定义Caller的规定:public abstract class CustomizeDaprCallerBase : DaprCallerBase{    protected CustomizeDaprCallerBase(IServiceProvider serviceProvider) : base(serviceProvider)    {        var hostEnvironment = serviceProvider.GetRequiredService<IWebHostEnvironment>();        if (!hostEnvironment.IsDevelopment() || hostEnvironment.IsStaging())            AppId = AppId + "-" + hostEnvironment.EnvironmentName;    }}
  • 如何批改反对自定义Header?

    目前Caller.Dapr不反对自定义Header,目前只能应用`SendAsync`能力自定义Header,不过此性能曾经在0.5.0的开发计划中,在0.5.0中会反对

总结

应用Masa提供的Caller服务,有助于咱们的我的项目在后期没有应用Dapr的状况下先利用Caller.HttpClient做缓冲,等前期时机成熟,只须要更改绝对应的CallerBase即可,其余代码根本不须要调整,加重了咱们的开发成本,并且不同的Caller依然能够很灵便的调整超时工夫、Header等信息,并且Caller默认提供了解决异样的性能,当调用出错后,会主动抛出异样,让咱们能够更分心的解决业务。

但目前Caller还有不足之处,目前Caller.Dapr版针对申请头解决的并不欠缺,除此之外,目前不反对Content-Type为非Json类型,这块性能会在0.5.0版本中加以反对欠缺

本章源码

Assignment03

https://github.com/zhenlei520...

开源地址

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

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

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

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

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

如果你对咱们的 MASA Framework 感兴趣,无论是代码奉献、应用、提 Issue,欢送分割咱们