前言
上一篇咱们讲了应用HttpClient的形式调用,那么如果咱们当初须要更换为通过dapr实现服务调用,咱们须要做哪些事件呢?
Caller.Dapr 入门
如果咱们的我的项目本来应用的是Caller.HttpClient,当初心愿改为应用Caller.Dapr,那么咱们须要做什么呢?
- 革新Caller 服务调用 - HttpClient的中的服务端,使得服务端反对dapr调用
- 调整客户端代码,使客户端反对通过dapr来做到服务调用,并达到与HttpClient调用雷同的后果
筹备工作
- 装置.Net 6.0
- 创立ASP.NET Core 空白解决方案
Assignment03
- 将
Assignment02
文件夹下的Assignment.Server
复制到Assignment03
的文件夹下,而后将我的项目Assignment.Server
增加到解决方案Assignment03
中 选中
Assignment.Server
并装置Masa.Utils.Development.Dapr.AspNetCore
dotnet add package Masa.Utils.Development.Dapr.AspNetCore --version 0.4.0-rc1
批改
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 sidecarQ: 为什么要指定AppId、DaprGrpcPort、DaprHttpPort等信息?
A: 客户端调用须要失去Dapr的AppId、设置DaprGrpcPort、DaprHttpPort是因为客户端演示我的项目没有应用dapr sidecar,如果客户端我的项目也应用dapr sidecar,此处能够不指定DaprGrpcPort、DaprHttpPort,更多信息请参考文章创立ASP.NET Core 空我的项目
Assignment.Client.DaprClientWeb
作为客户端并装置Masa.Utils.Caller.DaprClient
dotnet add package Masa.Utils.Caller.DaprClient --version 0.4.0-rc1
批改
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.HttpClientWeb
,Assignment.Client.DaprClientWeb
仅仅是更改了Program.cs
,将UseHttpClient
改为UseDapr
,其余代码无需批改增加环境变量
DAPR_GRPC_PORT
,值为7007
、DAPR_HTTP_PORT
,值为7008
Q: 为什么要增加环境变量?
A: 因为以后客户端并未应用dapr sidecar,若以后客户端也应用dapr sidecar,此处能够不增加环境变量
当初Caller的HttpClient版本就能够应用了,别离启动Assignment.Server
、Assignment.Client.DaprClientWeb
服务,浏览器拜访http://localhost:5042/Test/User/Get
、http://localhost:5042/Test/User/Add
,别离输入对应的获取用户信息胜利以及创立用户胜利的提醒,则证实调用胜利了
DaprClient 最佳实际
Assignment.Client.DaprClientWeb
的写法比较简单,其用法与Assignment.Client.HttpClientWeb
基本一致,与Caller.HttpClient相似,DaprClient咱们举荐应用上面的写法:
- 创立ASP.NET Core 空我的项目
Assignment.Client.DaprClientWeb.V2
作为调用方V2版本 选中
Assignment.Client.DaprClientWeb.V2
并装置Masa.Utils.Caller.DaprClient
dotnet add package Masa.Utils.Caller.DaprClient --version 0.4.0-rc1
增加类
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) { }}
增加类
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!;}
- 增加环境变量
DAPR_GRPC_PORT
,值为7007
、DAPR_HTTP_PORT
,值为7008
最初,别离启动Assignment.Server
、Assignment.Client.DaprClientWeb.V2
服务,浏览器拜访http://localhost:5102/Test/User/Get
、http://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,欢送分割咱们