前言
上一篇咱们讲了应用 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,欢送分割咱们