为了防止并发对数据修改造成差异,dapr使用了etag标签来作为版本号,对数据修改进行验证。
下面是对etag的一个demo
appsettings.json中的url配置
"StateUrl": "http://localhost:3500/v1.0/state/statestore"
在PaymentSystem项目中添加两个action
[HttpPost("/writekeyswithetag")]public async Task<IActionResult> WriteKeysWithEtag([FromBody] KeyEntityWithEtag[] keys){var client = _clientFactory.CreateClient();var jsonContent = System.Text.Json.JsonSerializer.Serialize(keys);var content = new StringContent(jsonContent);var response = await client.PostAsync(_stateUrl, content);return Ok(await response.Content.ReadAsStringAsync());}[HttpGet("/readekeywithetag/{key}")]public async Task<IActionResult> ReadKeyWithEtag(string key){var client = _clientFactory.CreateClient();var response = await client.GetAsync($"{_stateUrl}/{key}"); var dataString = await response.Content.ReadAsStringAsync();var data = (string.IsNullOrEmpty(dataString) ? null : System.Text.Json.JsonSerializer.Deserialize<OrderPayment>(dataString));return new JsonResult(new { result = true, data = new { data = data, etag = response.Headers.SingleOrDefault(s => s.Key.ToLower() == "etag") }, host = Dns.GetHostName() });}
实体类
public class OrderPayment
{public string PayOrder { get; set; }public decimal PayTotal { get; set; }public string PayType { get; set; }public DateTime PayTime { get; set; }
}
public class KeyEntityWithEtag
{public string Key { get; set; }public OrderPayment Value { get; set; }public string Etag { get; set; }
}
docker-compose.yml
version: '3.4'services:#┌─────────────────────────┐#│ Dapr placement1 service │#└─────────────────────────┘ placement:image: "daprio/dapr"command: ["./placement", "-port", "50006"]ports:- "50006:50006"networks:- b2c-dapr#┌────────────────────┐#│ Redis1 state store │#└────────────────────┘ redis:image: "redis:latest"ports:- "6380:6379"networks:- b2c-dapr#┌───────────────────────────────────┐#│ paymentsystem1 app + Dapr sidecar │#└───────────────────────────────────┘ paymentsystem1:image: ${DOCKER_REGISTRY-}paymentsystemdepends_on:- redis- placementbuild:context: ../dockerfile: /PaymentSystem/Dockerfileports:- "3601:3500"volumes: - ../PaymentSystem:/PaymentSystem networks:- b2c-dapr paymentsystem1-dapr:image: "daprio/daprd:latest"command: [ "./daprd", "-app-id", "pay", "-app-port", "80","-placement-host-address", "placement:50006","-components-path","/components" ]build:context: ../depends_on:- paymentsystem1network_mode: "service:paymentsystem1"volumes: - ../components:/components #┌───────────────────────────────────┐#│ paymentsystem2 app + Dapr sidecar │#└───────────────────────────────────┘ paymentsystem2:image: ${DOCKER_REGISTRY-}paymentsystemdepends_on:- redis- placement build:context: ../dockerfile: /PaymentSystem/Dockerfilevolumes: - ../PaymentSystem:/PaymentSystem ports:- "3602:3500"networks:- b2c-dapr paymentsystem2-dapr:image: "daprio/daprd:latest"command: [ "./daprd", "-app-id", "pay", "-app-port", "80" ,"-placement-host-address", "placement:50006","-components-path","/components"]build:context: ../depends_on:- paymentsystem2network_mode: "service:paymentsystem2"volumes: - ../components:/components
networks:b2c-dapr:
提交带有etag标签的数据,多提交几次,可以把etag顶起来
查看etag为非1
这时再次提交就会报错,如果另外的服务更新了这个值,本次提交就会失败,需要再次查询后更新,或作别的业务逻辑处理。