Dapr + .NET Core实战(三)状态管理

状态管理解决了什么

分布式应用程序中的状态可能很有挑战性。例如:

  • 应用程序可能需要不同类型的数据存储

  • 访问和更新数据可能需要不同的一致性级别。

  • 多个用户可以同时更新数据,这需要解决冲突

  • 服务必须重试 与数据存储交互 时发生的任何短期暂时性错误。

Dapr 状态管理解决了这些难题。它简化了跟踪状态,而无需依赖关系或第三方存储 SDK 上的学习曲线。

工作原理

e7378bd9f24d7106aa85d5eb95f81dc2.png

应用程序与 Dapr sidecar 交互,以存储和检索键/值数据。在底层,sidecar API 使用可配置的状态存储组件来保存数据。开发人员可以从不断增长的受支持状态存储集合中选择,其中包括 Azure Cosmos DB、SQL Server 和 Cassandra。

可以使用 HTTP 或 gRPC 调用 API。使用以下 URL 调用 HTTP API:

http://localhost:<dapr-port>/v1.0/state/<store-name>/
  • <dapr-port>:Dapr 侦听的 HTTP 端口。

  • <store-name>:使用的状态存储组件的名称。

状态组件

Dapr支持的组件

为本地自承载开发初始化时,Dapr 将 Redis 注册为默认状态存储。下面是默认状态存储配置的示例,配置文件位置为C:\Users\<username>\.dapr\components。记下默认名称 statestore :

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

89c7e9d1b7bb30e0678046d30fa5d759.png

项目演示

仍然使用 上一篇服务调用 的FrontEnd项目,新建StateController

using Dapr;
using Dapr.Client;using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;using System;
using System.Collections.Generic;
using System.Threading.Tasks;namespace FrontEnd.Controllers
{[Route("[controller]")][ApiController]public class StateController : ControllerBase{private readonly ILogger<StateController> _logger;private readonly DaprClient _daprClient;public StateController(ILogger<StateController> logger, DaprClient daprClient){_logger = logger;_daprClient = daprClient;}// 获取一个值[HttpGet]public async Task<ActionResult> GetAsync(){var result = await _daprClient.GetStateAsync<string>("statestore", "guid");return Ok(result);}//保存一个值[HttpPost]public async Task<ActionResult> PostAsync(){await _daprClient.SaveStateAsync<string>("statestore", "guid", Guid.NewGuid().ToString(), new StateOptions() { Consistency = ConsistencyMode.Strong });return Ok("done");}//删除一个值[HttpDelete]public async Task<ActionResult> DeleteAsync(){await _daprClient.DeleteStateAsync("statestore", "guid");return Ok("done");}//通过tag防止并发冲突,保存一个值[HttpPost("withtag")]public async Task<ActionResult> PostWithTagAsync(){var (value, etag) = await _daprClient.GetStateAndETagAsync<string>("statestore", "guid");await _daprClient.TrySaveStateAsync<string>("statestore", "guid", Guid.NewGuid().ToString(), etag);return Ok("done");}//通过tag防止并发冲突,删除一个值[HttpDelete("withtag")]public async Task<ActionResult> DeleteWithTagAsync(){var (value, etag) = await _daprClient.GetStateAndETagAsync<string>("statestore", "guid");return Ok(await _daprClient.TryDeleteStateAsync("statestore", "guid", etag));}// 从绑定获取一个值,健值name从路由模板获取[HttpGet("frombinding/{name}")]public async Task<ActionResult> GetFromBindingAsync([FromState("statestore", "name")] StateEntry<string> state){return Ok(state.Value);}// 根据绑定获取并修改值,健值name从路由模板获取[HttpPost("withbinding/{name}")]public async Task<ActionResult> PostWithBindingAsync([FromState("statestore", "name")] StateEntry<string> state){state.Value = Guid.NewGuid().ToString();return Ok(await state.TrySaveAsync());}// 获取多个个值[HttpGet("list")]public async Task<ActionResult> GetListAsync(){var result = await _daprClient.GetBulkStateAsync("statestore", new List<string> { "guid" }, 10);return Ok(result);}// 删除多个个值[HttpDelete("list")]public async Task<ActionResult> DeleteListAsync(){var data = await _daprClient.GetBulkStateAsync("statestore", new List<string> { "guid" }, 10);var removeList = new List<BulkDeleteStateItem>();foreach (var item in data){removeList.Add(new BulkDeleteStateItem(item.Key, item.ETag));}await _daprClient.DeleteBulkStateAsync("statestore", removeList);return Ok("done");}}
}

cmd运行

dapr run --dapr-http-port 3501 --app-port 5001  --app-id frontend dotnet  .\FrontEnd\bin\Debug\net5.0\FrontEnd.dll

可通过postman调用sidecar的endpoint

bdb43401f5511e5010b94fc8cabac69c.png

 74466fba8b34269518c918c7739cf0f6.png

 查看store存储中的内容

进入容器内部

docker exec -it dapr_redis /bin/sh

调用redis-cli

redis-cli

查看所有key

keys *

可以看到有"frontend||guid"这个key,所以状态在redis中存储中Name的规则是appName||keyName,这样可以防止不同app的键冲突

我们通过type key查看下这个键的类型,可以发现他是一个hash

127.0.0.1:6379> type frontend||guid
hash

再通过hgetall key查看他的数据,发现有两个键,一个data,一个version

127.0.0.1:6379> hgetall  frontend||guid
1) "data"
2) "\"e17b3e06-ba30-42c5-8960-48511c70b496\""
3) "version"
4) "1"

data很明显是存入的数据,version呢?现在猜测是防止并发冲突的etag,我们下面来验证一下

在StateController中新增接口

// 获取一个值和etag[HttpGet("withetag")]public async Task<ActionResult> GetWithEtagAsync(){var (value,etag) = await _daprClient.GetStateAndETagAsync<string>("statestore", "guid");return Ok($"value is {value}, etag is {etag}");}

通过dapr重启这个app,并调用withetag api,很明显redis中version与etag相等,初步印证我们的猜测

4f92a1dd242315eeca2101e8616d5340.png

 我们可以通过post方法修改一下guid这个key,修改后etag会变更,再来看一下redis中version和etag是不是一个东西

首先调用POST方法修改值

6ddf12697b68f4c9d1bf2cc458c7c66c.png

 再调用withetag方法,看下etag,发现etag变成了2

729296c69138fb9b93d681ffba48a51d.png

 在比较一下redis中的version

127.0.0.1:6379> hgetall  frontend||guid
1) "data"
2) "\"36a55558-35c3-402c-ac9e-615014eb6904\""
3) "version"
4) "2"

现在可以确定etag就是redis中的version

相关文章:

  • Dapr实战(一) 基础概念与环境搭建

  • Dapr + .NET Core实战(二) 服务调用

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/297610.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Building JavaScript Games for Phones Tablets and Desktop(3)-创造一个游戏世界

2019独角兽企业重金招聘Python工程师标准>>> 创造一个游戏世界 这章教会你如何通过内存中储存的信息创造一个游戏世界。介绍了基本类型和变量并且这些变量是如何储存和改变信息的。接下来&#xff0c;你会看到如何用对象储存更复杂的信息&#xff0c;里面包含成员变…

我女朋友让我删前任,我明明删了她还是要分手...

1 人家都已经删了你还有什么不满意&#xff1f;&#xff1f;&#xff1f;▼2 高跟鞋翻车现场▼3 渣男总能渣出新花样▼4 现在的小朋友懂得也太多了吧&#xff01;▼5 耍帅不可怕&#xff0c;谁失败谁尴尬▼6 朋友&#xff0c;你清醒一点&#xff01;那个小手是鼠标&#…

你知道哪些开源基金会?

从 RMS 创立 FSF 发起自由软件运动&#xff0c;再到 OSI 成立并明确开源软件定义&#xff0c;这种崇尚开放协作的软件开发模式迅速席卷全球。除 FSF 与 OSI 外&#xff0c;还陆续诞生了许多致力于推广和发展开源的基金会。开源基金会对于开源软件和开源社区的组织、发展、协同创…

bpmn如何查看代码 idea_提高程序员效率的IDEA插件推荐(五大神器)

1. SequenceDiagramSequenceDiagram 可以根据代码调用链路自动生成时序图&#xff0c;超级赞&#xff0c;超级推荐&#xff01;这对研究源码&#xff0c;梳理工作中的业务代码有极大的帮助&#xff0c;堪称神器。安装完成后&#xff0c;在某个类的某个函数中&#xff0c;右键 -…

一张纸还能上天能救命?理工男宁愿放弃NASA百万年薪,也要回家折纸?!

全世界有3.14 % 的人已经关注了爆炸吧知识一张纸能做什么&#xff1f;小时候&#xff0c;它可能默默记录着你天马行空的想象力&#xff1a;而到了艺术家手中&#xff0c;它们就会变幻成各种各样精妙绝伦的艺术品&#xff1a;可当一双文艺的手&#xff0c;遇上一颗聪明无比的“理…

【干货】单日10亿GMV的.NET5电商平台,是如何设计的?

自京东和唯品会转了Java&#xff0c;.NET就一直缺乏高并发电商案例&#xff0c;.NET5能做高并发电商吗&#xff1f;必须的&#xff0c;别停留在.NET Framework的旧印象了&#xff01;这里为大家分享一家上市公司的项目案例&#xff0c;纯.NET5电商平台&#xff0c;轻松承接双11…

通过 Lotus Domino Java 代理消费 Web 服务

Web 服务是一种允许两台或更多的计算机在网络中交互的系统设计。这种服务的主要优点是&#xff0c;它是在多台不同操作系统的计算机和应用服务器之间发送对象的标准解决方法。例如&#xff0c;我们的公司使用 Web 服务从一台运行 Microsoft .NET Framework 的计算机向基于 IBM …

goahead如何使用cgi服务_QQ如何设置使用代理服务器?

很多人可能会问了&#xff0c;QQ上可以设置代理服务器吗?答案是可以的。今天就为大家详细介绍一下&#xff0c;如何在QQ上设置代理服务器的。1、双击QQ图标&#xff0c;打开QQ登录界面&#xff0c;我们就可以看到界面右上角有一个“设置”按钮。QQ如何设置使用代理服务器12、点…

android listview添加数据_Android面经分享,失业两个月,五一节前拿到offer

秦子帅明确目标&#xff0c;每天进步一点点.....作者 | 天天有道地址 | juejin.im/post/5eb01866f265da7b9c24562c基本介绍今天介绍一位朋友的经历&#xff1a;从3月初开始复习&#xff0c;准备面试题。复习的资料主要为《Android开发艺术探索》和jsonchao的博客&#xff0c;…

Dapr + .NET 实战(四)发布和订阅

什么是发布-订阅发布订阅是一种众所周知并被广泛使用的消息传送模式&#xff0c;常用在微服务架构的服务间通信&#xff0c;高并发削峰等情况。但是不同的消息中间件之间存在细微的差异&#xff0c;项目使用不同的产品需要实现不同的实现类&#xff0c;虽然是明智的决策&#x…

这些数学趣图,数学老师看了后会怎么想?

全世界有3.14 % 的人已经关注了爆炸吧知识这个扣分不?我的人生98%的时间都是无比正确的数学与我不能言语的关系最深情的告白限速是......当我完成数学作业后....维生素C的来历高数课堂恩..... 来拜师了啊, 好好学习. 为师给你命名: 阿尔法狗.这个是驻点, 这是最值, 这些机器学…

COM 组件设计与应用(六)

一、前言  1、与 《COM 组件设计与应用(五)》的内容基本一致。但本回讲解的是在 vc.net 2003 下的使用方法&#xff0c;即使你不再使用vc6.0&#xff0c;也请和上一回的内容&#xff0c;参照比对。   2、这第一个组件&#xff0c;除了所有 COM 组件必须的 IUnknown 接口外&…

python 柱状图 间距_专题第18篇:Python 绘图入门

我的施工之路1我的施工计划2数字专题3字符串专题4列表专题5流程控制专题6编程风格专题7函数使用8面向对象编程(上篇)9面向对象编程(下篇)10十大数据结构11包和模块使用总结12Python正则专题总结13设计模式14Python时间模块总结15 Python 装饰器16 Python 迭代器17 Python 生成器…

WPF实现截屏(仿微信)

WPF开发者QQ群&#xff1a; 340500857 | 微信群 -> 进入公众号主页 加入组织欢迎转发、分享、点赞、在看&#xff0c;谢谢~。 前言有小伙伴需要在软件反馈窗体增加截图功能需求&#xff0c;所以今天来实现一个仿微信的截图。01—效果预览效果预览&#xff08;更多效果请下…

我妈要把闺蜜介绍给我当女朋友......

1 反正手没闲着啊▼2 这...这女孩子不会是您跳广场舞认识的吧&#xff1f;▼3 这就是生活▼4 有画面感了▼5 这种运动会想想就觉得很好看▼6 电脑屏幕不亮手机玩起来不够舒服▼7 这种脱衣方式可真是太酷啦&#xff01;▼你点的每个赞&#xff0c;我都认真当成了喜欢

topic数量是指什么_一个网站的IP、UV和PV到底是什么

在百度统计后台会看到“IP统计”、“UV统计”、“PV统计”&#xff0c;那么、什么是IP&#xff0c;什么是UV&#xff0c;什么又是PV&#xff0c;三者之间有什么关系&#xff0c;IP重要&#xff0c;还是UV重要&#xff0c;还是PV重要。什么是IP&#xff1f;IP即&#xff1a;Inte…

发布一个博客园专用Windows Live Writer代码插件

一直用Windows Live Writer写博客&#xff0c;不过没找到能与博客园配合得很好的代码插件&#xff0c;每次写完文章发布到博客园总要手动修改代码。所以我自己写了一个博客园专用的Windows Live Writer代码插件&#xff08;我知道这世界上已经有N个代码插件&#xff0c;好吧&am…

js深拷贝和浅拷贝

一、数组的深浅拷贝 在使用JavaScript对数组进行操作的时候&#xff0c;我们经常需要将数组进行备份&#xff0c;事实证明如果只是简单的将它赋予其他变量&#xff0c;那么我们只要更改其中的任何一个&#xff0c;然后其他的也会跟着改变&#xff0c;这就导致了问题的发生。 va…

dbeaver 数据转化 mapping_Python机器学习实例:数据竞赛-足球运动员身价估计

前言1&#xff0c;背景介绍每个足球运动员在转会市场都有各自的价码。本次数据练习的目的是根据球员的各项信息和能力来预测该球员的市场价值。2&#xff0c;数据来源FIFA20183&#xff0c;数据文件说明数据文件分为三个&#xff1a;train.csv         训练集     文件…

对SQL server、Oracle、MySQL和PostgreSQL进行OLTP性能测试(Benchmark)

&#x1f4e2;欢迎点赞 &#xff1a;&#x1f44d; 收藏 ⭐留言 &#x1f4dd; 如有错误敬请指正&#xff0c;赐人玫瑰&#xff0c;手留余香&#xff01;&#x1f4e2;本文作者&#xff1a;由webmote 原创&#xff0c;首发于 【掘金】&#x1f4e2;作者格言&#xff1a;生活在于…