【Dapr】| 总结/Edison Zhou


分布式应用运行时Dapr目前已经发布了1.1.0版本,阿里云也在积极地为Dapr贡献代码和落地实践。作为一名开发者,自然也想玩一玩,看看Dapr带来的新“视”界到底是怎么样的。

1关于Dapr

Dapr(Distributed Application Runtime)是一个开源、可移植、事件驱动的运行时。它使开发人员能够轻松地构建运行在云平台和边缘的弹性而微服务化的应用程序,无论是无状态还是有状态。Dapr 让开发人员能够专注于编写业务逻辑,而不是解决分布式系统的挑战,从而显著提高生产力并减少开发时间。此外,Dapr 也降低了大部分中小型企业基于微服务架构构建现代云原生应用的准入门槛。

Dapr 的核心构建模块 (或者说核心功能)如下:

  • 服务调用: 弹性服务与服务之间(service-to-service)调用可以在远程服务上启用方法调用,包括重试,无论远程服务在受支持的托管环境中运行在何处。

  • 状态管理:通过对键 / 值对的状态管理,可以很容易编写长时间运行、高可用性的有状态服务,以及同一个应用中的无状态服务。状态存储是可插入的,并且可以包括 Azure Cosmos 或 Redis,以及组件路线图上的其他组件,如 AWS DynamoDB 等。

  • 在服务之间发布和订阅消息(Pub/Sub):使事件驱动的架构能够简化水平可扩展性,并使其具备故障恢复能力。

  • 事件驱动的资源绑定:资源绑定和触发器在事件驱动的架构上进一步构建,通过从任何外部资源(如数据库、队列、文件系统、blob 存储、webhooks 等)接收和发送事件,从而实现可扩展性和弹性。例如,你的代码可以由 Azure EventHub 服务上的消息触发,并将数据写入 Azure CosmosDB。

  • 虚拟角色:无状态和有状态对象的模式,通过方法和状态封装使并发变得简单。Dapr 在其虚拟角色(Virtual Actors)运行时提供了许多功能,包括并发、状态、角色激活 / 停用的生命周期管理以及用于唤醒角色的计时器和提醒。

  • 服务之间的分布式跟踪:使用 W3C 跟踪上下文(W3C Trace Context)标准,轻松诊断和观察生产中的服务间调用,并将事件推送到跟踪和监视系统。

目前Dapr提供了如下所示的主流语言的SDK:

更多关于Dapr的介绍不是本文的重点,有兴趣的读者可以移步阅读:

(1)阿里巴巴的Dapr实践与探索

(2)Dapr是否会引领云原生中间件的未来

(3)分布式运行时 Dapr 知多少

本文的试玩会主要集中在服务调用(service invocation)和 发布订阅(pub / sub)上面,并且只会在入门小DEMO的程度,期望值过高的童鞋可以自行学习 或 绕道行走,毕竟我的时间也有限。

2准备工作

一台Linux虚拟机

为了后面的DEMO,在VMware Workstation中准备一个Linux虚拟机环境,这里我选择的是CentOS 7.6。

在此虚拟机中设定静态IP地址(本示例为 192.168.2.100),关闭防火墙,设定主机名等一系列基本操作。

安装.NET 5 SDK

这里我的DEMO是基于local-host部署模式(也可以选择Kubernetes模式部署,但我没时间弄),因此给Linux安装一下.NET 5 SDK,命令如下:

添加受信源
sudo rpm -Uvh https://packages.microsoft.com/config/centos/7/packages-microsoft-prod.rpm
安装.NET 5 SDK
sudo yum install dotnet-sdk-5.0

安装Dapr CLI

官网提示直接在Linux下执行以下命令就可以将Dapr CLI下载到/usr/local/bin目录下:

wget -q https://raw.githubusercontent.com/dapr/cli/master/install/install.sh -O - | /bin/bash

不过由于网络原因,我选择了直接下载Release来安装:

(1)到github上下载1.1.0的release压缩包(dapr_linux_amd64.tar.gz),并将其传到Linux中。

(2)解压该压缩包,并将解压后的目录移动到/usr/local/bin目录下:

tar -zvxf dapr_linux_amd64.tar.gz

(3)通过输入 dapr 来验证是否安装成功:

此外,也可以通过 dapr --version 查看Dapr版本:

CLI version: 1.1.0
Runtime version: 1.1.0

初始化Dapr

安装好Dapr CLI之后,就可以在Linux上初始化Dapr了,命令如下:

dapr init

这个命令会帮你做一些列的事情,包括但不限于 拉取一波docker镜像 & 运行一波docker容器,如下图所示:

可以看到,dapr, redis, zipkin都已经运行起来了。

为什么有redis?因为它会作为默认的pub/sub中间件为dapr提供具体的实现能力。

为什么会有zipkin?因为它会作为默认的tracing中间件为我们提供链路追踪的能力。

OK,到此为止,本地的Dapr运行时基础环境已基本就绪。

3.NET 5 应用集成Dapr SDK

准备三个.NET WebAPI

这里我们准备了三个WebAPI项目,分别是订单服务、购物车服务 以及 商品服务。

具体的代码可以去github上查看,github地址为:。

为所有WebAPI项目添加集成

为所有项目添加Dapr SDK的nuget包,这里是 Dapr.AspNetCore 组件。

为所有WebAPI项目注册Dapr

在StartUp类中,对Dapr Client进行注册,这里的AddDapr背后的操作其实就是给IoC容器注入了一个单例的DaprClient对象。

public void ConfigureServices(IServiceCollection services)
{services.AddControllers().AddDapr();......
}

4服务调用示例

这里假设CartService要和ProductService进行通信,通过REST获取商品数据。这里,就可以借助Dapr提供的服务间调用的功能进行通信。其工作原理如下图所示:

这里使用的方式是通过DaprClient直接InvokeMethod进行服务间的通信,传递了两个重要的参数,一个是依赖服务的app-id(根据你部署时设定的名字来写),另一个是依赖接口的route。

具体如下代码所示:

[ApiController]
[Route("[controller]")]
public class CartController : ControllerBase
{private readonly ILogger<CartController> _logger;private readonly DaprClient _daprClient;public CartController(ILogger<CartController> logger, DaprClient daprClient){_logger = logger;_daprClient = daprClient;}[HttpGet]public async Task<IEnumerable<SKU>> Get(){_logger.LogInformation("[Begin] Query product data from Product Service");var products = await _daprClient.InvokeMethodAsync<IEnumerable<SKU>>(HttpMethod.Get, "ProductService", "Product");_logger.LogInformation($"[End] Query product data from Product Service, data : {products.ToArray().ToString()}");return products;}
}

这里对应ProductService的接口默认返回一些假数据:

[ApiController]
[Route("[controller]")]
public class ProductController : ControllerBase
{private static readonly string[] FakeProducts = new[]{"SKU1", "SKU2", "SKU3", "SKU4", "SKU5", "SKU6", "SKU7", "SKU8", "SKU9", "SKU10"};......[HttpGet]public IEnumerable<SKU> Get(){_logger.LogInformation("[Begin] Query product data.");var rng = new Random();var result = Enumerable.Range(1, 5).Select(index => new SKU{Date = DateTime.Now.AddDays(index),Index = rng.Next(1, 100),Summary = FakeProducts[rng.Next(FakeProducts.Length)]}).ToArray();_logger.LogInformation("[End] Query product data.");return result;}
}

然后,将这两个服务发布到Linux服务器上,当然,我们要通过dapr来部署,让.net application和dapr sidecar形成一体。

部署命令如下所示,可以看到我们既要为.net application指定端口,也要为dapr sidecar指定端口(这里主要为dapr指定了http端口,也可以为其指定grpc端口)。

dapr run --app-id CartService --app-port 5000 --dapr-http-port 5005 -- dotnet EDT.EMall.Cart.API.dll --urls "http://*:5000"
dapr run --app-id ProductService --app-port 5010 --dapr-http-port 5015 -- dotnet EDT.EMall.Product.API.dll --urls "http://*:5010"

你会发现,当你run成功之后,会看到以下log,其中既有dapr的log,也有.net application的log,虽然他们是两个应用程序,但是你看到的它们是一体的。

最后,通过swagger来测试一下,结果如下,成功进行了服务调用。

5消息发布及订阅示例

发布订阅模式(Publish-Subscribe)是众所周知且广泛使用的消息模式。这里我们假设OrderService的某个接口完成后就发布一个消息,告知订阅方有新订单的事件产生。

在Dapr中其工作原理如下图所示:

具体代码示例如下,借助DaprClient的PublishEvent接口实现消息发布:

[ApiController]
[Route("[controller]")]
public class OrderController : ControllerBase
{private const string DaprPubSubName = "pubsub";private readonly ILogger<OrderController> _logger;private readonly DaprClient _daprClient;public OrderController(ILogger<OrderController> logger, DaprClient daprClient){_logger = logger;_daprClient = daprClient;}[HttpPost]public async Task<Models.Order> Post(OrderDto orderDto){_logger.LogInformation("[Begin] Create Order.");var order = new Models.Order(){// some mappingId = orderDto.Id,ProductId = orderDto.ProductId,Count = orderDto.Count};// some other logic for ordervar orderStockDto = new OrderStockDto(){ProductId = orderDto.ProductId,Count = orderDto.Count};await _daprClient.PublishEventAsync(DaprPubSubName, "neworder", orderStockDto);_logger.LogInformation($"[End] Create Order Finished. Id : {orderStockDto.ProductId}, Count : {orderStockDto.Count}");return order;}
}

假设ProductService作为订阅方,需要消费这个事件,并扣减某个商品的库存。而基于Dapr,我们需要对ProductService添加一点配置:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{......app.UseCloudEvents(); // 标准化的消息传递格式app.UseEndpoints(endpoints =>{endpoints.MapSubscribeHandler(); // 订阅消费处理......});
}

然后,在ProductService中添加一个方法/接口 来作为订阅处理。

具体代码示例如下,需要注意的就是:

(1)作为消息处理接口,需要指定为HttpPost方式。

(2)需要指定Topic特性,并标注pubsubname 和 事件名。

private const string DaprPubSubName = "pubsub";[HttpPost]
[Topic(DaprPubSubName, "neworder")]
public Models.Product SubProductStock(OrderStockDto orderStockDto)
{_logger.LogInformation($"[Begin] Sub Product Stock, Stock Need : {orderStockDto.Count}.");var product = _productService.GetProductById(orderStockDto.ProductId);if (orderStockDto.Count < 0 || orderStockDto.Count > product.Stock){throw new InvalidOperationException("Invalid Product Count!");}product.Stock = product.Stock - orderStockDto.Count;_productService.SaveProduct(product);_logger.LogInformation($"[End] Sub Product Stock Finished, Stock Now : {product.Stock}.");return product;
}

这里的DaprPubSubName是pubsub,这是因为Dapr默认的pubsub实现是基于Redis的,而在配置中为Redis设置的name就是 pubsub,因此对于我们入门的话,就不要去更改,或者和配置中的name保持一致。

[root@dapr-lab-server ~]# cat ~/.dapr/components/pubsub.yaml
apiVersion: dapr.io/v1alpha1
kind: Component
metadata:name: pubsub
spec:type: pubsub.redismetadata:- name: redisHostvalue: localhost:6379- name: redisPasswordvalue: ""

当然,我们也可以将默认的pubsub实现Redis换为熟悉的RabbitMQ。我们只需要更改上面的yml文件内容如下:

apiVersion: dapr.io/v1alpha1
kind: Component
metadata:name: pubsub-rq
spec:type: pubsub.rabbitmqversion: v1metadata:- name: hostvalue: "amqp://localhost:5672"- name: durablevalue: true

然后,将这两个服务发布到Linux服务器上,当然,我们要通过dapr来部署,让.net application和dapr sidecar形成一体。

dapr run --app-id OrderService --app-port 5020 --dapr-http-port 5025 -- dotnet EDT.EMall.Order.API.dll --urls "http://*:5020"
dapr run --app-id ProductService --app-port 5010 --dapr-http-port 5015 -- dotnet EDT.EMall.Product.API.dll --urls "http://*:5010"

run成功后,通过 dapr list 查看,可以看到三个服务都已经启动起来了,它们是三个由.net application + dapr sidecar 组成的“合体应用”。

最后,我们通过swagger来测试一下,测试结果如下图所示:

(1)OrderService:

(2)ProductService:

这里的99其实是假总库存100 - 消息传递过来的商品数量得到的,具体可以参考代码示例。

6小结

本文总结了我试玩Dapr的一些经过,包括Dapr的Local环境搭建、.NET 5 Application与Dapr的集成 和 两个具体场景的小DEMO(服务调用 和 Pub/Sub)。

这里借助知乎上 iyacontrol 童鞋的评论(来源:https://www.zhihu.com/question/351298264),作为结尾:

Dapr 本身是一种 Sidecar 模式(虽然Dapr也提供了SDK,但是个人认为这并不是Dapr以后的发展方向)。Sidecar 模式的意义在于, 解耦了基础设施和核心业务

简单来看,Dapr的意义在于:

  • 对于小公司,甚至没有基础架构和中间件团队的公司,Dapr 提供了开箱即用的基础设施功能,可以让小公司轻松构建弹性,分布式应用

  • 对于中等单位,具备一定的基础架构能力,在使用Dapr的过程中,可能Dapr并不能完全满足需求,那么也可以在Dapr框架体系下,花费较小的成本进行自定义扩展

  • 对于大公司,Dapr 提供了一种思路。相信基础架构团队会越来越倾向于通过交付Sidecar的形式来提供基础设施

长远来看,Dapr背后的架构模式是符合未来架构趋势(多运行时架构)和云原生发展趋势的

代码示例

github:https://github.com/EdisonChou/EDT.Dapr.Sample

参考资料

Microsoft,《Dapr for .NET Developer》: https://docs.microsoft.com/zh-cn/dotnet/architecture/dapr-for-net-developers

Tony,《Dapr公开课》:https://www.bilibili.com/video/BV1Fb4y197fT

相关文章:

  • Dapr能否引领云原生中间件的未来?

  • 云原生 | 阿里巴巴的Dapr实践与探索

  • Dapr 可视化指南

  • Dapr 知多少 | 分布式应用运行时

  • Dapr 正式发布 1.0

  • Dapr 交通流量控制示例

  • Dapr是如何简化微服务的开发和部署

  • 微软开源微服务运行时Dapr,赋能云原生应用开发

  • Dapr微服务应用开发系列0:概述

  • Dapr微服务应用开发系列1:环境配置

  • Dapr微服务应用开发系列2:Hello World与SDK初接触

  • Dapr微服务应用开发系列3:服务调用构件块

  • Dapr微服务应用开发系列4:状态管理构件块

  • Dapr微服务应用开发系列5:发布订阅构建块

  • Windows环境下Dapr入门

  • 通过Dapr实现一个简单的基于.net的微服务电商系统

云原生 | .NET 5 with Dapr 初体验相关推荐

  1. 云原生 CI/CD 框架 Tekton 初体验

    Tekton 是一款功能非常强大而灵活的 CI/CD 开源的云原生框架.Tekton 的前身是 Knative 项目的 build-pipeline 项目,这个项目是为了给 build 模块增加 pi ...

  2. 华为云人脸识别服务 FRS 之初体验

    华为云人脸识别服务 FRS 之初体验 程序之美 前言 操作流程 所遇问题 结束语 程序之美 前言 人脸识别服务(Face Recognition Service,简称FRS),是基于人的脸部特征信息, ...

  3. 数跑科技联合阿里云创造基于云原生的无边界数字新体验

    简介:引入阿里业务中台理念和技术框架,通过数字化渠道重构,建立以业务中台为基础,围绕单个客户的消费决策周期模型,构建数字化任务工单系统,驱动多部门.多工种协作,提升企业线索采集.商机挖掘.潜客培育.销 ...

  4. 双11特刊|购物车实时显示到手价,看云原生内存数据库Tair如何提升用户体验?

    阿里云自研内存数据库Tair诞生于2009年,是一种支持高并发低延迟访问的云原生内存数据库,完全兼容Redis,已历经多年双11大促考验,提供核心在线访问加速能力,显著提升系统吞吐量. 作为双11大促 ...

  5. 云原生分布式应用运行时 Dapr 在阿里的实践

    Dapr 是什么? Dapr是一个开源.可移植.事件驱动的云原生分布式应用运行时,它使开发人员能够轻松地构建运行在云平台和边缘的弹性而微服务化的无状态和有状态的应用程序,从而降低基于微服务架构构建现代 ...

  6. 乘风破浪,.Net Core遇见Dapr,为云原生而生的分布式应用运行时

    Dapr是一个由微软主导的云原生开源项目,国内云计算巨头阿里云也积极参与其中,2019年10月首次发布,到今年2月正式发布V1.0版本.在不到一年半的时间内,github star数达到了1.2万,超 ...

  7. 云原生CI/CD框架Tekton国内部署方式

    Tekton 是一款功能非常强大而灵活的 CI/CD 开源的云原生框架.致力于提供全功能.标准化的云原生 CI/CD 解决方案.[本文主要是通过流水线自动化的将tekton镜像同步到腾讯云仓库,并部署 ...

  8. 一年增加1.2w星,Dapr能否引领云原生中间件的未来?

    作者 | 敖小剑 Dapr 将引领云原生时代应用和中间件的未来. Dapr 是由微软发起的云原生开源新项目,在今年 2 月份刚刚发布了 v1.0 正式版本.虽然推出至今不过一年半时间,但 Dapr 发 ...

  9. Dapr 在阿里云原生的实践

    简介:Faas 场景下,比较吸引用户的是成本和研发效率,成本主要通过按需分配和极致的弹性效率来达成.而应用开发者期望通过 FaaS 提供多语言的编程环境,提升研发效率,包括启动时间.发布时间.开发的效 ...

最新文章

  1. task_struct源码
  2. PHP 的 cURL库快速入门文档
  3. 一款App基于mPaaS小程序如何进行改造?
  4. 电脑word在哪_word是什么?小学生:单词,大学生:论文排版工具
  5. 一文看懂高可用:异地多活
  6. 解决Linux中crontab不执行ntpdate问题
  7. 根据html元素的类型设置元素的值
  8. 加拿大第二大行TD Bank是如何践行科技战略的?
  9. JavaScript基础知识(二)
  10. 零基础如何学习 iOS 开发?
  11. 从OpenGL ES 2.0到Direct3D 11.1之路
  12. Wireshark实战分析之UDP协议
  13. eviews安装教程
  14. Unity镜头特写效果
  15. 最新web/java/jsp实现发送手机短信验证码和邮箱验证码的注册登录功能(详细)
  16. 漏洞复现之CVE-2018-1273 Spring Data Commons 远程命令执行
  17. c语言字符串删掉小写字母
  18. 【转】利用Windows API调用摄像头
  19. Qt QList详解
  20. 系统中断服务器,windows7资源管理器中有一个 系统中断 描述为延迟过程调用和中断服务例程__这是安全的吗,windows7的系统进程吗...

热门文章

  1. 深入浅出理解索引结构
  2. matlab 规范,matlab-代码-规范
  3. [BZOJ4182]Shopping
  4. SQL Server在更改计算机名后的设置
  5. [tools]notepad++当前文件路径不是工作路径
  6. Managing Gigabytes--文本压缩
  7. 百度家电行业报告摘录
  8. plex 乱码_Plex Media Center现在支持播客
  9. keep-alive使用_如何使用Google Keep进行无忧笔记
  10. 框架基础:深入理解Java注解类型(@Annotation)