Dapr状态存储
提示:以下是本篇文章正文内容,下面案例可供参考
Dapr状态存储的优势
- 可插拔的存储组件
- 支持的存储组件:
https://docs.dapr.io/zh-hans/reference/components-reference/supported-state-stores/
- 支持的存储组件:
- 并发控制:通过Etag实现
- 一致性:可以指定是否强一致性来保证所有存储副本保存成功之后再返回成功
- 批量操作
调用终结点
http://localhost:<dapr-port>/v1.0/state/<store-name>/
-
<dapr-port>:Dapr正在侦听的HTTP端口
-
<store-name>:要使用的状态存储组件的名称。
代码编写
- FrontEnd项目下,新建StateController
- 注入DaprClient
private readonly ILogger<StateController> _logger; private readonly DaprClient _daprClient; public StateController(ILogger<StateController> logger, DaprClient daprClient) { _logger = logger; _daprClient = daprClient; }
- 声明要使用的存储组件和Key
const string STATE_STORE = "statestore"; const string KEY_NAME = "guid";
- 新增接口
//设置强一致性,保存一个值 [HttpPost] public async Task<ActionResult> PostAsync() { await _daprClient.SaveStateAsync<string>(STATE_STORE, KEY_NAME, Guid.NewGuid().ToString(), new StateOptions() { Consistency = ConsistencyMode.Strong }); return Ok("done"); } //通过tag防止并发冲突,保存一个值 [HttpPost("withtag")] public async Task<ActionResult> PostWithTagAsync() { var (value, etag) = await _daprClient.GetStateAndETagAsync<string>(STATE_STORE, KEY_NAME); var resust= await _daprClient.TrySaveStateAsync<string>(STATE_STORE, KEY_NAME, Guid.NewGuid().ToString(), etag); return Ok("done"); } // 获取一个值 [HttpGet] public async Task<ActionResult> GetAsync() { var result = await _daprClient.GetStateAsync<string>(STATE_STORE, KEY_NAME); return Ok(result); } // 获取一个值和etag [HttpGet("withetag")] public async Task<ActionResult> GetWithEtagAsync() { var (value, etag) = await _daprClient.GetStateAndETagAsync<string>(STATE_STORE, KEY_NAME); return Ok($"value is {value}, etag is {etag}"); } //删除一个值 [HttpDelete] public async Task<ActionResult> DeleteAsync() { await _daprClient.DeleteStateAsync(STATE_STORE, KEY_NAME); return Ok("done"); } //通过tag防止并发冲突,删除一个值 [HttpDelete("withtag")] public async Task<ActionResult> DeleteWithTagAsync() { var (value, etag) = await _daprClient.GetStateAndETagAsync<string>(STATE_STORE, KEY_NAME); var success = await _daprClient.TryDeleteStateAsync(STATE_STORE, KEY_NAME, etag); return Ok($"value is {value}, etag is {etag}"); } //根据FromState获取一个值,健值name从路由模板获取 [HttpGet("fromState/{name}")] public async Task<ActionResult> GetFromBindingAsync([FromState(STATE_STORE, KEY_NAME)] StateEntry<string> state) { return Ok(state.Value); } // 根据FromState获取并修改值,健值name从路由模板获取 [HttpPost("fromState/{name}")] public async Task<ActionResult> PostWithBindingAsync([FromState(STATE_STORE, KEY_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(STATE_STORE, new List<string> { KEY_NAME }, 10); return Ok(result); } //批量删除 [HttpDelete("list")] public async Task<ActionResult> DeleteListAsync() { var data = await _daprClient.GetBulkStateAsync(STATE_STORE, new List<string> { KEY_NAME }, 10); var removeList = new List<BulkDeleteStateItem>(); foreach (var item in data) { removeList.Add(new BulkDeleteStateItem(item.Key, item.ETag)); } await _daprClient.DeleteBulkStateAsync(STATE_STORE, removeList); return Ok("done"); }
运行与测试
- 启动FrontEnd
dapr run --dapr-http-port 3501 --app-port 5001 --app-id frontend dotnet .\FrontEnd\bin\Debug\net6.0\FrontEnd.dll
调用结果如下:
新增接口:
可以看到Redis已经有了值:
其他接口就不一一在此测试了,大家有兴趣可以自己去试试
切换存储组件
-
新增yaml文件statestore-mysql,写入以下代码
apiVersion: dapr.io/v1alpha1 kind: Component metadata: name: statestore-mysql spec: type: state.mysql version: v1 metadata: - name: connectionString value: "root:mysql123@tcp(192.168.11.112:3306)/?allowNativePasswords=true"
-
修改STATE_STORE,注意这里的STATE_STORE 需要和yaml文件中metadata的name保持一致
const string STATE_STORE = "statestore-mysql";
-
重启项目
测试
调用结果如下:
新增接口
mysql已经插入了数据:
其他的接口大家也可自行测试,这里就不一一为大家展示了