乐趣区

关于c#:手把手教你学Dapr-4-服务调用

介绍

通过应用服务调用,您的应用程序能够应用规范的 gRPC 或 HTTP 协定与其余应用程序牢靠、平安地通信。

为什么不间接用 HttpClientFactory 呢

先问几个问题:

  • 如何发现和调用不同服务的办法
  • 如何平安地调用其余服务,并对办法利用访问控制
  • 如何解决重试和瞬态谬误
  • 如何应用分布式跟踪指标来查看调用图来诊断生产中的问题

此时你会发现这些事件 HttpClientFactory 没有帮你实现,而在微服务中这些又是必不可少的能力,接下来看看服务调用都做了什么

服务调用如何工作的

先看一下两个服务之间的调用程序

  1. 服务 A 向服务 B 发动一个 HTTP/gRPC 的调用。调用转到了本地的 Dapr sidecar
  2. Dapr 应用名称解析组件发现服务 B 的地位
  3. Dapr 将音讯转发至服务 B 的 Dapr sidecar

    : Dapr sidecar 之间的所有调用都通过 gRPC 来进步性能。仅服务与 Dapr sidecar 之间的调用能够是 HTTP 或 gRPC

  4. 服务 B 的 Dapr sidecar 将申请转发至服务 B 上的特定端点 (或办法)。服务 B 随后运行其业务逻辑代码
  5. 服务 B 发送响应给服务 A。响应将转至服务 B 的 Dapr sidecar
  6. Dapr 转发响应至服务 A 的 Dapr sidecar
  7. 服务 A 接管响应

命名空间作用域

默认状况下,调用同一个命名空间的其余服务能够间接应用 AppID(假如是:nodeapp)

localhost:3500/v1.0/invoke/nodeapp/method/neworder

服务调用也反对跨命名空间调用,在所有受反对的宿主平台上,Dapr AppID 遵循 FQDN 格局,其中包含指标命名空间。

FQDN:(Fully Qualified Domain Name)全限定域名:同时带有主机名和域名的名称。(通过符号“.”)

例如:主机名是 bigserver, 域名是 mycompany.com, 那么 FQDN 就是 bigserver.mycompany.com

注:FQDN 是通过符号 . 来拼接域名的,这也就解释了 AppID 为什么不能用符号.,这里不记住的话,应该会有不少小伙伴会踩坑

​ 比方.net 开发者习惯用 A.B.C 来命名我的项目,但 AppID 须要把 . 换成 - 且所有单词最好也变成小写(a-b-c),倡议把它变成约定恪守

比方调用命名空间:production,AppID:nodeapp

localhost:3500/v1.0/invoke/nodeapp.production/method/neworder

这在 K8s 集群中的跨名称空间调用中特地有用

服务间安全性

通过托管平台上的互相 (mTLS) 身份验证,包含通过 Dapr Sentry 服务的主动证书转移,能够确保 Dapr 应用程序之间的所有调用的平安。下图显示了自托管应用程序的状况。

访问控制

应用程序能够管制哪些其余应用程序能够调用它们,以及通过拜访策略受权它们做什么。这使您可能限度具备个人信息的敏感应用程序不被未经受权的应用程序拜访,并联合服务到服务的平安通信,提供了软多租户部署。

具体的访问控制后续章节会介绍

重试

在调用失败和瞬态谬误的状况下,服务调用执行主动重试,并在回退时间段内执行。

注:主动重试,默认是开启的,能够关。但如果不关且业务又不反对幂等是很危险的。倡议服务的接口要设计反对幂等,这在微服务里也是一个标配的抉择。

导致重试的谬误有:

网络谬误,包含端点不可用和回绝连贯。

因为在调用 / 被调用的 Dapr sidecars 上更新证书而导致的身份验证谬误。

每次呼叫重试的回退距离为 1 秒,最多为 3 次。通过 gRPC 与指标 Sidecar 连贯的超时工夫为 5 秒

可插拔的服务发现

Dapr 能够在各种托管平台上运行。为了启用服务发现和服务调用,Dapr 应用可插拔的名称解析组件。例如,K8s 名称解析组件应用 K8s DNS 服务来解析集群中运行的其余应用程序的地位。自托管机器能够应用 mDNS 名称解析组件。Consul 名称解析组件能够在任何托管环境中应用,包含 K8s 或自托管环境

划重点,自托管机器应用 mDNS,在开发环境中前面文章会举荐 VS 上的无缝开发体验,就是基于 mDNS 的

但它有点点小问题,咱们曾经解决了。你只须要像开发一个控制台程序一样,基于 Minimal API 开心的 F5 就能够了

倡议还没有理解 Minimal API 的小伙伴能够钻研起来了,真香

应用 mDNS 进行轮询负载平衡

一图胜千言,就应用 mDNS 轮着调用

可观测性的跟踪和指标

默认状况下,将跟踪应用程序之间的所有调用,并收集指标,以提供应用程序的洞察力和诊断,这在生产场景中尤其重要。这为您提供了服务之间调用的调用图和指标。

服务调用 API 和 gRPC 代理

pythonapp 通过 Dapr sidecar 调用 nodeapp,通过服务调用的 API 及 gRPC 代理仍然是下面见到的那个调用流程,做到了语言无关

应用 HTTP 调用服务

创立 Assignment.Server

创立 ASP.NET Core 空 我的项目,并批改launchSettings.json,让启动 HTTP 的启动端口变为 5000

profiles.Assignment.Server.applicationUrl 的值改为 “https://localhost:6000;http://localhost:5000”

批改 Program.cs 文件

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

app.MapPost("/", () => Console.WriteLine("Hello!"));

app.MapGet("/Hello1", () =>
{Console.WriteLine("Hello World1!");
    return $"\"Hello World1!\"";
});

app.MapPost("/Hello2", () => Console.WriteLine("Hello World2!"));

app.Map("/Hello3", () => Console.WriteLine("Hello World3!"));

app.Run();

此时一共有 4 个服务

  • /:Post 办法,打印 Hello!
  • /Hello1:Get 办法,打印 Hello World1!,返回 Hello World1!

    注:返回的类型要是 Json 字符串,不便 SDK 反序列化

  • /Hello2:Post 办法,打印 Hello World2!
  • /Hello3:不带后缀示意适配所有办法,打印 Hello World3!

先应用 Dapr CLI 来验证一下

运行 Assignment.Server:在目录dapr-study-room\Assignment04\Assignment.Server 关上命令行工具,并执行上面命令

dapr run --app-id assignment-server --app-port 5000 dotnet watch

仔细的小伙伴应该能够发现与上一篇的命令有一点点不同,dontet run 变成了 dotnet watch,这样会开启热重载,不便调试

调用服务:再关上一个新的命令行工具,并执行上面命令

dapr invoke --app-id assignment-server --method /
dapr invoke --app-id assignment-server --method Hello1
dapr invoke --app-id assignment-server --method Hello2
dapr invoke --app-id assignment-server --method Hello3

能够发现 4 个命令都调用胜利了,然而 Assignment.Server 输入后果有点意外

== APP == Hello!
== APP == Hello World2!
== APP == Hello World3!

是的,没有Hello World1!,那怎么办呢?咱们把 Hello1 的命令改一下

dapr invoke --app-id assignment-server --method Hello1 --verb GET

invoke 调用的输入除了 App invoked successfully 以外还多了一行Hello World1!

与此同时 Assignment.Server 的输入正确了

== APP == Hello World1!

除此之外 invoke 还有一些参数,比方--data,--data-file,喜爱钻研 Dapr CLI 的小伙伴能够持续尝试。不过个别状况下用 SDK 就能够了

创立 Assignment.Client

HTTP 服务调用

创立 控制台应用程序 我的项目,应用 NuGet 包管理器增加 Dapr.Client SDK,并批改Program.cs 文件

using Dapr.Client;

var appId = "assignment-server";

var client = new DaprClientBuilder().Build();

await client.InvokeMethodAsync(appId, "/");

var resp = await client.InvokeMethodAsync<string>(HttpMethod.Get, appId, "Hello1");
Console.WriteLine($"Hello1 Response: {resp}");

await client.InvokeMethodAsync(appId, "Hello2");

await client.InvokeMethodAsync(appId, "Hello3");

看几个细节

  • DaprClient 是从DaprClinetBuilder Build 进去的

    还有一种形式应用 DaprClient,通过 DI

    首先都是须要增加Dapr.AspNetCore NuGet 包

    而后开始有分支了,如果是以前 Web API 的形式能够在 Startup.cs 文件 ConfigureServices 办法退出一行代码

    services.AddControllers().AddDapr();

    如果应用 Minimal API 默认是没有 Controllers 的,那能够在var builder = WebApplication.CreateBuilder(args); 之后退出一行代码

    builder.Services.AddDaprClient();

    胜利的注入进来了,在 构造函数 或者 [FromServices] 里欢快的游玩吧

  • HttpMethod.Post 的我都没有指定,默认就是 Post
  • HttpMethod.Get 的时候,返回值会主动用 Json 反序列化

    不喜爱 Json?能够通过 DaprClient.CreateInvokeHttpClient 结构 HttpClient,聪慧的你必定晓得前面怎么办了

注:

1. Minimal API 虽香,但新,所以不是所有性能都反对,比方从参数中间接映射状态治理,要等 Minimal API 反对 Model Binder 当前且 SDK 也同步反对了才能够
2. DaprClient 是 TCP 的,也是线程平安的,能够大胆的复用,如果不必 DI 的话不须要频繁构建 DaprClient


验证调用胜利

应用命令行工具关上目录dapr-study-room\Assignment04\Assignment.Client,而后执行命令

dotnet run

如果你不是用 VS Code 终端的 PowerShell 执行 dapr run 就可能遇到上面的谬误

即使你没有遇到也倡议理解一下如何反对非默认端口

An exception occurred while invoking method: '/' on app-id: 'assignment-server'
 ---> System.Net.Http.HttpRequestException: 因为指标计算机踊跃回绝,无奈连贯。(127.0.0.1:3500)
 ---> System.Net.Sockets.SocketException (10061): 因为指标计算机踊跃回绝,无奈连贯。

因为下面应用 dapr run 的时候没有指定 dapr http port,而默认 client 拜访的是 3500 端口

解决的方法有两种:

  1. 批改 Assignment.Server 启动参数,减少--dapr-http-port 3500,这个办法治标不治本,因为未来咱们可能启动多个服务

    dapr run --app-id assignment-server --app-port 5000 --dapr-http-port 3500 dotnet watch
  2. 批改 Assignment.Client 的环境变量

    首先执行 dapr list 查看端口,以上面为例,HTTP PORT 是51460

    APP ID HTTP PORT GRPC PORT APP PORT COMMAND AGE CREATED PID

    assignment-server 51460 51461 5000 dotnet watch 7s 2021-10-29 14:13.49 11676

    批改 Assignment.Client 的启动参数,留神把 51460 换成你本人的端口,应用 PowerShell 执行上面命令

    $Env:DAPR_HTTP_PORT = 51460
    dotnet run

再执行一次 dotnet run 就能够看到正确的输入后果了

Hello1 Response: Hello World1!

gRPC 服务调用

篇幅太长了,触类旁通吧。就是调用InvokeMethodGrpcAsync,而后 dapr-http-port 换成 dapr-grpc-port,DAPR_HTTP_PORT 换成 DAPR_GRPC_PORT

查看跟踪

还记得 dapr init 的时候 docker 里有个 zipkin 吧,通过 zipkin 能够看一下调用跟踪,通过浏览器关上上面地址

http://localhost:9411/

此时页面是空的

依据步骤操作一下就能够看到了

轻易点开一行数据尾部的 SHOW,就能够看到调用详情

本章源码

Assignment04

https://github.com/doddgu/dap…

咱们正在口头,新的框架、新的生态

咱们的指标是 自在的 易用的 可塑性强的 功能丰富的 强壮的

所以咱们借鉴 Building blocks 的设计理念,正在做一个新的框架MASA Framework,它有哪些特点呢?

  • 原生反对 Dapr,且容许将 Dapr 替换成传统通信形式
  • 架构不限,单体利用、SOA、微服务都反对
  • 反对.Net 原生框架,升高学习累赘,除特定畛域必须引入的概念,保持不造新轮子
  • 丰盛的生态反对,除了框架以外还有组件库、权限核心、配置核心、故障排查核心、报警核心等一系列产品
  • 外围代码库的单元测试覆盖率 90%+
  • 开源、收费、社区驱动
  • 还有什么?咱们在等你,一起来探讨

通过几个月的生产我的项目实际,已实现 POC,目前正在把之前的积攒重构到新的开源我的项目中

目前源码已开始同步到 Github(文档站点在布局中,会缓缓欠缺起来):

MASA.BuildingBlocks

MASA.Contrib

MASA.Utils

MASA.EShop

BlazorComponent

MASA.Blazor

QQ 群:7424099

微信群:加技术经营微信(MasaStackTechOps),备注来意,邀请进群

转载自:(鬼谷子)

退出移动版