介绍

使用状态管理,您的应用程序可以将数据作为键/值对存储在支持的状态存储中。

您的应用程序可以使用 Dapr 的状态管理 API 使用状态存储组件来保存和读取键/值对,如下图所示。例如,通过使用 HTTP POST,您可以保存键/值对,通过使用 HTTP GET,您可以读取键并返回其值。

特性

可插拔状态存储

Dapr 数据存储被建模为组件,可以在不更改代码的情况下更换它。例如:MySQL、Redis、Azure CosmosDB等。

可配置的状态存储行为

Dapr 允许开发人员将额外的元数据附加到状态操作请求中,用以描述请求的处理方式。如:

  • 并发要求

  • 一致性要求

默认情况下,您的应用程序应假定数据存储最终一致并使用最后写入获胜的并发模式

并发

Dapr 支持使用 ETags 的乐观并发控制 (OCC)。当请求状态时,Dapr 总是将 ETag 属性附加到返回的状态。当用户代码尝试更新或删除状态时,应该通过请求正文附加 ETag 以进行更新或通过 If-Match 标头进行删除。只有当提供的 ETag 与状态存储中的 ETag 匹配时,写操作才能成功。建议您在使用 ETag 时使用重试策略来补偿此类冲突。

如果您的应用程序在写入请求时省略 ETag,则 Dapr 在处理请求时会跳过 ETag 检查。与使用 ETag 的先写赢模式相比,这实质上启用了最后写赢模式。

自动加密

Dapr 支持应用程序状态的自动客户端加密,并支持密钥轮换。这是一项预览功能,所有 Dapr 状态存储都支持。

一致性

Dapr 支持强一致性和最终一致性,最终一致性作为默认行为。

  • 当使用强一致性时,Dapr 在确认写入请求之前等待所有副本(或指定的仲裁)确认。

  • 当使用最终一致性时,一旦底层数据存储接受写入请求,Dapr 就会立即返回,即使这是单个副本。

批量操作

Dapr 支持两种类型的批量操作 - 批量(bulk)或多(multi)。

:bulk与multi的区别在于bulk不是事务性的,multi是事务处理。

Actor状态

事务状态存储可用于存储Actor状态。要指定用于Actor的状态存储,请在状态存储组件的元数据部分中将属性 actorStateStore的值指定为 true

:Actors 状态以特定方案存储在事务状态存储中允许一致的查询。所以只能有一个状态存储组件被用于所有的Actor。

直接查询状态存储

Dapr 无需任何转换即可保存和检索状态值。您可以直接从底层状态存储查询和聚合状态。

例如,要在 Redis 中获取与应用程序 ID “myApp” 关联的所有状态键,请使用:

KEYS "myApp*"

查询Actor状态

如果数据存储支持 SQL 查询,您可以使用 SQL 查询查询参与者的状态。例如使用:

SELECT * FROM StateTable WHERE Id='<app-id>||<actor-type>||<actor-id>||<key>'

您还可以跨Actor实例执行聚合查询,避免Actor 框架常见的基于回合的并发限制。例如,要计算所有温度计Actor的平均温度,请使用:

保存并获取状态

状态管理是任何应用程序最常见的需求之一:新的或遗留的、单体或微服务。处理不同的数据库、测试、处理重试和故障可能既费时又费力。

先决条件

准备好Dapr运行环境可以看之前的文章

手把手教你学Dapr - 3. 使用Dapr运行第一个.Net程序

设置状态存储

Windows打开目录%USERPROFILE%\.dapr\components

  1. 创建文件statestore.yaml

  2. 使用redis作为状态存储的数据库

    apiVersion: dapr.io/v1alpha1
    kind: Component
    metadata:name: statestore
    spec:type: state.redisversion: v1metadata:- name: redisHostvalue: localhost:6379- name: redisPasswordvalue: ""- name: actorStateStorevalue: "true"

    :这个yaml已经通过actorStateStore开启了Actor状态

保存和检索单个状态

:设置 app-id 很重要,因为状态键以该值作为前缀。如果您不设置它,则在运行时为您生成一个,下次运行该命令时将生成一个新的,您将无法再访问以前保存的状态。换句话说,如果你要共享状态可以自定义一个保留app-id作为共享状态而不是留空。

运行Dapr Sidecar

运行一个空的Sidecar,因为我们只用它来帮助访问状态存储,所以与之前不同的是,dapr run后面没有接dotnet run去作为某一个程序的Sidecar

dapr run --app-id myapp --dapr-http-port 3500 --dapr-grpc-port 50001

创建客户端

创建控制台程序,添加Dapr.Client NuGet包引用。

修改Program.cs

using Dapr.Client;var storeName = "statestore";
var key = "myFirstKey";
var value = "myFirstValue";var client = new DaprClientBuilder().Build();
await client.SaveStateAsync(storeName, key, value);
Console.WriteLine("State has been stored");var data = await client.GetStateAsync<string>(storeName, key);
Console.WriteLine($"Got value: {data}");Console.ReadKey();

删除单个状态

await client.DeleteStateAsync(storeName, key);

通过事务保存和检索多个状态

Dapr 还允许您在同一个调用中保存和检索多个状态。

var lst = new List<StateTransactionRequest>()
{new StateTransactionRequest("test1", System.Text.Encoding.UTF8.GetBytes("value1"), StateOperationType.Upsert),new StateTransactionRequest("test2", System.Text.Encoding.UTF8.GetBytes("value2"), StateOperationType.Upsert),
};
await client.ExecuteStateTransactionAsync(storeName, lst);var datas = await client.GetBulkStateAsync(storeName, lst.Select(r => r.Key).ToList(), 0);
Console.WriteLine($"Got items: {string.Join(",", datas.Select(d => $"{d.Key}={d.Value}"))}");

强一致性

使用强一致性时,Dapr将确保底层状态存储在写入或删除状态之前,一旦数据被写入到所有副本或收到来自quorum的ack,就会返回响应。

对于GET请求,Dapr 将确保存储在副本之间一致地返回最新数据。默认为最终一致性,除非在对状态 API 的请求中另有说明。

await client.SaveStateAsync(storeName, key, value, new StateOptions() { Consistency = ConsistencyMode.Strong });var etagData = await client.GetStateAndETagAsync<string>(storeName, key, ConsistencyMode.Strong);
Console.WriteLine($"ETag:{etagData.etag}");await client.DeleteStateAsync(storeName, key, new StateOptions() { Consistency = ConsistencyMode.Strong });

先写赢和最后写赢

Dapr 允许开发人员在使用数据存储时选择两种常见的并发模式:首先写入获胜`最后写入获胜。First-Write-Wins 在您有多个应用程序实例的情况下很有用,所有实例都同时写入同一个键。

Dapr 的默认模式是最后写入获胜

下面的例子展示了如何获取一个 ETag,然后使用它来保存状态,然后删除状态:

await client.SaveStateAsync(storeName, key, value, new StateOptions() { Concurrency = ConcurrencyMode.FirstWrite });
var firstWriteWinData = await client.GetStateAndETagAsync<string>(storeName, key);
var etag = firstWriteWinData.etag;await client.TrySaveStateAsync(storeName, key, DateTime.Now.Ticks.ToString(), etag, new StateOptions() { Concurrency = ConcurrencyMode.FirstWrite });
var firstWriteWinDeleteSucceeded = await client.TryDeleteStateAsync(storeName, key, etag);
Console.WriteLine($"First write wins delete:{firstWriteWinDeleteSucceeded}");firstWriteWinData = await client.GetStateAndETagAsync<string>(storeName, key);
firstWriteWinDeleteSucceeded = await client.TryDeleteStateAsync(storeName, key, firstWriteWinData.etag);
Console.WriteLine($"First write wins delete:{firstWriteWinDeleteSucceeded}");

:这里演示了ETag在更新后尝试删除失败的例子,最后再重新获取新的状态以修正ETag再删除

在不同的应用程序之间共享状态

为了实现状态共享,Dapr 支持以下键前缀策略

  • appid - 这是默认策略。appid 前缀允许状态只能由具有指定 appid 的应用程序管理。所有状态键都将以 appid 为前缀,并以应用程序为范围。

  • name - 此设置使用状态存储组件的名称作为前缀。对于给定的状态存储,多个应用程序可以共享相同的状态。

  • none - 此设置不使用前缀。多个应用程序在不同的状态存储之间共享状态

举个例子:要指定前缀策略,请在状态组件上添加名为 keyPrefix 的元数据键

apiVersion: dapr.io/v1alpha1
kind: Component
metadata:name: statestorenamespace: production
spec:type: state.redisversion: v1metadata:- name: keyPrefixvalue: <key-prefix-strategy>

:此示例演示相对较复杂,思路大概是使用多个statestore.yaml,然后根据不同的storename切换不同策略即可。感兴趣的小伙伴可以自行尝试。

自动加密状态并管理密钥轮换

:截止目前,这个功能是个预览版,感兴趣的小伙伴可以自行尝试

应用程序状态通常需要静态加密,以在企业工作负载或受监管环境中提供更强的安全性。Dapr 提供基于 AES256 的自动客户端加密。

状态的生存时间(TTL)

Dapr 为每个状态在请求时设置生存时间 (TTL)。这意味着应用程序可以为每个存储的状态设置生存时间,并且这些状态在到期后无法检索。

:只有一部分 Dapr 状态存储组件与状态 TTL 兼容。对于支持的状态存储,只需在发布消息时设置 ttlInSeconds 元数据。其他状态存储将忽略此值。

await client.SaveStateAsync(storeName, key, value, metadata: new Dictionary<string, string>() { { "ttlInSeconds", "3" } });
var ttlData = await client.GetStateAsync<string>(storeName, key);
Console.WriteLine($"TTL Data:{ttlData}");Thread.Sleep(5000);
ttlData = await client.GetStateAsync<string>(storeName, key);
Console.WriteLine($"TTL Data:{ttlData}");

持久化状态

要显式设置持久化状态(忽略为键设置的任何 TTL),请将 ttlInSeconds 值指定为 -1

本章源码

Assignment05

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

我们正在行动,新的框架、新的生态

我们的目标是自由的易用的可塑性强的功能丰富的健壮的

所以我们借鉴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),备注来意,邀请进群

手把手教你学Dapr - 5. 状态管理相关推荐

  1. 手把手教你学Dapr - 6. 发布订阅

    介绍 发布/订阅模式允许微服务使用消息相互通信.生产者或发布者在不知道哪个应用程序将接收它们的情况下向主题发送消息.这涉及将它们写入输入通道.同样,消费者或订阅者订阅该主题并接收其消息,而不知道是什么 ...

  2. 手把手教你学Dapr - 2. 必须知道的概念

    Sidecar 边车 Dapr API提供Http和gRPC两种通讯方式. 运行方式则可以是容器也可以是进程(Windows开发推荐使用Self Hosted,后续会解释). 这样的好处是与运行环境无 ...

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

    介绍 通过使用服务调用,您的应用程序可以使用标准的gRPC或HTTP协议与其他应用程序可靠.安全地通信. 为什么不直接用HttpClientFactory呢 先问几个问题: 如何发现和调用不同服务的方 ...

  4. 手把手教你学Dapr - 3. 使用Dapr运行第一个.Net程序

    注意: 文章中提到的命令行工具即是Windows Terminal/PowerShell/cmd其中的一个,推荐使用Windows Terminal 运行命令行工具的时候建议以管理员身份,避免踩坑 为 ...

  5. 手把手教你学Dapr - 1. .Net开发者的大时代

    Dapr全称 Distributed Application Runtime,分布式应用运行时 Dapr的口号 简化云原生应用开发,聚焦在应用的核心逻辑,让代码简单.可移植 Dapr的目标 最佳实践的 ...

  6. 手把手教你学Dapr - 7. Actors

    介绍 Actor模式将Actor描述为最低级别的"计算单元".换句话说,您在一个独立的单元(称为actor)中编写代码,该单元接收消息并一次处理一个消息,没有任何并发或线程. 再换 ...

  7. oracle数据库更新语句_20_手把手教你学Python之操作数据库

    数据库是数据的仓库,将大量数据按照一定的方式组织并存储起来,方便进行管理和维护,例如快速检索和统计等.数据库的主要特点: 以一定的方式组织.存储数据: 能为多个用户共享: 与程序彼此独立. -- 数据 ...

  8. 正点原子linux驱动教程,正点原子 手把手教你学Linux之驱动开发篇

    简 介 该课程是正点原子手把手教你学Linux系列课程,该课程配套开发板为正点原子alpha/mini Linux开发板. 手把手教你学Linux之驱动开发篇: 第1讲 Linux驱动开发与裸机开发区 ...

  9. 手把手教你学Python之Pandas(一文掌握数据分析与处理库-Pandas)

    目录 基本结构之Series Series对象的创建 Index对象介绍 Series中数据的访问 Series中常用方法 基本结构之DataFrame DataFrame的创建 ​DataFrame ...

最新文章

  1. 左牵Uber右联大众,黄教主带领320家车企一统自动驾驶江湖
  2. 非常棒的jQuery排版用插件
  3. C++中基类的析构函数为什么要用virtual虚析构函数
  4. 【调参实战】那些优化方法的性能究竟如何,各自的参数应该如何选择?
  5. 人最重要的能力是什么?
  6. 检测单击鼠标左键并拖动的消息_计算机视觉OpenCV学习笔记(四):关于鼠标的相关事件函数...
  7. 《采访中收集程序猿》学习记录5
  8. 使用二进制编辑器制作操作系统启动盘
  9. 最新php在线扒站程序源码分享
  10. pg数据库的基本操作
  11. paypal android sdk,Android Paypal SDK错误:商家不接受此类付款
  12. windows11虚拟机安装失败解决办法
  13. 翻译连载 | JavaScript轻量级函数式编程-第 8 章:列表操作 |《你不知道的JS》姊妹篇
  14. Oracle 19c VLDB and Partitioning Guide 第2章:Partitioning Concepts 读书笔记
  15. 国家开放大学计算机应用基础本科性考,精选国家开放大学电大本科《1200计算机应用基础》形考任务1试题及答案...
  16. 【生态环境保护】绿水青山就是金山银山——生态环保篇
  17. Rikka with Travels【换根树dp】
  18. RNAmmer:预测基因组上的核糖体RNA
  19. 【资源分享】疫情居家一个月,精心整理了一个PPT资源社区(含模板-资源-高级技巧)
  20. maple 2018 窗口关闭提示乱码_GRF中野再次实锤加盟LNG!韩媒爆料:Maple或去北美赛区养老...

热门文章

  1. EqualLogic全攻略视频[(四)高级管理]
  2. VS2010自定义新建文件模版
  3. php strtoup,PHP 7 的几处函数安全小变化
  4. 如何添加JWT生成的token在请求头中
  5. luogu 1484\1792 种树 奇怪的贪心可反悔
  6. 在ubuntu 16.04里使用python—scrapy将爬取到的数据存到mysql数据库中的一些随笔
  7. Installing OpenCV 2.3.1 in Ubuntu
  8. C#操作Excel文件暨C#实现在Excel中将连续多列相同数据项合并
  9. 弹窗php整人_[整人小程序] 超级信息框(无限弹窗++)
  10. 中药ppi网络图太杂乱_太杂乱了吗? 这是您的iPhone,iPad,Android或台式机的15张简约壁纸...