.NET 7 轻松上手Dapr之服务调用

前言

对于Dapr ,在项目中也有用过一段时间,优缺点并存,但是瑕不掩瑜,目前随着版本的迭代和第三方团队对它的支持也使得我们用得更加得心应手,所以借此也回顾一下Dapr的相关知识以及分享一下项目中用到的第三方库MASA.Framework:https://www.masastack.com 对Dapr的完美支持。

什么是Dapr?

Dapr 是 Distributed Application Runtime (分布式应用运行时)的缩写。.

Dapr是一种可移植的,serverless的,事件驱动的运行时,它使开发人员可以轻松构建弹性,无状态和有状态微服务,这些服务运行在云和边缘上,并包含多种语言和开发框架。

Dapr 的概念模型图:

.NET 7 轻松上手Dapr之服务调用

官方介绍:https://docs.dapr.io/zh-hans

Dapr 环境配置

网上对于dapr自托管模式下的环境配置的教程也比较多了,所以这里就只简单介绍介绍几个需要注意的地方。

首先在安装Dapr之前你或许需要能够进行科学的上网,如果发现冲浪速度不理想的话,那就或许需要在夜深人静的时候偷波塔了,当然你也可以选择离线安装,也比较简单,相信聪明的你们都能够一一搞定。

安装 Dapr CLI

执行命令:

powershell -Command "iwr -useb https://raw.githubusercontent.com/dapr/cli/master/install/install.ps1 | iex"

此命令会安装最新的 windows Dapr cli 并将$Env:SystemDrive\dapr此目录添加到用户 PATH 环境变量

然后通过重新启动终端/命令提示符并运行 dapr 命令来验证 CLI 是否已安装:

dapr

.NET 7 轻松上手Dapr之服务调用

也可以在C盘和系统环境变量中查看验证

.NET 7 轻松上手Dapr之服务调用

详细步骤可以参考 安装 Dapr CLI:https://docs.dapr.io/getting-started/install-dapr-cli/

安装 Docker Desktop

然后因为Dapr CLI默认会在Docker内启动 redis、zipkin、placement。所以我们可以安装个Docker Desktop来增加dapr的体验性。安装完成后默认开启WSL2。

.NET 7 轻松上手Dapr之服务调用

详细步骤可以参考 安装 Docker Desktop:https://docs.docker.com/get-docker/

初始化 Dapr

初始化dapr后,我们可以

在本地获取并安装 Dapr sidecar 二进制文件。

使用 Dapr 创建一个简化应用程序开发的开发环境。

Dapr初始化包括:

运行Redis 容器实例以用作本地状态存储和消息代理。

运行Zipkin 容器实例以实现可观察性。

使用上述组件定义创建默认组件文件夹。

运行Dapr 放置服务容器实例以支持本地参与者。

首先我们如果只使用dapr的服务调用的话,就可以只安装精简版

dapr init --slim

如果想体验dapr完整功能支持的话,可以执行

dapr init

这里会从外网上拉取一些二进制文件,如果网络不好的话可能需要等待一段时间,如果长时间未能完成或出现网络相关错误的话,可以多尝试几次或者选择离线安装。

离线安装这里稍微介绍:

执行上述dapr初始化命令后,无论最后是否成功,都会在C:\Users\Administrator.dapr生成一些文件 如:

.NET 7 轻松上手Dapr之服务调用

然后如果最后失败的话,可能会导致bin文件中拉取的内容不完整。正常情况是这样:

.NET 7 轻松上手Dapr之服务调用

所以我们离线安装的话,可以先使用命令

Dapr uninstall //删除bin文件夹 (这里选择此命令)
Dapr uninstall --all //删除 C:\Users\Administrator\.dapr 

就可以自己去dapr 的https://github.com/dapr/cli/releases上下载对应版本的文件压缩包,然后把文件放入bin文件夹中即可。一般情况下,会自动解压缩。

  • dashboard_windows_amd64.zip
  • daprd_windows_amd64.zip

安装完成后可以执行命令验证:

dapr -v

.NET 7 轻松上手Dapr之服务调用

详细步骤可以参考初始化 Daprhttps://docs.dapr.io/getting-started/install-dapr-selfhost/

项目准备

  • dotNet 7
  • Docker Desktop
  • Visual Studio 2022
  • Dapr

项目搭建

我们先准备一个客户端项目-DaprClientWeb与两个服务端项目-ServiceAServiceB

.NET 7 轻松上手Dapr之服务调用

然后先在两个服务端项目中分别增加一个测试接口

ServiceA 项目示例

.NET 7 轻松上手Dapr之服务调用

接下来我们先用dapr cli 请求接口验证一下环境可行性

使用命令行工具,跳转到ServiceA的源码目录,执行命令:

 dapr run --app-id service-a --app-port 5001 dotnet run

这个命令会调用基础 Dapr 运行时,并使应用程序和 Dapr sidecar一起运行

.NET 7 轻松上手Dapr之服务调用

然后输入以下命令查看 Dapr sidecar是否启动成功:

dapr list

最后接着输入以下命令访问接口:

dapr invoke --app-id service-a --method GetServiceA --verb GET

OK,环境到此验证完毕,项目也基本上搭建完成,下面会借助客户端项目-DaprClientWeb 通过Dapr .Net SDK来分别请求ServiceA与ServiceB的接口 演示Dapr的服务调用。

Dapr 服务调用

Dapr 服务调用的工作原理

.NET 7 轻松上手Dapr之服务调用

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

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

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

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

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

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

7、服务 A 接收响应

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

注:Dapr sidecar使用可插入的名称解析组件来解析服务 B 的地址。

在自托管模式下,Dapr 使用 mdns:https://www.ionos.com/digitalguide/server/know-how/multicast-dns/)来查找它。

在 Kubernetes 模式下运行时,由 Kubernetes DNS 服务决定地址。

关于自托管模式下的mDNS:

.NET 7 轻松上手Dapr之服务调用

综上我们可以得知:

Dapr是通过向每个计算单元注入了一个Sidecar容器/进程,然后运用Sidecar与事件触发器进行交互,并通过标准HTTP或gRPC协议与计算单元进行通信的。

项目实战

我们在DaprClientWeb项目中增加两个接口分别用来请求ServiceA服务的GetServiceA接口与ServiceB服务的GetServiceB

同时需要在DaprClientWeb项目中引入Dapr.Client Nuget包

代码:

.NET 7 轻松上手Dapr之服务调用

注意:此处DaprClient是从DaprClinetBuilder Build出来的

ServiceA

.NET 7 轻松上手Dapr之服务调用

ServiceB

.NET 7 轻松上手Dapr之服务调用

执行命令:

 dapr run --app-id service-a --app-port 5001 dotnet run
 dapr run --app-id service-b --app-port 5002 dotnet run
 dapr run --app-id dapr-client-web --app-port 5003 dotnet run

查看效果:

.NET 7 轻松上手Dapr之服务调用

然后我们通过DaprClientWeb项目 请求接口

.NET 7 轻松上手Dapr之服务调用

到这里我们已经可以使用dapr进行服务之间的通信了。

但是每次都需要通过dapr run 命令启动dapr sidecar这样岂不是太不优雅了,其中还包括几个APPID,DAPR_HTTP_PORT,AppPort,DAPR_GRPC_PORT需要管理,到时候服务一多肯定会十分头疼。其实这些问题都已经被一些大佬解决了,比如MASA团队就为此提供了很好地支持,我们只需在我们的项目中引入一个包就甚至可以通过一行代码就能够让项目轻松的使用Dapr了。

MASA DaprStarter

首先我们先在项目中引入 Masa.Contrib.Development.DaprStarter.AspNetCore

当前我用的版本是1.0.0-preview.22并且都在一直更新,还是比较稳定的,听说他们有全职的开源团队在维护与迭代,所以我们可以放心使用。

然后在各自项目的Program.cs中增加一行代码就可以了

builder.Services.AddDaprStarter(builder.Configuration.GetSection("DaprOptions"));

DaprClientWeb 示例:

.NET 7 轻松上手Dapr之服务调用

当然需要在appsettings.Development.json文件中加入配置

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "DaprOptions": {
    "AppId": "service-a",//不指定的话会自动根据AppId + AppIdDelimiter('-') + AppIdSuffix 规则生成
    "AppPort": 5001,
    "AppIdSuffix": "",//当前机器网卡地址
    "DaprHttpPort": 8082,
    "DaprGrpcPort": 8083
  }
}

最后我们就只需直接启动项目就可以了,其他的就不用操心了。

看看效果:

.NET 7 轻松上手Dapr之服务调用

细心的同学会发现这几个端口都变成我们在项目appsettings.Development.json 文件中配置的了。

然后这里需要注意的是,这种用法只是在自托管模式下方便与本地开发调试使用,在生产环境上有基于k8s的另外一套用法,这里就不做多概述,感兴趣的同学可自行研究。

如果想了解 Masa.Contrib.Development.DaprStarter.AspNetCore 这个包的到底帮我们做了那些工作,可以去看看大佬的文章一行代码让你的项目轻松使用Dapr:https://www.cnblogs.com/zhenlei520/p/16157625.html

到此,基于dapr的服务调用已经差不多大功告成了,如果MASA的包用的爽了,记得去GitHub:https://github.com/masastackStar 一下。

结尾

由于文章篇幅有限,涉及到知识内容也不是很深入,感兴趣的同学可以自行研究。然后本文都是基于我的个人理解,然后也有参考官网以及大佬的文章和视频,文章如有什么不妥的地方欢迎指正,共同进步。