天天看点

手把手教你学Dapr - 4. 服务调用

通过使用服务调用,您的应用程序可以使用标准的gRPC或HTTP协议与其他应用程序可靠、安全地通信。

先问几个问题:

如何发现和调用不同服务的方法

如何安全地调用其他服务,并对方法应用访问控制

如何处理重试和瞬态错误

如何使用分布式跟踪指标来查看调用图来诊断生产中的问题

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

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

手把手教你学Dapr - 4. 服务调用

服务A 向服务B发起一个HTTP/gRPC的调用。调用转到了本地的Dapr sidecar

Dapr使用名称解析组件发现服务B的位置

Dapr 将消息转发至服务 B的 Dapr sidecar

注: Dapr sidecar之间的所有调用都通过gRPC来提高性能。 仅服务与 Dapr sidecar之间的调用可以是 HTTP或gRPC

服务B 的 Dapr sidecar将请求转发至服务B 上的特定端点 (或方法) 。 服务B 随后运行其业务逻辑代码

服务B 发送响应给服务A。 响应将转至服务B 的Dapr sidecar

Dapr 转发响应至服务A 的 Dapr sidecar

服务 A 接收响应

默认情况下,调用同一个命名空间的其他服务可以直接使用AppID(假设是:nodeapp)

服务调用也支持跨命名空间调用,在所有受支持的宿主平台上,Dapr AppID遵循FQDN格式,其中包括目标命名空间。

FQDN:(Fully Qualified Domain Name)全限定域名:同时带有主机名和域名的名称。(通过符号“.”) 例如:主机名是bigserver,域名是mycompany.com,那么FQDN就是bigserver.mycompany.com

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

​ 比如.net开发者习惯用 <code>A.B.C</code> 来命名项目,但AppID需要把<code>.</code>换成<code>-</code>且所有单词最好也变成小写 (a-b-c),建议把它变成约定遵守

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

这在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轮着调用

手把手教你学Dapr - 4. 服务调用

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

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

手把手教你学Dapr - 4. 服务调用

创建<code>ASP.NET Core空</code>项目,并修改<code>launchSettings.json</code>,让启动HTTP的启动端口变为5000

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

修改<code>Program.cs</code>文件

此时一共有4个服务

/ :Post方法,打印Hello!

/Hello1:Get方法,打印Hello World1!,返回Hello World1!

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

/Hello2:Post方法,打印Hello World2!

/Hello3:不带后缀表示适配所有方法,打印Hello World3!

运行<code>Assignment.Server</code>:在目录<code>dapr-study-room\Assignment04\Assignment.Server</code>打开命令行工具,并执行下面命令

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

调用服务:再打开一个新的命令行工具,并执行下面命令

可以发现4个命令都调用成功了,但是<code>Assignment.Server</code>输出结果有点意外

是的,没有<code>Hello World1!</code>,那怎么办呢?我们把Hello1的命令改一下

invoke调用的输出除了<code>App invoked successfully</code>以外还多了一行<code>Hello World1!</code>

与此同时<code>Assignment.Server</code>的输出正确了

除此之外<code>invoke</code>还有一些参数,比如<code>--data</code>,<code>--data-file</code>,喜欢研究Dapr CLI的小伙伴可以继续尝试。不过一般情况下用SDK就可以了

创建<code>控制台应用程序</code>项目,使用NuGet包管理器添加<code>Dapr.Client</code> SDK,并修改<code>Program.cs</code>文件

看几个细节

DaprClient是从<code>DaprClinetBuilder</code> Build出来的

还有一种方式使用DaprClient,通过DI

首先都是需要添加<code>Dapr.AspNetCore</code> NuGet包

然后开始有分支了,如果是以前Web API的方式可以在Startup.cs文件<code>ConfigureServices</code>方法加入一行代码

如果使用Minimal API默认是没有Controllers的,那可以在<code>var builder = WebApplication.CreateBuilder(args);</code> 之后加入一行代码

成功的注入进来了,在<code>构造函数</code>或者<code>[FromServices]</code>里愉快的玩耍吧

HttpMethod.Post 的我都没有指定,默认就是Post

HttpMethod.Get的时候,返回值会自动用Json反序列化

不喜欢Json?可以通过 DaprClient.CreateInvokeHttpClient 构造 HttpClient,聪明的你肯定知道后面怎么办了

注:

使用命令行工具打开目录<code>dapr-study-room\Assignment04\Assignment.Client</code>,然后执行命令

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

即便你没有遇到也建议了解一下如何支持非默认端口

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

解决的办法有两种:

修改<code>Assignment.Server</code>启动参数,增加<code>--dapr-http-port 3500</code>,这个方法治标不治本,因为将来我们可能启动多个服务

修改<code>Assignment.Client</code>的环境变量

首先执行<code>dapr list</code>查看端口,以下面为例,HTTP PORT是<code>51460</code>

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

修改<code>Assignment.Client</code>的启动参数,注意把<code>51460</code>换成你自己的端口,使用<code>PowerShell</code>执行下面命令

再执行一次<code>dotnet run</code>就可以看到正确的输出结果了

篇幅太长了,举一反三吧。就是调用<code>InvokeMethodGrpcAsync</code>,然后dapr-http-port换成dapr-grpc-port,DAPR_HTTP_PORT换成DAPR_GRPC_PORT

还记得dapr init的时候docker里有个zipkin吧,通过zipkin可以看一下调用跟踪,通过浏览器打开下面地址

http://localhost:9411/

此时页面是空的

手把手教你学Dapr - 4. 服务调用

根据步骤操作一下就可以看到了

手把手教你学Dapr - 4. 服务调用

随便点开一行数据尾部的SHOW,就可以看到调用详情

手把手教你学Dapr - 4. 服务调用

Assignment04

https://github.com/doddgu/dapr-study-room

我们的目标是<code>自由的</code>、<code>易用的</code>、<code>可塑性强的</code>、<code>功能丰富的</code>、<code>健壮的</code>。

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

原生支持Dapr,且允许将Dapr替换成传统通信方式

架构不限,单体应用、SOA、微服务都支持

支持.Net原生框架,降低学习负担,除特定领域必须引入的概念,坚持不造新轮子

丰富的生态支持,除了框架以外还有组件库、权限中心、配置中心、故障排查中心、报警中心等一系列产品

核心代码库的单元测试覆盖率90%+

开源、免费、社区驱动

还有什么?我们在等你,一起来讨论

经过几个月的生产项目实践,已完成POC,目前正在把之前的积累重构到新的开源项目中

目前源码已开始同步到Github(文档站点在规划中,会慢慢完善起来):

MASA.BuildingBlocks

MASA.Contrib

MASA.Utils

MASA.EShop

BlazorComponent

MASA.Blazor

QQ群:7424099

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

手把手教你学Dapr - 4. 服务调用

转载自:(鬼谷子)