状态管理API参考
组件文件
Dapr的statestore.yaml
组件文件结构如下:
apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
name: <NAME>
namespace: <NAMESPACE>
spec:
type: state.<TYPE>
version: v1
metadata:
- name:<KEY>
value:<VALUE>
- name: <KEY>
value: <VALUE>
设置 | 描述 |
---|---|
metadata.name |
状态存储的名称。 |
spec/metadata |
一个开放的键值对元数据,允许绑定定义连接属性。 |
键方案
Dapr状态存储是键/值存储。Dapr要求这些数据存储遵循固定的键方案,以确保数据兼容性。对于一般状态,键格式为:
<App ID>||<state key>
对于actor状态,键格式为:
<App ID>||<Actor type>||<Actor id>||<state key>
保存状态
通过该端点可以保存一组状态对象。
HTTP请求
POST http://localhost:<daprPort>/v1.0/state/<storename>
URL参数
参数 | 描述 |
---|---|
daprPort |
Dapr端口 |
storename |
用户配置的statestore.yaml 组件文件中的metadata.name 字段。请参阅上面提到的Dapr状态存储配置结构。 |
可选的请求元数据通过URL查询参数传递。例如,
POST http://localhost:3500/v1.0/state/myStore?metadata.contentType=application/json
所有URL参数区分大小写。
由于
||
是用作键方案中的分隔符,因此不能在<state key>
字段中使用。
请求体
状态对象的JSON数组,每个状态对象包含以下字段:
字段 | 描述 |
---|---|
key |
状态键 |
value |
状态值,可以是任何字节数组 |
etag |
(可选)状态ETag |
metadata |
(可选)要传递给状态存储的附加键值对 |
options |
(可选)状态操作选项;请参阅状态操作选项 |
ETag格式: Dapr运行时将ETags视为不透明字符串。确切的ETag格式由相应的数据存储定义。
元数据
元数据可以通过请求的URL中的查询参数发送。它必须以metadata.
为前缀,如下所示。
参数 | 描述 |
---|---|
metadata.ttlInSeconds |
消息过期的秒数,如此处所述 |
TTL: 只有某些状态存储支持TTL选项,根据支持的状态存储。
HTTP响应
响应代码
代码 | 描述 |
---|---|
204 |
状态已保存 |
400 |
状态存储缺失或配置错误或请求格式错误 |
500 |
保存状态失败 |
响应体
无。
示例
curl -X POST http://localhost:3500/v1.0/state/starwars?metadata.contentType=application/json \
-H "Content-Type: application/json" \
-d '[
{
"key": "weapon",
"value": "DeathStar",
"etag": "1234"
},
{
"key": "planet",
"value": {
"name": "Tatooine"
}
}
]'
获取状态
通过该端点可以获取特定键的状态。
HTTP请求
GET http://localhost:<daprPort>/v1.0/state/<storename>/<key>
URL参数
参数 | 描述 |
---|---|
daprPort |
Dapr端口 |
storename |
用户配置的statestore.yaml组件文件中的metadata.name 字段。请参阅上面提到的Dapr状态存储配置结构。 |
key |
所需状态的键 |
consistency |
(可选)读取一致性模式;请参阅状态操作选项 |
metadata |
(可选)作为查询参数传递给状态存储的元数据 |
可选的请求元数据通过URL查询参数传递。例如,
GET http://localhost:3500/v1.0/state/myStore/myKey?metadata.contentType=application/json
注意,所有URL参数区分大小写。
HTTP响应
响应代码
代码 | 描述 |
---|---|
200 |
获取状态成功 |
204 |
找不到键 |
400 |
状态存储缺失或配置错误 |
500 |
获取状态失败 |
响应头
头 | 描述 |
---|---|
ETag |
返回值的ETag |
响应体
JSON编码的值
示例
curl http://localhost:3500/v1.0/state/starwars/planet?metadata.contentType=application/json
上述命令返回状态:
{
"name": "Tatooine"
}
要将元数据作为查询参数传递:
GET http://localhost:3500/v1.0/state/starwars/planet?metadata.partitionKey=mypartitionKey&metadata.contentType=application/json
获取批量状态
通过该端点可以获取给定键列表的值列表。
HTTP请求
POST/PUT http://localhost:<daprPort>/v1.0/state/<storename>/bulk
URL参数
参数 | 描述 |
---|---|
daprPort |
Dapr端口 |
storename |
用户配置的statestore.yaml组件文件中的metadata.name 字段。请参阅上面提到的Dapr状态存储配置结构。 |
metadata |
(可选)作为查询参数传递给状态存储的元数据 |
可选的请求元数据通过URL查询参数传递。例如,
POST/PUT http://localhost:3500/v1.0/state/myStore/bulk?metadata.partitionKey=mypartitionKey
注意,所有URL参数区分大小写。
HTTP响应
响应代码
代码 | 描述 |
---|---|
200 |
获取状态成功 |
400 |
状态存储缺失或配置错误 |
500 |
获取批量状态失败 |
响应体
一个JSON编码的值数组
示例
curl http://localhost:3500/v1.0/state/myRedisStore/bulk \
-H "Content-Type: application/json" \
-d '{
"keys": [ "key1", "key2" ],
"parallelism": 10
}'
上述命令返回一个键/值对象数组:
[
{
"key": "key1",
"value": "value1",
"etag": "1"
},
{
"key": "key2",
"value": "value2",
"etag": "1"
}
]
要将元数据作为查询参数传递:
POST http://localhost:3500/v1.0/state/myRedisStore/bulk?metadata.partitionKey=mypartitionKey
删除状态
通过该端点可以删除特定键的状态。
HTTP请求
DELETE http://localhost:<daprPort>/v1.0/state/<storename>/<key>
URL参数
参数 | 描述 |
---|---|
daprPort |
Dapr端口 |
storename |
用户配置的statestore.yaml组件文件中的metadata.name 字段。请参阅上面提到的Dapr状态存储配置结构。 |
key |
所需状态的键 |
concurrency |
(可选)first-write或last-write;请参阅状态操作选项 |
consistency |
(可选)strong或eventual;请参阅状态操作选项 |
可选的请求元数据通过URL查询参数传递。例如,
DELETE http://localhost:3500/v1.0/state/myStore/myKey?metadata.contentType=application/json
注意,所有URL参数区分大小写。
请求头
头 | 描述 |
---|---|
If-Match | (可选)与要删除的键关联的ETag |
HTTP响应
响应代码
代码 | 描述 |
---|---|
204 |
删除状态成功 |
400 |
状态存储缺失或配置错误 |
500 |
删除状态失败 |
响应体
无。
示例
curl -X DELETE http://localhost:3500/v1.0/state/starwars/planet -H "If-Match: xxxxxxx"
查询状态
通过该端点可以查询键/值状态。
alpha
此API处于alpha阶段。HTTP请求
POST/PUT http://localhost:<daprPort>/v1.0-alpha1/state/<storename>/query
URL参数
参数 | 描述 |
---|---|
daprPort |
Dapr端口 |
storename |
用户配置的statestore.yaml组件文件中的metadata.name 字段。请参阅上面提到的Dapr状态存储配置结构。 |
metadata |
(可选)作为查询参数传递给状态存储的元数据 |
可选的请求元数据通过URL查询参数传递。例如,
POST http://localhost:3500/v1.0-alpha1/state/myStore/query?metadata.contentType=application/json
注意,所有URL参数区分大小写。
响应代码
代码 | 描述 |
---|---|
200 |
状态查询成功 |
400 |
状态存储缺失或配置错误 |
500 |
状态查询失败 |
响应体
一个JSON编码的值数组
示例
curl -X POST http://localhost:3500/v1.0-alpha1/state/myStore/query?metadata.contentType=application/json \
-H "Content-Type: application/json" \
-d '{
"filter": {
"OR": [
{
"EQ": { "person.org": "Dev Ops" }
},
{
"AND": [
{
"EQ": { "person.org": "Finance" }
},
{
"IN": { "state": [ "CA", "WA" ] }
}
]
}
]
},
"sort": [
{
"key": "state",
"order": "DESC"
},
{
"key": "person.id"
}
],
"page": {
"limit": 3
}
}'
上述命令返回一个对象数组以及一个令牌:
{
"results": [
{
"key": "1",
"data": {
"person": {
"org": "Dev Ops",
"id": 1036
},
"city": "Seattle",
"state": "WA"
},
"etag": "6f54ad94-dfb9-46f0-a371-e42d550adb7d"
},
{
"key": "4",
"data": {
"person": {
"org": "Dev Ops",
"id": 1042
},
"city": "Spokane",
"state": "WA"
},
"etag": "7415707b-82ce-44d0-bf15-6dc6305af3b1"
},
{
"key": "10",
"data": {
"person": {
"org": "Dev Ops",
"id": 1054
},
"city": "New York",
"state": "NY"
},
"etag": "26bbba88-9461-48d1-8a35-db07c374e5aa"
}
],
"token": "3"
}
要将元数据作为查询参数传递:
POST http://localhost:3500/v1.0-alpha1/state/myStore/query?metadata.partitionKey=mypartitionKey
状态事务
将更改持久化到状态存储作为事务操作。
此API依赖于支持事务的状态存储组件。
请参阅状态存储组件规范以获取支持事务的状态存储的完整、当前列表。
HTTP请求
POST/PUT http://localhost:<daprPort>/v1.0/state/<storename>/transaction
HTTP响应代码
代码 | 描述 |
---|---|
204 |
请求成功 |
400 |
状态存储缺失或配置错误或请求格式错误 |
500 |
请求失败 |
URL参数
参数 | 描述 |
---|---|
daprPort |
Dapr端口 |
storename |
用户配置的statestore.yaml组件文件中的metadata.name 字段。请参阅上面提到的Dapr状态存储配置结构。 |
可选的请求元数据通过URL查询参数传递。例如,
POST http://localhost:3500/v1.0/state/myStore/transaction?metadata.contentType=application/json
注意,所有URL参数区分大小写。
请求体
字段 | 描述 |
---|---|
operations |
状态operation 的JSON数组 |
metadata |
(可选)适用于所有操作的事务metadata |
所有事务性数据库实现以下必需操作:
操作 | 描述 |
---|---|
upsert |
添加或更新值 |
delete |
删除值 |
每个操作都有一个关联的request
,由以下字段组成:
请求 | 描述 |
---|---|
key |
状态键 |
value |
状态值,可以是任何字节数组 |
etag |
(可选)状态ETag |
metadata |
(可选)要传递给状态存储的附加键值对,适用于此操作 |
options |
(可选)状态操作选项;请参阅状态操作选项 |
示例
下面的示例显示了key1
的upsert
操作和key2
的delete
操作。这适用于状态存储中名为’planet’的分区。两个操作在事务中要么成功要么失败。
curl -X POST http://localhost:3500/v1.0/state/starwars/transaction \
-H "Content-Type: application/json" \
-d '{
"operations": [
{
"operation": "upsert",
"request": {
"key": "key1",
"value": "myData"
}
},
{
"operation": "delete",
"request": {
"key": "key2"
}
}
],
"metadata": {
"partitionKey": "planet"
}
}'
为actor配置状态存储
actor不支持多个状态存储,并且需要使用事务性状态存储与Dapr一起使用。查看当前实现事务性状态存储接口的服务。
在statestore.yaml
组件文件的元数据部分中为属性actorStateStore
指定一个true
值,以指定用于actor的状态存储。
例如,以下组件yaml将配置Redis用作actor的状态存储。
apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
name: statestore
spec:
type: state.redis
version: v1
metadata:
- name: redisHost
value: <redis host>
- name: redisPassword
value: ""
- name: actorStateStore
value: "true"
可选行为
键方案
一个Dapr兼容的状态存储应使用以下键方案:
- <App ID>||<state key> 键格式用于一般状态
- <App ID>||<Actor type>||<Actor id>||<state key> 键格式用于actor状态。
并发
Dapr使用带有ETags的乐观并发控制(OCC)。Dapr对状态存储提出以下可选要求:
- 一个Dapr兼容的状态存储可以支持使用ETags的乐观并发控制。存储允许在ETag:
- 与保存或删除请求相关联时。
- 匹配数据库中的最新ETag时。
- 当写请求中缺少ETag时,状态存储应以最后写入优先的方式处理请求。这允许对高吞吐量写入场景进行优化,其中数据争用较低或没有负面影响。
- 存储在返回状态给调用者时应始终返回ETags。
一致性
Dapr允许客户端将一致性提示附加到获取、设置和删除操作。Dapr支持两种一致性级别:强一致性和最终一致性。
最终一致性
Dapr假定数据存储默认是最终一致的。状态应:
- 对于读取请求,从任何副本返回数据。
- 对于写入请求,在确认更新请求后异步复制更新到配置的法定人数。
强一致性
当附加了强一致性提示时,状态存储应:
- 对于读取请求,始终返回跨副本一致的最新数据。
- 对于写入/删除请求,在完成写入请求之前同步复制更新的数据到配置的法定人数。
示例:完整选项请求示例
以下是一个带有完整options
定义的设置请求示例:
curl -X POST http://localhost:3500/v1.0/state/starwars \
-H "Content-Type: application/json" \
-d '[
{
"key": "weapon",
"value": "DeathStar",
"etag": "xxxxx",
"options": {
"concurrency": "first-write",
"consistency": "strong"
}
}
]'
示例:使用ETags
以下是一个在兼容状态存储中设置/删除对象时使用ETag的示例演练。此示例将Redis定义为statestore
。
-
在状态存储中存储一个对象:
curl -X POST http://localhost:3500/v1.0/state/statestore \ -H "Content-Type: application/json" \ -d '[ { "key": "sampleData", "value": "1" } ]'
-
获取对象以查找由状态存储自动设置的ETag:
curl http://localhost:3500/v1.0/state/statestore/sampleData -v * Connected to localhost (127.0.0.1) port 3500 (#0) > GET /v1.0/state/statestore/sampleData HTTP/1.1 > Host: localhost:3500 > User-Agent: curl/7.64.1 > Accept: */* > < HTTP/1.1 200 OK < Server: fasthttp < Date: Sun, 14 Feb 2021 04:51:50 GMT < Content-Type: application/json < Content-Length: 3 < Etag: 1 < Traceparent: 00-3452582897d134dc9793a244025256b1-b58d8d773e4d661d-01 < * Connection #0 to host localhost left intact "1"* Closing connection 0
上述返回的ETag为1。如果您发送一个新的请求以错误的ETag更新或删除数据,它将返回错误。省略ETag将允许请求。
# 更新 curl -X POST http://localhost:3500/v1.0/state/statestore \ -H "Content-Type: application/json" \ -d '[ { "key": "sampleData", "value": "2", "etag": "2" } ]' {"errorCode":"ERR_STATE_SAVE","message":"failed saving state in state store statestore: possible etag mismatch. error from state store: ERR Error running script (call to f_83e03ec05d6a3b6fb48483accf5e594597b6058f): @user_script:1: user_script:1: failed to set key nodeapp||sampleData"} # 删除 curl -X DELETE -H 'If-Match: 5' http://localhost:3500/v1.0/state/statestore/sampleData {"errorCode":"ERR_STATE_DELETE","message":"failed deleting state with key sampleData: possible etag mismatch. error from state store: ERR Error running script (call to f_9b5da7354cb61e2ca9faff50f6c43b81c73c0b94): @user_script:1: user_script:1: failed to delete node app||sampleData"}
-
通过简单地在请求体(更新)或
If-Match
头(删除)中匹配ETag来更新或删除对象。当状态更新时,它会接收一个新的ETag,未来的更新或删除将需要使用。# 更新 curl -X POST http://localhost:3500/v1.0/state/statestore \ -H "Content-Type: application/json" \ -d '[ { "key": "sampleData", "value": "2", "etag": "1" } ]' # 删除 curl -X DELETE -H 'If-Match: 1' http://localhost:3500/v1.0/state/statestore/sampleData
下一步
Feedback
Was this page helpful?
Glad to hear it! Please tell us how we can improve.
Sorry to hear that. Please tell us how we can improve.