This is the multi-page printable view of this section. Click here to print.

Return to the regular view of this page.

状态存储组件规格

与 Dapr 对接的受支持状态存储

下表列出了 Dapr 状态管理构建块在不同级别上支持的状态存储。了解如何为 Dapr 状态管理配置不同的状态存储。

Table headers to note:

HeaderDescriptionExample
StatusComponent certification statusAlpha
Beta
Stable
Component versionThe version of the componentv1
Since runtime versionThe version of the Dapr runtime when the component status was set or updated1.11

Generic

ComponentCRUDTransactionalETagTTLActorsWorkflowStatusComponent versionSince runtime version
AerospikeTransactions: Not supportedTTL: Not supportedActors: Not supportedWorkflow: Not supportedAlphav11.0
Apache CassandraTransactions: Not supportedETag: Not supportedActors: Not supportedWorkflow: Not supportedStablev11.9
CockroachDBWorkflow: Not supportedStablev11.10
CouchbaseTransactions: Not supportedTTL: Not supportedActors: Not supportedWorkflow: Not supportedAlphav11.0
etcdBetav21.12
Hashicorp ConsulTransactions: Not supportedETag: Not supportedTTL: Not supportedActors: Not supportedWorkflow: Not supportedAlphav11.0
HazelcastTransactions: Not supportedETag: Not supportedTTL: Not supportedActors: Not supportedWorkflow: Not supportedAlphav11.0
In-memoryStablev11.9
JetStream KVTransactions: Not supportedETag: Not supportedTTL: Not supportedActors: Not supportedWorkflow: Not supportedAlphav11.7
MemcachedTransactions: Not supportedETag: Not supportedActors: Not supportedWorkflow: Not supportedStablev11.9
MongoDBStablev11.0
MySQL & MariaDBStablev11.10
Oracle DatabaseBetav11.7
PostgreSQL v1Stablev11.0
PostgreSQL v2Stablev21.13
RavenDBWorkflow: Not supportedStablev11.16
RedisStablev11.0
RethinkDBTransactions: Not supportedETag: Not supportedTTL: Not supportedActors: Not supportedWorkflow: Not supportedBetav11.9
SQLiteStablev11.11
ZookeeperTransactions: Not supportedTTL: Not supportedActors: Not supportedWorkflow: Not supportedAlphav11.0

Alibaba Cloud

ComponentCRUDTransactionalETagTTLActorsWorkflowStatusComponent versionSince runtime version
AliCloud TableStoreTransactions: Not supportedTTL: Not supportedActors: Not supportedWorkflow: Not supportedAlphav11.3

Amazon Web Services (AWS)

ComponentCRUDTransactionalETagTTLActorsWorkflowStatusComponent versionSince runtime version
AWS DynamoDBWorkflow: Not supportedStablev11.10

Cloudflare

ComponentCRUDTransactionalETagTTLActorsWorkflowStatusComponent versionSince runtime version
Cloudflare Workers KVTransactions: Not supportedETag: Not supportedActors: Not supportedWorkflow: Not supportedBetav11.10

Google Cloud Platform (GCP)

ComponentCRUDTransactionalETagTTLActorsWorkflowStatusComponent versionSince runtime version
GCP FirestoreTransactions: Not supportedETag: Not supportedTTL: Not supportedActors: Not supportedWorkflow: Not supportedStablev11.11

Microsoft Azure

ComponentCRUDTransactionalETagTTLActorsWorkflowStatusComponent versionSince runtime version
Azure Blob StorageTransactions: Not supportedTTL: Not supportedActors: Not supportedWorkflow: Not supportedStablev21.13
Azure Cosmos DBWorkflow: Not supportedStablev11.0
Azure Table StorageTransactions: Not supportedTTL: Not supportedActors: Not supportedWorkflow: Not supportedStablev11.9
Microsoft SQL Server V1Stablev11.5
Microsoft SQL Server V2Stablev21.17

Oracle Cloud

ComponentCRUDTransactionalETagTTLActorsWorkflowStatusComponent versionSince runtime version
Autonomous Database (ATP and ADW)Alphav11.7
CoherenceTransactions: Not supportedETag: Not supportedActors: Not supportedWorkflow: Not supportedAlphav11.16
Object StorageTransactions: Not supportedActors: Not supportedWorkflow: Not supportedAlphav11.6

1 - Aerospike

Aerospike 状态存储组件的详细信息

组件格式

要设置 Aerospike 状态存储,请创建一个类型为 state.Aerospike 的组件。有关如何创建和应用状态存储配置,请参阅此指南

apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
  name: <NAME>
spec:
  type: state.Aerospike
  version: v1
  metadata:
  - name: hosts
    value: <REPLACE-WITH-HOSTS> # 必填。以逗号分隔的主机字符串。示例:"aerospike:3000,aerospike2:3000"
  - name: namespace
    value: <REPLACE-WITH-NAMESPACE> # 必填。Aerospike 命名空间。
  - name: set
    value: <REPLACE-WITH-SET> # 可选

规格元数据字段

字段必填详情示例
hostsY数据库服务器的主机名/端口"localhost:3000", "aerospike:3000,aerospike2:3000"
namespaceYAerospike 命名空间"namespace"
setN数据库中的 setName"myset"

设置 Aerospike

您可以使用 Docker 在本地运行 Aerospike:

docker run -d --name aerospike -p 3000:3000 -p 3001:3001 -p 3002:3002 -p 3003:3003 aerospike

然后可以使用 localhost:3000 与服务器交互。

在 Kubernetes 上安装 Aerospike 最简单的方法是使用 Helm chart

helm repo add incubator http://storage.googleapis.com/kubernetes-charts-incubator
helm install --name my-aerospike --namespace aerospike stable/aerospike

这会将 Aerospike 安装到 aerospike 命名空间中。 要与 Aerospike 交互,使用以下命令查找服务:kubectl get svc aerospike -n aerospike

例如,如果使用上述示例安装,Aerospike 主机地址将是:

aerospike-my-aerospike.aerospike.svc.cluster.local:3000

相关链接

2 - Alibaba Cloud TableStore

关于用于 Dapr 的 Alibaba Cloud TableStore 状态存储组件的详细信息

组件格式

要设置 Alibaba Cloud TableStore 状态存储,请创建类型为 state.alicloud.tablestore 的组件。 请参阅此指南了解如何创建和应用状态存储配置。

apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
  name: <NAME>
spec:
  type: state.alicloud.tablestore
  version: v1
  metadata:
  - name: endpoint
    value: <REPLACE-WITH-ENDPOINT>
  - name: instanceName
    value: <REPLACE-WITH-INSTANCE-NAME>
  - name: tableName
    value: <REPLACE-WITH-TABLE-NAME>
  - name: accessKeyID
    value: <REPLACE-WITH-ACCESS-KEY-ID>
  - name: accessKey
    value: <REPLACE-WITH-ACCESS-KEY>

规格元数据字段

字段必填详情示例
endpointYAlibaba Cloud TableStore 实例的端点"https://tablestore.aliyuncs.com"
instanceNameYAlibaba Cloud TableStore 实例的名称"my_instance"
tableNameY用于 Dapr 状态的表的名称。如果不存在,将会创建它"my_table"
accessKeyIDY用于身份验证的访问密钥 ID"my_access_key_id"
accessKeyY用于身份验证的访问密钥"my_access_key"

身份验证

Alibaba Cloud TableStore 支持使用 Access KeyAccess Key ID 进行身份验证。

你也可以使用 Dapr 的 secret store 来安全地存储这些值,而不是直接将它们包含在 YAML 文件中。

使用密钥引用的示例:

- name: accessKeyID
  secretKeyRef:
    name: alicloud-secrets
    key: accessKeyID
- name: accessKey
  secretKeyRef:
    name: alicloud-secrets
    key: accessKey

相关链接

3 - AWS DynamoDB

AWS DynamoDB 状态存储组件的详细信息

组件格式

要设置 DynamoDB 状态存储,请创建类型为 state.aws.dynamodb 的组件。请参阅此指南了解如何创建和应用状态存储配置。

apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
  name: <NAME>
spec:
  type: state.aws.dynamodb
  version: v1
  metadata:
  - name: table
    value: "Contracts"
  - name: accessKey
    value: "AKIAIOSFODNN7EXAMPLE" # 可选
  - name: secretKey
    value: "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY" # 可选
  - name: endpoint
    value: "http://localhost:8080" # 可选
  - name: region
    value: "eu-west-1" # 可选
  - name: sessionToken
    value: "myTOKEN" # 可选
  - name: ttlAttributeName
    value: "expiresAt" # 可选
  - name: ttlInSeconds
    value: <int> # 可选
  - name: partitionKey
    value: "ContractID" # 可选
  # 如希望将 AWS DynamoDB 用作 actor 的状态存储,请取消此注释(可选)
  #- name: actorStateStore
  #  value: "true"

主键

为了将 DynamoDB 用作 Dapr 状态存储,表必须具有名为 key 的主键。有关更改此行为的选项,请参阅分区键部分。

规格元数据字段

字段必填详情示例
tableY要使用的 DynamoDB 表名"Contracts"
accessKeyN具有访问 SNS 和 SQS 适当权限的 AWS 账户 ID。可以是 secretKeyRef 以使用密钥引用"AKIAIOSFODNN7EXAMPLE"
secretKeyNAWS 用户的密钥。可以是 secretKeyRef 以使用密钥引用"wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"
regionN实例的 AWS 区域。有关有效区域,请参阅此页面:https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Concepts.RegionsAndAvailabilityZones.html。确保该区域支持 DynamoDB。"us-east-1"
endpointN组件要使用的 AWS 端点。仅用于本地开发。针对生产 AWS 运行时不需要 endpoint"http://localhost:4566"
sessionTokenN要使用的 AWS 会话令牌。仅在使用临时安全凭证时才需要会话令牌。"TOKEN"
ttlAttributeNameN应用于 TTL 的表属性名称。"expiresAt"
ttlInSecondsN允许指定以秒为单位的生存时间(TTL),该 TTL 将应用于每个状态存储请求,除非通过请求元数据明确定义了 TTL。如果设置为零或更小,则不会应用默认 TTL,并且只有在设置了 ttlAttributeName 且在请求元数据中明确提供了 TTL 时,项目才会过期。600
partitionKeyN表主键或分区键属性名称。此字段用于替换默认主键属性名称 "key"。请参阅分区键部分。"ContractID"
actorStateStoreN将此状态存储用于 actor。默认为 “false”"true", "false"

设置 AWS DynamoDB

有关身份验证相关属性的信息,请参阅向 AWS 进行身份验证

生存时间(TTL)

要使用 DynamoDB TTL 功能,您必须在表上启用 TTL 并定义属性名称。 属性名称必须在 ttlAttributeName 字段中定义。 请参阅官方 AWS 文档

分区键

默认情况下,DynamoDB 状态存储组件使用表属性名称 key 作为 DynamoDB 表中的主键/分区键。 可以通过在组件配置中指定元数据字段来覆盖,其键为 partitionKey,值为所需的属性名称。

要了解有关 DynamoDB 主键/分区键的更多信息,请阅读 AWS DynamoDB 开发者指南。

以下 statestore.yaml 文件显示了如何配置 DynamoDB 状态存储组件以使用分区键属性名称 ContractID

apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
  name: statestore
spec:
  type: state.aws.dynamodb
  version: v1
  metadata:
  - name: table
    value: "Contracts"
  - name: partitionKey
    value: "ContractID"

上述组件规格假定以下 DynamoDB 表布局:

{
    "Table": {
        "AttributeDefinitions": [
            {
                "AttributeName": "ContractID",
                "AttributeType": "S"
            }
        ],
        "TableName": "Contracts",
        "KeySchema": [
            {
                "AttributeName": "ContractID",
                "KeyType": "HASH"
            }
        ],
}

以下操作将 "A12345" 作为 key 的值传递,根据上面提供的组件规格,Dapr 运行时将把 key 属性名称 替换为 ContractID,作为发送到 DynamoDB 的分区/主键:

$ dapr run --app-id contractsprocessing --app-port ...

$ curl -X POST http://localhost:3500/v1.0/state/<store_name> \
  -H "Content-Type: application/json"
  -d '[
        {
          "key": "A12345",
          "value": "Dapr Contract"
        }
      ]'

以下 AWS CLI 命令显示 DynamoDB Contracts 表的内容:

$ aws dynamodb get-item \
    --table-name Contracts \
    --key '{"ContractID":{"S":"contractsprocessing||A12345"}}' 
{
    "Item": {
        "value": {
            "S": "Dapr Contract"
        },
        "etag": {
            "S": "....."
        },
        "ContractID": {
            "S": "contractsprocessing||A12345"
        }
    }
}

工作流限制

工作流越复杂(活动数量、子工作流等),它在每个状态存储事务中执行的状态操作就越多。 DynamoDB 在单个事务中可以执行的最大操作数为 100。 这意味着 DynamoDB 只能处理复杂度有限的工作流,因此并不适合所有工作流场景。 有关在工作流执行期间保存的记录数量的一般指南,可在此处找到。

相关链接

4 - Azure Blob Storage

Azure Blob Store 状态存储组件的详细信息

组件格式

要设置 Azure Blob Storage 状态存储,需创建类型为 state.azure.blobstorage 的组件。请参阅本指南了解如何创建并应用状态存储配置。

apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
  name: <NAME>
spec:
  type: state.azure.blobstorage
  # 支持 v1 和 v2。用户应始终默认使用 v2。没有从 v1 到 v2 的迁移路径,参见下面的 `versioning`。
  version: v2
  metadata:
  - name: accountName
    value: "[your_account_name]"
  - name: accountKey
    value: "[your_account_key]"
  - name: containerName
    value: "[your_container_name]"

版本

Dapr 有 2 个版本的 Azure Blob Storage 状态存储组件:v1v2。建议所有新应用程序使用 v2v1 被视为旧版本,仅为了与现有应用程序兼容而保留。

v1 中,发现了一个长期存在的实现问题,其中组件错误地剥离了键前缀,其行为本质上就像 keyPrefix 总是被设置为 none
组件的更新版本 v2 修复了此错误行为,并使状态存储正确遵守 keyPrefix 属性。

虽然 v1v2 具有相同的元数据字段,但它们在其他方面不兼容,并且没有从 v1v2 的自动数据迁移路径。

如果您正在使用此组件的 v1 版本,则应继续使用 v1,直到创建新的状态存储。

规格元数据字段

字段必填详情示例
accountNameY存储账户名称"mystorageaccount"
accountKeyY(除非使用 Microsoft Entra ID)主存储密钥或辅助存储密钥"key"
containerNameY用于 Dapr 状态的容器的名称。如果容器不存在,将为您创建该容器"container"
azureEnvironmentN如果使用不同的 Azure 云,则为 Azure 环境的可选名称"AZUREPUBLICCLOUD"(默认值)、"AZURECHINACLOUD""AZUREUSGOVERNMENTCLOUD"
endpointN可选的自定义终结点 URL。当使用 Azurite 模拟器或为 Azure Storage 使用自定义域时(尽管这不是官方支持的),这很有用。终结点必须是完整的基本 URL,包括协议(http://https://)、IP 或 FQDN 以及可选端口。"http://127.0.0.1:10000"
ContentTypeNblob 的内容类型"text/plain"
ContentMD5Nblob 的 MD5 哈希"vZGKbMRDAnMs4BIwlXaRvQ=="
ContentEncodingNblob 的内容编码"UTF-8"
ContentLanguageNblob 的内容语言"en-us"
ContentDispositionNblob 的内容处置。传达有关如何处理响应负载的其他信息"attachment"
CacheControlNblob 的缓存控制"no-cache"

设置 Azure Blob Storage

按照说明从 Azure 文档中了解如何创建 Azure 存储账户。

如果您希望为 Dapr 创建一个要使用的容器,可以预先创建。但是,如果 Blob Storage 状态提供程序不存在,它将自动为您创建一个。

为了将 Azure Blob Storage 设置为状态存储,您需要以下属性:

  • accountName:存储账户名称。例如:mystorageaccount
  • accountKey:主存储账户密钥或辅助存储账户密钥。
  • containerName:用于 Dapr 状态的容器的名称。如果容器不存在,将为您创建该容器。

使用 Microsoft Entra ID 进行身份验证

此组件支持使用 Microsoft Entra ID 进行身份验证,作为使用账户密钥的替代方法。在可能的情况下,建议在生产系统中使用 Microsoft Entra ID 进行身份验证,以利用更好的安全性、精细的访问控制以及为在 Azure 上运行的应用程序使用托管标识的能力。

以下脚本针对 bash 或 zsh shell 进行了优化,并且需要安装以下应用程序:

您还必须在 Azure CLI 中通过 Azure 身份验证。

  1. 要开始使用 Microsoft Entra ID 对 Blob Storage 状态存储组件进行身份验证,请确保您已创建 Microsoft Entra ID 应用程序和服务主体,如向 Azure 进行身份验证文档中所述。
    完成后,使用您创建的服务主体的 ID 设置一个变量:
SERVICE_PRINCIPAL_ID="[your_service_principal_object_id]"
  1. 使用您的 Azure 存储账户的名称及其所在的资源组的名称设置以下变量:
STORAGE_ACCOUNT_NAME="[your_storage_account_name]"
RG_NAME="[your_resource_group_name]"
  1. 使用 RBAC 为我们的服务主体分配一个角色,以便它可以访问存储账户内的数据。
    在这种情况下,您分配的是"Storage blob Data Contributor"角色,该角色具有广泛的访问权限;根据您的应用程序,也可以使用其他更严格的角色。
RG_ID=$(az group show --resource-group ${RG_NAME} | jq -r ".id")
az role assignment create \
  --assignee "${SERVICE_PRINCIPAL_ID}" \
  --role "Storage blob Data Contributor" \
  --scope "${RG_ID}/providers/Microsoft.Storage/storageAccounts/${STORAGE_ACCOUNT_NAME}"

当使用 Microsoft Entra ID 对组件进行身份验证时,不需要 accountKey 字段。相反,请根据向 Azure 进行身份验证文档,在组件的元数据中指定所需的凭据(如果有)。

例如:

apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
  name: <NAME>
spec:
  type: state.azure.blobstorage
  version: v1
  metadata:
  - name: accountName
    value: "[your_account_name]"
  - name: containerName
    value: "[your_container_name]"
  - name: azureTenantId
    value: "[your_tenant_id]"
  - name: azureClientId
    value: "[your_client_id]"
  - name: azureClientSecret
    value : "[your_client_secret]"

应用配置

在 Kubernetes 中

要将 Azure Blob Storage 状态存储应用于 Kubernetes,请使用 kubectl CLI:

kubectl apply -f azureblob.yaml

本地运行

要在本地运行,请创建一个包含 YAML 文件的 components 目录,并使用标志 --resources-path 将路径提供给 dapr run 命令。

此状态存储在容器中创建一个 blob 文件,并将原始状态放入其中。

例如,来自名为 myservice 的服务的以下操作:

curl -X POST http://localhost:3500/v1.0/state \
  -H "Content-Type: application/json"
  -d '[
        {
          "key": "nihilus",
          "value": "darth"
        }
      ]'

这将在容器中创建 blob 文件,其中 key 作为文件名,value 作为文件的内容。

并发

根据 Azure Blob Storage 文档,通过使用 ETag 来实现 Azure Blob Storage 状态并发。

相关链接

5 - Azure Cosmos DB (SQL API)

Azure Cosmos DB (SQL API) 状态存储组件的详细信息

组件格式

要设置 Azure Cosmos DB 状态存储,请创建类型为 state.azure.cosmosdb 的组件。请参阅此指南了解如何创建和应用状态存储配置。

apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
  name: <NAME>
spec:
  type: state.azure.cosmosdb
  version: v1
  metadata:
  - name: url
    value: <REPLACE-WITH-URL>
  - name: masterKey
    value: <REPLACE-WITH-MASTER-KEY>
  - name: database
    value: <REPLACE-WITH-DATABASE>
  - name: collection
    value: <REPLACE-WITH-COLLECTION>
  # 如果您希望使用 Azure Cosmos DB 作为 actor 的状态存储,请取消注释此选项(可选)
  #- name: actorStateStore
  #  value: "true"

如果您希望将 Cosmos DB 用作 actor 存储,请在 yaml 中添加以下内容。

  - name: actorStateStore
    value: "true"

规范元数据字段

字段必填详情示例
urlYCosmos DB 的 URL"https://******.documents.azure.com:443/"
masterKeyY*用于向 Cosmos DB 账户进行身份验证的密钥。仅在不使用 Microsoft Entra ID 身份验证时需要。"key"
databaseY数据库的名称"db"
collectionY集合(容器)的名称"collection"
actorStateStoreN将此状态存储用于 actor。默认为 "false""true", "false"

Microsoft Entra ID 身份验证

Azure Cosmos DB 状态存储组件支持使用所有 Microsoft Entra ID 机制进行身份验证。有关更多信息以及根据选择的 Microsoft Entra ID 身份验证机制需要提供的组件元数据字段,请参阅 Azure 身份验证文档

您可以在下方的部分中阅读有关使用 Azure AD 身份验证设置 Cosmos DB 的更多信息。

设置 Azure Cosmos DB

按照说明从 Azure 文档中了解如何创建 Azure Cosmos DB 账户。数据库和集合必须在 Dapr 使用之前在 Cosmos DB 中创建。

重要:集合的分区键必须命名为 /partitionKey(注意:这是区分大小写的)。

为了将 Cosmos DB 设置为状态存储,您需要以下属性:

  • URL:Cosmos DB 的 URL。例如:https://******.documents.azure.com:443/
  • 主密钥:用于向 Cosmos DB 账户进行身份验证的密钥。如果使用 Microsoft Entra ID 身份验证,请跳过此项。
  • 数据库:数据库的名称
  • 集合:集合(或容器)的名称

TTL 和清理

此状态存储支持使用 Dapr 存储的记录的生存时间 (TTL)。使用 Dapr 存储数据时,您可以设置 ttlInSeconds 元数据属性以覆盖 CosmodDB 容器上的默认 TTL,指示数据何时应被视为"已过期"。请注意,只有当容器的 DefaultTimeToLive 字段具有非 NULL 值时,此值才会生效。有关更多信息,请参阅 CosmosDB 文档

生产环境的最佳实践

Azure Cosmos DB 在单个 Azure Cosmos DB 账户的所有数据库之间共享严格的可接受的元数据请求速率限制。与 Azure Cosmos DB 的新连接会占用可接受的请求速率限制的很大一部分。(请参阅 Cosmos DB 文档

因此,必须应用多种策略来避免同时建立与 Azure Cosmos DB 的新连接:

  • 确保应用程序的边车仅在需要时才加载 Azure Cosmos DB 组件,以避免不必要的数据库连接。这可以通过将组件范围限定到特定应用程序来实现。
  • 选择顺序部署或启动应用程序的部署策略,以最大程度减少对 Azure Cosmos DB 账户的新连接突发。
  • 避免为不相关的数据库或系统重用同一个 Azure Cosmos DB 账户(即使在 Dapr 之外)。不同的 Azure Cosmos DB 账户具有不同的速率限制。
  • 增加 initTimeout 值以允许组件在边车初始化期间重试连接 Azure Cosmos DB,最多 5 分钟。默认值为 5s,应该增加。使用 Kubernetes 时,增加此值可能还需要更新您的 Readiness 和 Liveness 探测
spec:
  type: state.azure.cosmosdb
  version: v1
  initTimeout: 5m
  metadata:

数据格式

要使用 Cosmos DB 状态存储,您的数据必须以 JSON 序列化格式发送到 Dapr。仅具有 JSON 可序列化是不够的。

如果您使用的是 Dapr SDK(例如 .NET SDK),SDK 会自动将您的数据序列化为 JSON。

如果您想直接调用 Dapr 的 HTTP 端点,请查看下面 分区键 部分中的示例(使用 curl)。

分区键

对于 非 actor 状态操作,Azure Cosmos DB 状态存储将使用对 Dapr API 的请求中提供的 key 属性来确定 Cosmos DB 分区键。可以通过在请求中指定元数据字段来覆盖此设置,该元数据字段的键为 partitionKey,值为所需的分区。

以下操作使用 nihilus 作为发送到 Cosmos DB 的分区键值:

curl -X POST http://localhost:3500/v1.0/state/<store_name> \
  -H "Content-Type: application/json"
  -d '[
        {
          "key": "nihilus",
          "value": "darth"
        }
      ]'

对于 非 actor 状态操作,如果您想控制 Cosmos DB 分区,可以在元数据中指定它。重用上面的示例,以下是如何将其放在 mypartition 分区下

curl -X POST http://localhost:3500/v1.0/state/<store_name> \
  -H "Content-Type: application/json"
  -d '[
        {
          "key": "nihilus",
          "value": "darth",
          "metadata": {
            "partitionKey": "mypartition"
          }
        }
      ]'

对于 actor 状态操作,分区键由 Dapr 使用 appId、actor 类型和 actor id 生成,使得同一 actor 的数据始终位于同一分区下(您无需指定它)。这是因为 actor 状态操作必须使用事务,而在 Cosmos DB 中,事务中的项目必须位于同一分区上。

为使用 Microsoft Entra ID 进行身份验证而设置 Cosmos DB

使用 Dapr Cosmos DB 状态存储并通过 Microsoft Entra ID 进行身份验证时,您需要执行一些额外步骤来设置环境。

先决条件:

  • 您需要按照 Azure 身份验证 页面上的说明创建一个服务主体。以下命令需要服务主体的 ID(请注意,这与您的应用程序的客户端 ID 或您在元数据中用于 azureClientId 的值不同)。
  • Azure CLI
  • jq
  • 以下脚本针对 bash 或 zsh shell 进行了优化

授予您的 Microsoft Entra ID 应用程序对 Cosmos DB 的访问权限

您可以在官方文档中找到更多信息,包括分配更细粒度权限的说明。

为了授予您的应用程序访问存储在 Cosmos DB 中的数据的权限,您需要为其分配 Cosmos DB 数据平面的自定义角色。在此示例中,您将使用内置角色"Cosmos DB 内置数据参与者",该角色授予您的应用程序对数据的完全读写访问权限;您可以选择按照官方文档中的说明创建自定义的、精细的角色。

# 包含您的 Cosmos DB 的资源组名称
RESOURCE_GROUP="..."
# 您的 Cosmos DB 账户名称
ACCOUNT_NAME="..."
# 您的服务主体对象的 ID
PRINCIPAL_ID="..."
# "Cosmos DB 内置数据参与者"角色的 ID
# 您也可以使用自定义角色的 ID
ROLE_ID="00000000-0000-0000-0000-000000000002"

az cosmosdb sql role assignment create \
  --account-name "$ACCOUNT_NAME" \
  --resource-group "$RESOURCE_GROUP" \
  --scope "/" \
  --principal-id "$PRINCIPAL_ID" \
  --role-definition-id "$ROLE_ID"

优化

优化 Cosmos DB 以实现批量操作写入性能

如果您构建的系统仅通过键 (id) 从 Cosmos DB 读取数据,这是使用状态管理 API 或 actor 时的默认 Dapr 行为,您可以通过一些方式优化 Cosmos DB 以提高写入速度。这是通过从索引中排除所有路径来实现的。默认情况下,Cosmos DB 对文档内的所有字段进行索引。在写入繁重的系统上,并且对文档内的值运行很少或没有查询的情况下,此索引策略会减慢在 Cosmos DB 中写入或更新文档的时间。这在大量系统中会更加严重。

例如,Cosmos SQL 容器索引的默认 Terraform 定义如下:

indexing_policy {
  indexing_mode = "consistent"

  included_path {
    path = "/*"
  }
}

可以通过从索引中排除所有其他字段来强制 Cosmos DB 仅索引 idpartitionKey 字段。这可以通过将上述内容更新为以下内容来实现:

indexing_policy {
  # 如果您纯粹将容器用作键值存储,这也可以设置为 "none"。如果您的容器仅用作分布式缓存,这可能适用。
  indexing_mode = "consistent" 

  # 请注意,included_path 已被替换为 excluded_path
  excluded_path {
    path = "/*"
  }
}

优化 Cosmos DB 以节省成本

如果您打算仅将 Cosmos DB 用作键值对,可能会考虑将状态对象转换为 JSON 并在持久化到状态之前对其进行压缩,然后在从状态中读取时对其进行解压缩,这可能符合您的利益。这是因为 Cosmos DB 根据给定时间段(通常是每小时)内使用的最大 RU/s 数向您收费。此外,RU 使用量计算为每读取或写入 1 KB 数据 1 RU。压缩通过减少存储在 Cosmos DB 中的数据大小来帮助减少 RU 使用量。

这种节省对于 Dapr actor 来说特别重要。虽然 Dapr 状态管理 API 在保存之前对对象进行 base64 编码,但 Dapr actor 状态以原始格式化的 JSON 形式保存。这意味着多行带有缩进用于格式化。压缩可以显着减少 actor 状态对象的大小。例如,如果您有一个 actor 状态对象,在 actor 水合时大小为 75KB,您将使用 75 RU/s 从状态中读取该对象。如果您随后修改状态对象并将其增长到 100KB,您将使用 100 RU/s 将该对象写入 Cosmos DB,总共 175 RU/s 用于 I/O 操作。假设您的 actor 每秒并发处理 1000 个请求,您将至少需要 175,000 RU/s 才能满足该负载。通过有效的压缩,大小减少可以达到 90% 左右,这意味着您只需要大约 17,500 RU/s 就能满足负载。

工作流限制

工作流越复杂,包含的活动数量、子工作流等越多,每个状态存储事务执行的 DB 状态操作就越多。 所有输入和输出值都保存到工作流历史记录中,并且是这些事务操作的一部分。 CosmosDB 的最大文档大小为 2MB,最大事务大小为 100 个操作。 尝试超出这些限制写入 CosmosDB 会导致错误代码 413。 这意味着工作流历史记录不得超过此大小,这意味着 CosmosDB 不适合具有大型输入/输出值或更复杂的工作流。 有关在工作流执行期间保存的记录数量的一般指南,可以在此处找到。

相关链接

6 - Azure Table Storage

关于 Azure Table Storage 状态存储组件的详细信息,该组件可用于连接到 Cosmos DB Table API 和 Azure Tables

组件格式

要设置 Azure Tablestorage 状态存储,请创建一个类型为 state.azure.tablestorage 的组件。请参阅本指南了解如何创建和应用状态存储配置。

apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
  name: <NAME>
spec:
  type: state.azure.tablestorage
  version: v1
  metadata:
  - name: accountName
    value: <REPLACE-WITH-ACCOUNT-NAME>
  - name: accountKey
    value: <REPLACE-WITH-ACCOUNT-KEY>
  - name: tableName
    value: <REPLACE-WITH-TABLE-NAME>
# - name: cosmosDbMode
#   value: false

规范元数据字段

字段必填详情示例
accountNameY存储账户名称"mystorageaccount"
accountKeyY主密钥或辅助存储密钥"key"
tableNameY用于 Dapr 状态的表的名称。如果表不存在,将自动为你创建"table"
cosmosDbModeN如果启用,则连接到 Cosmos DB Table API 而非 Azure Tables(存储账户)。默认为 false"false"
serviceURLN完整的存储服务终结点 URL。适用于公有云之外的 Azure 环境。"https://mystorageaccount.table.core.windows.net/"
skipCreateTableN跳过对指定存储表的检查(以及在必要时创建该表)。在使用具有最小权限的 Active Directory 身份验证时很有用。默认为 false"true"

Microsoft Entra ID 身份验证

Azure Cosmos DB 状态存储组件支持使用所有 Microsoft Entra ID 机制进行身份验证。有关更多信息以及根据所选的 Microsoft Entra ID 身份验证机制需要提供的相关组件元数据字段,请参阅向 Azure 进行身份验证的文档

你可以在下一节中阅读有关使用 Microsoft Entra ID 身份验证设置 Cosmos DB 的其他信息。

选项 1:设置 Azure Table Storage

按照 Azure 文档中的说明创建 Azure 存储账户。

如果你希望为 Dapr 创建一个表,可以提前创建。不过,除非启用了 skipCreateTable 选项,否则如果表不存在,Table Storage 状态提供程序会自动为你创建一个。

要设置 Azure Table Storage 作为状态存储,你需要以下属性:

  • AccountName:存储账户名称。例如:mystorageaccount
  • AccountKey:主密钥或辅助存储密钥。如果使用 Microsoft Entra ID 身份验证,请跳过此项。
  • TableName:用于 Dapr 状态的表的名称。如果表不存在,将自动为你创建,除非启用了 skipCreateTable 选项。
  • cosmosDbMode:将此项设置为 false 以连接到 Azure Tables。

选项 2:设置 Azure Cosmos DB Table API

按照 Azure 文档中的说明创建一个具有 Table API 的 Cosmos DB 账户。

如果你希望为 Dapr 创建一个表,可以提前创建。不过,除非启用了 skipCreateTable 选项,否则如果表不存在,Table Storage 状态提供程序会自动为你创建一个。

要设置 Azure Cosmos DB Table API 作为状态存储,你需要以下属性:

  • AccountName:Cosmos DB 账户名称。例如:mycosmosaccount
  • AccountKey:Cosmos DB 主密钥。如果使用 Microsoft Entra ID 身份验证,请跳过此项。
  • TableName:用于 Dapr 状态的表的名称。如果表不存在,将自动为你创建,除非启用了 skipCreateTable 选项。
  • cosmosDbMode:将此项设置为 true 以连接到 Azure Tables。

分区

Azure Table Storage 状态存储使用在 Dapr API 请求中提供的 key 属性来确定 row key。服务名称用作 partition key。这提供了最佳性能,因为每种服务类型在自己的表分区中存储状态。

此状态存储在表存储中创建一个名为 Value 的列,并将原始状态放入其中。

例如,以下来自名为 myservice 的服务的操作

curl -X POST http://localhost:3500/v1.0/state \
  -H "Content-Type: application/json"
  -d '[
        {
          "key": "nihilus",
          "value": "darth"
        }
      ]'

将在表中创建以下记录:

PartitionKeyRowKeyValue
myservicenihilusdarth

并发

Azure Table Storage 状态并发是通过根据官方文档使用 ETag 来实现的。

相关链接

7 - Cassandra

Cassandra 状态存储组件的详细信息

组件格式

要设置 Cassandra 状态存储,请创建类型为 state.cassandra 的组件。请参阅本指南了解如何创建和应用状态存储配置。

apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
  name: <NAME>
spec:
  type: state.cassandra
  version: v1
  metadata:
  - name: hosts
    value: <REPLACE-WITH-COMMA-DELIMITED-HOSTS> # 必填。示例:cassandra.cassandra.svc.cluster.local
  - name: username
    value: <REPLACE-WITH-PASSWORD> # 可选。默认值:""
  - name: password
    value: <REPLACE-WITH-PASSWORD> # 可选。默认值:""
  - name: consistency
    value: <REPLACE-WITH-CONSISTENCY> # 可选。默认值:"All"
  - name: table
    value: <REPLACE-WITH-TABLE> # 可选。默认值:"items"
  - name: keyspace
    value: <REPLACE-WITH-KEYSPACE> # 可选。默认值:"dapr"
  - name: protoVersion
    value: <REPLACE-WITH-PROTO-VERSION> # 可选。默认值:"4"
  - name: replicationFactor
    value: <REPLACE-WITH-REPLICATION-FACTOR> #  可选。默认值:"1"

规范元数据字段

字段必填详情示例
hostsY主机的逗号分隔值"cassandra.cassandra.svc.cluster.local"
portN通信端口。默认值为 "9042""9042"
usernameY数据库用户的用户名。无默认值"user"
passwordY用户的密码"password"
consistencyN一致性值"All""Quorum"
tableN表名。默认值为 "items""items""tab"
keyspaceN要使用的 Cassandra 键空间。默认值为 "dapr""dapr"
protoVersionN客户端的协议版本。默认值为 "4""3""4"
replicationFactorN调用的复制因子。默认值为 "1""3"

设置 Cassandra

您可以使用 Datastax Docker 镜像在本地运行 Cassandra:

docker run -e DS_LICENSE=accept --memory 4g --name my-dse -d datastax/dse-server -g -s -k

然后您可以使用 localhost:9042 与服务器交互。

在 Kubernetes 上安装 Cassandra 最简单的方法是使用 Helm chart

kubectl create namespace cassandra
helm install cassandra incubator/cassandra --namespace cassandra

这将默认把 Cassandra 安装到 cassandra 命名空间中。 要与 Cassandra 交互,请使用以下命令查找服务:kubectl get svc -n cassandra

例如,如果使用上述示例安装,Cassandra DNS 将是:

cassandra.cassandra.svc.cluster.local

Apache Ignite

Apache Ignite 与作为缓存层的 Cassandra 集成不被此组件支持。

Apache Ignite

Apache Ignite 与作为缓存层的 Cassandra 集成不被此组件支持。

Apache Ignite

Apache Ignite 与作为缓存层的 Cassandra 集成不被此组件支持。

相关链接

8 - Cloudflare Workers KV

Cloudflare Workers KV 状态存储组件的详细信息

创建 Dapr 组件

要设置 Cloudflare Workers KV 状态存储,请创建一个类型为 state.cloudflare.workerskv 的组件。请参阅此指南了解如何创建和应用状态存储配置。

apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
  name: <NAME>
spec:
  type: state.cloudflare.workerskv
  version: v1
  # 如果 Dapr 为您管理 Worker,请增加 initTimeout
  initTimeout: "120s"
  metadata:
    # Workers KV 命名空间的 ID(必需)
    - name: kvNamespaceID
      value: ""
    # Worker 的名称(必需)
    - name: workerName
      value: ""
    # PEM 编码的 Ed25519 私钥(必需)
    - name: key
      value: |
        -----BEGIN PRIVATE KEY-----
        MC4CAQ...
        -----END PRIVATE KEY-----
    # Cloudflare 账户 ID(让 Dapr 管理 Worker 时必需)
    - name: cfAccountID
      value: ""
    # Cloudflare 的 API 令牌(让 Dapr 管理 Worker 时必需)
    - name: cfAPIToken
      value: ""
    # Worker 的 URL(如果在 Dapr 外部预先创建了 Worker 则必需)
    - name: workerUrl
      value: ""

规范元数据字段

字段必填详情示例
kvNamespaceIDY预先创建的 Workers KV 命名空间的 ID"123456789abcdef8b5588f3d134f74ac"
workerNameY要连接的 Worker 的名称"mydaprkv"
keyYEd25519 私钥,PEM 编码参见上文示例
cfAccountIDY/NCloudflare 账户 ID。让 Dapr 管理 Worker 时必需。"456789abcdef8b5588f3d134f74ac"def
cfAPITokenY/NCloudflare 的 API 令牌。让 Dapr 管理 Worker 时必需。"secret-key"
workerUrlY/NWorker 的 URL。如果在 Dapr 外部预先预配了 Worker 则必需。"https://mydaprkv.mydomain.workers.dev"

当您配置 Dapr 为您创建 Worker 时,可能需要为组件的 initTimeout 属性设置更长的值,以留出足够的时间来部署 Worker 脚本。例如:initTimeout: "120s"

创建 Workers KV 命名空间

要使用此组件,您必须在您的 Cloudflare 账户中创建一个 Workers KV 命名空间。

您可以通过以下两种方式之一创建新的 Workers KV 命名空间:

  • 使用 Cloudflare 控制面板
    记下您在控制面板中可以看到的 Workers KV 命名空间的 “ID”。这是一个十六进制字符串(例如 123456789abcdef8b5588f3d134f74ac)——不是您创建时使用的名称!

  • 使用 Wrangler CLI

    # 如需身份验证,首先运行 `npx wrangler login`
    wrangler kv:namespace create <NAME>
    

    输出包含命名空间的 ID,例如:

    { binding = "<NAME>", id = "123456789abcdef8b5588f3d134f74ac" }
    

配置 Worker

由于 Cloudflare Workers KV 命名空间只能由在 Workers 上运行的脚本访问,Dapr 需要维护一个 Worker 来与 Workers KV 存储进行通信。

Dapr 可以自动为您管理 Worker,或者您可以自己预先预配一个 Worker。在 workerd 上运行时,预先预配 Worker 是唯一支持的选项。

如果您想让 Dapr 为您管理 Worker,您需要提供以下 3 个元数据选项:

  • workerName:Worker 脚本的名称。这将是您的 Worker URL 的第一部分。例如,如果为您的 Cloudflare 账户配置的 “workers.dev” 域是 mydomain.workers.dev,并且您将 workerName 设置为 mydaprkv,Dapr 部署的 Worker 将在 https://mydaprkv.mydomain.workers.dev 访问。
  • cfAccountID:您的 Cloudflare 账户的 ID。登录 Cloudflare 控制面板后,您可以在浏览器地址栏中找到它,ID 是 dash.cloudflare.com 右侧的十六进制字符串。例如,如果 URL 是 https://dash.cloudflare.com/456789abcdef8b5588f3d134f74acdef,则 cfAccountID 的值是 456789abcdef8b5588f3d134f74acdef
  • cfAPIToken:具有创建和编辑 Workers 及 Workers KV 命名空间权限的 API 令牌。您可以在 Cloudflare 控制面板的 “My Profile” 部分的 “API Tokens” 页面中创建它:
    1. 点击 “Create token”
    2. 选择 “Edit Cloudflare Workers” 模板。
    3. 按照屏幕上的说明生成新的 API 令牌。

当 Dapr 配置为为您管理 Worker 时,当 Dapr 运行时启动时,它会检查 Worker 是否存在且是最新的。如果 Worker 不存在,或者使用的是过时的版本,Dapr 将自动为您创建或升级它。

如果您不想授予 Dapr 为您部署 Worker 脚本的权限,可以手动预配一个 Worker 供 Dapr 使用。请注意,如果您有多个 Dapr 组件通过 Worker 与 Cloudflare 服务交互,您需要为每个组件创建一个单独的 Worker。

要手动预配 Worker 脚本,您需要在本地机器上安装 Node.js。

  1. 创建一个新文件夹来放置 Worker 的源代码,例如:daprworker
  2. 如果尚未完成,请使用以下命令通过 Wrangler(Cloudflare Workers CLI)进行身份验证:npx wrangler login
  3. 在新创建的文件夹中,创建一个新的 wrangler.toml 文件,内容如下,并根据需要填写缺失的信息:
# 您的 Worker 的名称,例如 "mydaprkv"
name = ""

# 不要更改这些选项
main = "worker.js"
compatibility_date = "2022-12-09"
usage_model = "bundled"

[vars]
# 将此设置为 Ed25519 密钥的**公钥**部分,PEM 编码(换行符替换为 `\n`)。
# 示例:
# PUBLIC_KEY = "-----BEGIN PUBLIC KEY-----\nMCowB...=\n-----END PUBLIC KEY-----
PUBLIC_KEY = ""
# 将此设置为您的 Worker 的名称(与上方的 "name" 属性值相同),例如 "mydaprkv"。
TOKEN_AUDIENCE = ""

[[kv_namespaces]]
# 将以下两个值设置为您的 KV 命名空间的 ID(而不是名称),例如 "123456789abcdef8b5588f3d134f74ac"。
# 请注意,它们将被设置为相同的值。
binding = ""
id = ""

注意:有关如何生成 Ed25519 密钥对,请参阅下一节。确保在部署 Worker 时使用密钥的公钥部分!

  1. 将 Worker 的(预编译和压缩的)代码复制到 worker.js 文件中。您可以使用以下命令执行此操作:
# 将此设置为您正在使用的 Dapr 版本
DAPR_VERSION="release-1.18"
curl -LfO "https://raw.githubusercontent.com/dapr/components-contrib/${DAPR_VERSION}/internal/component/cloudflare/workers/code/worker.js"
  1. 使用 Wrangler 部署 Worker:
npx wrangler publish

Worker 部署完成后,您需要使用以下两个元数据选项来初始化组件:

  • workerName:Worker 脚本的名称。这是您在 wrangler.toml 文件的 name 属性中设置的值。
  • workerUrl:已部署的 Worker 的 URL。npx wrangler command 将显示完整的 URL,例如 https://mydaprkv.mydomain.workers.dev

生成 Ed25519 密钥对

所有 Cloudflare Workers 都监听公共 Internet,因此 Dapr 需要使用额外的身份验证和数据保护措施来确保没有其他人员或应用程序可以与您的 Worker 通信(进而与您的 Worker KV 命名空间通信)。这些措施包括行业标准措施,例如:

  • Dapr 向 Worker 发出的所有请求都通过不记名令牌(技术上是 JWT)进行身份验证,该令牌使用 Ed25519 密钥签名。
  • Dapr 与您的 Worker 之间的所有通信都通过加密连接进行,使用 TLS (HTTPS)。
  • 不记名令牌在每个请求上生成,仅在很短的时间内有效(目前为一分钟)。

要让 Dapr 颁发不记名令牌并让您的 Worker 验证它们,您需要生成一个新的 Ed25519 密钥对。以下是使用 OpenSSL 或 step CLI 生成密钥对的示例。

自 OpenSSL 1.1.0 起支持生成 Ed25519 密钥,因此如果您使用的是旧版本的 OpenSSL,以下命令将不起作用。

Mac 用户注意:在 macOS 上,Apple 附带的 “openssl” 二进制文件实际上基于 LibreSSL,截至撰写本文时,它不支持 Ed25519 密钥。如果您使用的是 macOS,请使用 step CLI,或使用 brew install openssl@3 从 Homebrew 安装 OpenSSL 3.0,然后将以下命令中的 openssl 替换为 $(brew --prefix)/opt/openssl@3/bin/openssl

您可以使用 OpenSSL 生成新的 Ed25519 密钥对:

openssl genpkey -algorithm ed25519 -out private.pem
openssl pkey -in private.pem -pubout -out public.pem

在 macOS 上,使用来自 Homebrew 的 openssl@3:

$(brew --prefix)/opt/openssl@3/bin/openssl genpkey -algorithm ed25519 -out private.pem
$(brew --prefix)/opt/openssl@3/bin/openssl pkey -in private.pem -pubout -out public.pem

如果您还没有 step CLI,请按照官方说明安装它。

接下来,您可以使用 step CLI 生成新的 Ed25519 密钥对:

step crypto keypair \
  public.pem private.pem \
  --kty OKP --curve Ed25519 \
  --insecure --no-password

无论您如何生成密钥对,按照上述说明,您将拥有两个文件:

  • private.pem 包含密钥的私钥部分;使用此文件的内容作为组件元数据的 key 属性。
  • public.pem 包含密钥的公钥部分,仅当您手动部署 Worker 时才需要(按照上一节的说明)。

其他注意事项

  • 请注意,Cloudflare Workers KV 不保证强数据一致性。虽然对同一 Cloudflare 数据中心发出的请求的更改通常是立即可见的,但更改复制到所有 Cloudflare 区域可能需要一定的时间(通常长达一分钟)。
  • 此状态存储支持 Dapr 的 TTL,但 TTL 的最小值为 1 分钟。

相关链接

9 - CockroachDB

CockroachDB 状态存储组件的详细信息

创建 Dapr 组件

创建一个名为 cockroachdb.yaml 的文件,粘贴以下内容并将 <CONNECTION STRING> 值替换为您的连接字符串。CockroachDB 的连接字符串遵循与 PostgreSQL 连接字符串相同的标准。例如,"host=localhost user=root port=26257 connect_timeout=10 database=dapr_test"。有关如何定义连接字符串的信息,请参阅 CockroachDB 关于数据库连接的文档

如果您还想配置 CockroachDB 来存储 actor,请添加 actorStateStore 选项,如下面的示例所示。

apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
  name: <NAME>
spec:
  type: state.cockroachdb
  version: v1
  metadata:
  # Connection string
  - name: connectionString
    value: "<CONNECTION STRING>"
  # Timeout for database operations, in seconds (optional)
  #- name: timeoutInSeconds
  #  value: 20
  # Name of the table where to store the state (optional)
  #- name: tableName
  #  value: "state"
  # Name of the table where to store metadata used by Dapr (optional)
  #- name: metadataTableName
  #  value: "dapr_metadata"
  # Cleanup interval in seconds, to remove expired rows (optional)
  #- name: cleanupIntervalInSeconds
  #  value: 3600
  # Max idle time for connections before they're closed (optional)
  #- name: connectionMaxIdleTime
  #  value: 0
  # Uncomment this if you wish to use CockroachDB as a state store for actors (optional)
  #- name: actorStateStore
  #  value: "true"

规范元数据字段

字段必填详情示例
connectionStringYCockroachDB 的连接字符串"host=localhost user=root port=26257 connect_timeout=10 database=dapr_test"
timeoutInSecondsN所有数据库操作的超时时间(秒)。默认为 2030
tableNameN存储数据的表的名称。默认为 state。可以选择性地包含模式名称作为前缀,例如 public.state"state", "public.state"
metadataTableNameNDapr 用于存储一些元数据属性的表的名称。默认为 dapr_metadata。可以选择性地包含模式名称作为前缀,例如 public.dapr_metadata"dapr_metadata", "public.dapr_metadata"
cleanupIntervalInSecondsN清理过期 TTL 行的间隔(秒)。默认值:3600(即 1 小时)。将此设置为 <=0 的值会禁用定期清理。1800, -1
connectionMaxIdleTimeN未使用的连接在连接池中自动关闭前的最大空闲时间。默认情况下没有值,这由数据库驱动程序选择。"5m"
actorStateStoreN将此状态存储用于 actor。默认为 "false""true", "false"

设置 CockroachDB

  1. 运行一个 CockroachDB 实例。您可以使用以下命令在 Docker CE 中运行 CockroachDB 的本地实例:

    此示例不描述生产配置,因为它设置的是单节点集群,仅推荐用于本地环境。

    docker run --name roach1 -p 26257:26257 cockroachdb/cockroach:v21.2.3 start-single-node --insecure
    
  2. 为状态数据创建一个数据库。

    要在 CockroachDB 中创建新数据库,请在容器内运行以下 SQL 命令:

    docker exec -it roach1 ./cockroach sql --insecure -e 'create database dapr_test'
    

在 Kubernetes 上安装 CockroachDB 最简单的方法是使用 CockroachDB Operator

高级

TTL 和清理

此状态存储支持 Dapr 存储记录的 Time-To-Live (TTL)。使用 Dapr 存储数据时,您可以设置 ttlInSeconds 元数据属性来指示数据应在多少秒后被视为"过期"。

由于 CockroachDB 没有内置的 TTL 支持,Dapr 通过在状态表中添加一个列来实现此功能,该列指示数据应被视为"过期"的时间。即使"过期"记录仍物理存储在数据库中,也不会返回给调用者。后台"垃圾收集器"会定期扫描状态表中的过期行并将其删除。

您可以使用 cleanupIntervalInSeconds 元数据属性设置删除过期记录的间隔,该属性默认为 3600 秒(即 1 小时)。

  • 较长的间隔需要较少频率地扫描过期行,但可能需要存储过期记录更长时间,从而可能需要更多的存储空间。如果您计划在状态表中存储许多具有短 TTL 的记录,请考虑将 cleanupIntervalInSeconds 设置为较小的值 - 例如,300(300 秒,或 5 分钟)。
  • 如果您不计划将 TTL 与 Dapr 和 CockroachDB 状态存储一起使用,您应该考虑将 cleanupIntervalInSeconds 设置为 <= 0 的值(例如 0-1)以禁用定期清理并减少数据库负载。

相关链接

10 - Coherence

关于 Coherence 状态存储组件的详细信息

组件格式

要设置 Coherence 状态存储,请创建一个类型为 state.coherence 的组件。有关如何创建和应用状态存储配置,请参阅此指南

apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
  name: <NAME>
spec:
  type: state.coherence
  version: v1
  metadata:
  - name: serverAddress
    value: <REPLACE-WITH-GRPC-PROXY-HOST-AND-PORT> # 必填。示例:"my-cluster-grpc:1408"
  - name: tlsEnabled
    value: <REPLACE-WITH-BOOLEAN> # 可选
  - name: tlsClientCertPath
    value: <REPLACE-WITH-PATH> # 可选
  - name: tlsClientKey
    value: <REPLACE-WITH-PATH> # 可选
  - name: tlsCertsPath
    value: <REPLACE-WITH-PATH> # 可选
  - name: ignoreInvalidCerts
    value: <REPLACE-WITH-BOOLEAN> # 可选
  - name: scopeName
    value: <REPLACE-WITH-SCOPE> # 可选
  - name: requestTimeout
    value: <REPLACE-WITH-REQUEST-TIMEOUT> # 可选
  - name: nearCacheTTL
    value: <REPLACE-WITH-NEAR-CACHE-TTL> # 可选
  - name: nearCacheUnits
    value: <REPLACE-WITH-NEAR-CACHE-UNITS> # 可选
  - name: nearCacheMemory
    value: <REPLACE-WITH-NEAR-CACHE-MEMORY> # 可选

规范元数据字段

字段必填详情示例
serverAddress逗号分隔的端点"my-cluster-grpc:1408"
tlsEnabled指示是否应启用 TLS。默认为 false"true"
tlsClientCertPathCoherence 的客户端证书路径。默认为 “"。可以是 secretKeyRef 以使用密钥引用"-----BEGIN CERTIFICATE-----\nMIIC9TCCA..."
tlsClientKeyCoherence 的客户端密钥。默认为 “"。可以是 secretKeyRef 以使用密钥引用"-----BEGIN CERTIFICATE-----\nMIIC9TCCA..."
tlsCertsPathCoherence 的附加证书。默认为 “"。可以是 secretKeyRef 以使用密钥引用"-----BEGIN CERTIFICATE-----\nMIIC9TCCA..."
ignoreInvalidCerts指示是否忽略自签名证书,仅用于测试,不应用于生产环境。默认为 false"false"
scopeName用于内部缓存的作用域名称。默认为 "”"my-scope"
requestTimeout调用集群的超时时间,默认为 “30s”"15s"
nearCacheTTL如果非零,则使用近缓存,近缓存 的 TTL 为此值。默认为 0s"60s"
nearCacheUnits如果非零,则使用近缓存,近缓存的最大大小为此值(以单位计)。默认为 0"1000"
nearCacheMemory如果非零,则使用近缓存,近缓存的最大大小为此值(以字节计)。默认为 0"4096"

关于使用近缓存 TTL

Coherence 状态存储允许您指定近缓存来在使用 Dapr 客户端时缓存频繁访问的数据。 当您使用 Get(ctx context.Context, req *GetRequest) 访问数据时,返回的条目会存储在近缓存中, 并且对近缓存中键的后续数据访问几乎是即时的,而没有近缓存的每次 Get() 操作都会导致网络调用。

使用近缓存选项时,Coherence 会自动向内部缓存添加一个 MapListener,该监听器监听所有缓存事件,并更新或使近缓存中已在服务器上更改或删除的条目失效。

为了管理近缓存使用的内存量,在创建近缓存时支持以下选项:

  • nearCacheTTL – 对象在近缓存中过期的时间,例如 5 分钟
  • nearCacheUnits – 近缓存中缓存条目的最大数量
  • nearCacheMemory – 缓存条目使用的最大内存量

您可以指定 High-Units 或 Memory,并在任一情况下可选择指定 TTL。

近缓存条目的最小过期时间为 1/4 秒。这是为了确保元素过期尽可能高效。如果您尝试将 TTL 设置为更低的值,将会收到错误。

设置 Coherence

使用 Docker 在本地运行 Coherence:

docker run -d -p 1408:1408 -p 30000:30000 ghcr.io/oracle/coherence-ce:25.03.1

然后您可以使用 localhost:1408 与服务器交互。

在 Kubernetes 上安装 Coherence 的最简单方法是使用 Coherence Operator

安装 Operator:

kubectl apply -f https://github.com/oracle/coherence-operator/releases/download/v3.5.2/coherence-operator.yaml

注意:将 v3.5.2 更改为最新版本。

这将把 Coherence operator 安装到 coherence 命名空间中。

创建 Coherence 集群 yaml my-cluster.yaml

apiVersion: coherence.oracle.com/v1
kind: Coherence
metadata:
  name: my-cluster
spec:
  coherence:
    management:
      enabled: true
  ports:
    - name: management
    - name: grpc
      port: 1408

应用 yaml

kubectl apply -f my-cluster.yaml

要与 Coherence 交互,使用以下命令查找服务:kubectl get svc 并查找名为 ‘*grpc’ 的服务。

NAME                    TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)                                               AGE
kubernetes              ClusterIP   10.96.0.1      <none>        443/TCP                                               9m
my-cluster-grpc         ClusterIP   10.96.225.43   <none>        1408/TCP                                              7m3s
my-cluster-management   ClusterIP   10.96.41.6     <none>        30000/TCP                                             7m3s
my-cluster-sts          ClusterIP   None           <none>        7/TCP,7575/TCP,7574/TCP,6676/TCP,30000/TCP,1408/TCP   7m3s
my-cluster-wka          ClusterIP   None           <none>        7/TCP,7575/TCP,7574/TCP,6676/TCP                      7m3s

例如,如果使用上述示例安装,Coherence 主机地址将是:

my-cluster-grpc

相关链接

11 - Couchbase

Couchbase 状态存储组件的详细信息

组件格式

要设置 Couchbase 状态存储,需创建一个类型为 state.couchbase 的组件。请参阅本指南了解如何创建和应用状态存储配置。

apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
  name: <NAME>
spec:
  type: state.couchbase
  version: v1
  metadata:
  - name: couchbaseURL
    value: <REPLACE-WITH-URL> # 必填。示例:"http://localhost:8091"
  - name: username
    value: <REPLACE-WITH-USERNAME> # 必填。
  - name: password
    value: <REPLACE-WITH-PASSWORD> # 必填。
  - name: bucketName
    value: <REPLACE-WITH-BUCKET> # 必填。

规格元数据字段

FieldRequiredDetailsExample
couchbaseURLYCouchbase 服务器的 URL"http://localhost:8091"
usernameY数据库用户名"user"
passwordY访问密码"password"
bucketNameY写入的 bucket 名称"bucket"

设置 Couchbase

您可以使用 Docker 在本地运行 Couchbase:

docker run -d --name db -p 8091-8094:8091-8094 -p 11210:11210 couchbase

然后您可以使用 localhost:8091 与服务器交互并开始服务器设置。

在 Kubernetes 上安装 Couchbase 的最简单方法是使用 Helm chart

helm repo add couchbase https://couchbase-partners.github.io/helm-charts/
helm install couchbase/couchbase-operator
helm install couchbase/couchbase-cluster

相关链接

12 - Etcd

Etcd 状态存储组件的详细信息

组件格式

要设置 Etcd 状态存储,需创建类型为 state.etcd 的组件。请参阅此指南了解如何创建和应用状态存储配置。

apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
  name: <NAME>
spec:
  type: state.etcd
  # 支持 v1 和 v2。用户应默认使用 v2。
  # 从 v1 到 v2 没有迁移路径,详见下方的 `versioning`。
  version: v2
  metadata:
  - name: endpoints
    value: <CONNECTION STRING> # 必填。示例: 192.168.0.1:2379,192.168.0.2:2379,192.168.0.3:2379
  - name: keyPrefixPath
    value: <KEY PREFIX STRING> # 可选。默认值:""。示例:"dapr"
  - name: tlsEnable
    value: <ENABLE TLS> # 可选。示例:"false"
  - name: ca
    value: <CA> # 可选。当 tlsEnable 为 `true` 时必填。
  - name: cert
    value: <CERT> # 可选。当 tlsEnable 为 `true` 时必填。
  - name: key
    value: <KEY> # 可选。当 tlsEnable 为 `true` 时必填。
  # 如果您希望将 Etcd 用作 actor 的状态存储,请取消此注释(可选)
  #- name: actorStateStore
  #  value: "true"

版本说明

Dapr 有 2 个版本的 Etcd 状态存储组件:v1v2。建议使用 v2,因为 v1 已被弃用。

虽然 v1v2 具有相同的元数据字段,但在使用 Dapr v1.12 的 Actor TTL 时,v1 会导致应用中的数据不一致。 v1v2 不兼容,在现有的活跃 Etcd 集群和 keyPrefixPath 上没有从 v1 迁移到 v2 的数据迁移路径。 如果您正在使用 v1,应继续使用 v1,直到您创建新的 Etcd 集群或使用不同的 keyPrefixPath

规格元数据字段

字段必填说明示例
endpointsYEtcd 集群的连接字符串"192.168.0.1:2379,192.168.0.2:2379,192.168.0.3:2379"
keyPrefixPathNEtcd 中的键前缀路径。默认无前缀。"dapr"
tlsEnableN是否为与 Etcd 的连接启用 TLS。"false"
caN连接 Etcd 的 CA 证书,PEM 编码。可以是 secretKeyRef 以使用密钥引用"-----BEGIN CERTIFICATE-----\nMIIC9TCCA..."
certN连接 Etcd 的 TLS 证书,PEM 编码。可以是 secretKeyRef 以使用密钥引用"-----BEGIN CERTIFICATE-----\nMIIDUTCC..."
keyN连接 Etcd 的 TLS 密钥,PEM 编码。可以是 secretKeyRef 以使用密钥引用"-----BEGIN PRIVATE KEY-----\nMIIEpAIB..."
actorStateStoreN将此状态存储用于 actor。默认为 "false""true", "false"

设置 Etcd

您可以使用 Docker Compose 在本地运行 Etcd 数据库。创建一个名为 docker-compose.yml 的新文件并添加以下内容作为示例:

version: '2'
services:
  etcd:
    image: gcr.io/etcd-development/etcd:v3.4.20
    ports:
      - "2379:2379"
    command: etcd --listen-client-urls http://0.0.0.0:2379 --advertise-client-urls http://0.0.0.0:2379```

保存 docker-compose.yml 文件并运行以下命令启动 Etcd 服务器:

docker-compose up -d

这将在后台启动 Etcd 服务器并暴露默认的 Etcd 端口 2379。然后您可以使用 etcdctl 命令行客户端在 localhost:12379 上与服务器交互。例如:

etcdctl --endpoints=localhost:2379 put mykey myvalue

使用 Helm 在您的 Kubernetes 集群中快速创建 Etcd 实例。此方法需要安装 Helm

遵循 Bitnami 说明开始在 Kubernetes 中设置 Etcd。

相关链接

13 - GCP Firestore (Datastore 模式)

GCP Firestore 状态存储组件的详细信息

组件格式

要设置 GCP Firestore 状态存储,请创建一个类型为 state.gcp.firestore 的组件。有关如何创建和应用状态存储配置,请参阅此指南

apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
  name: <NAME>
spec:
  type: state.gcp.firestore
  version: v1
  metadata:
  - name: project_id
    value: <REPLACE-WITH-PROJECT-ID> # 必填。
  - name: type 
    value: <REPLACE-WITH-CREDENTIALS-TYPE> # 必填。
  - name: endpoint # 可选。
    value: "http://localhost:8432"
  - name: private_key_id
    value: <REPLACE-WITH-PRIVATE-KEY-ID> # 可选。
  - name: private_key
    value: <REPLACE-WITH-PRIVATE-KEY> # 可选,但如果指定了 `private_key_id` 则为必填。
  - name: client_email
    value: <REPLACE-WITH-CLIENT-EMAIL> # 可选,但如果指定了 `private_key_id` 则为必填。
  - name: client_id
    value: <REPLACE-WITH-CLIENT-ID> # 可选,但如果指定了 `private_key_id` 则为必填。
  - name: auth_uri
    value: <REPLACE-WITH-AUTH-URI> # 可选。
  - name: token_uri
    value: <REPLACE-WITH-TOKEN-URI> # 可选。
  - name: auth_provider_x509_cert_url
    value: <REPLACE-WITH-AUTH-X509-CERT-URL> # 可选。
  - name: client_x509_cert_url
    value: <REPLACE-WITH-CLIENT-x509-CERT-URL> # 可选。
  - name: entity_kind
    value: <REPLACE-WITH-ENTITY-KIND> # 可选。默认值:"DaprState"
  - name: noindex
    value: <REPLACE-WITH-BOOLEAN> # 可选。默认值:"false"

规范元数据字段

字段必填详情示例
project_idY要使用的 GCP 项目 ID"project-id"
typeY凭证类型"service_account"
endpointN组件要使用的 GCP 端点。仅用于本地开发(例如配合 GCP Datastore Emulator 使用)。针对 GCP 生产 API 运行时不需要 endpoint"localhost:8432"
private_key_idN要使用的私钥 ID"private-key-id"
privateKeyN如果使用显式凭证,此字段应包含服务账号 json 中的 private_key 字段-----BEGIN PRIVATE KEY-----MIIBVgIBADANBgkqhkiG9w0B
client_emailN客户端的电子邮件地址"eample@example.com"
client_idN用于身份验证的客户端 ID 值"client-id"
auth_uriN要使用的身份验证 URI"https://accounts.google.com/o/oauth2/auth"
token_uriN用于查询 Auth token 的令牌 URI"https://oauth2.googleapis.com/token"
auth_provider_x509_cert_urlN身份验证提供者证书 URL"https://www.googleapis.com/oauth2/v1/certs"
client_x509_cert_urlN客户端证书 URL"https://www.googleapis.com/robot/v1/metadata/x509/x"
entity_kindNFirestore 中的实体名称。默认为 "DaprState""DaprState"
noindexN是否禁用状态实体的索引。如果遇到 Firestore 索引大小限制,请使用此设置。默认为 "false""true"

GCP 凭证

由于 GCP Firestore 组件使用 GCP Go 客户端库,默认情况下它使用 Application Default Credentials 进行身份验证。这在 使用客户端库向 GCP Cloud 服务进行身份验证 指南中有详细说明。

设置 GCP Firestore

您可以使用 GCP Datastore 模拟器在本地运行,说明请参见此处

然后您可以使用 http://localhost:8432 与服务器交互。

按照此处的说明在 Google Cloud 中开始设置 Firestore。

相关链接

14 - HashiCorp Consul

HashiCorp Consul 状态存储组件的详细信息

组件格式

要设置 Hashicorp Consul 状态存储,请创建类型为 state.consul 的组件。请参阅本指南了解如何创建和应用状态存储配置。

apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
  name: <NAME>
spec:
  type: state.consul
  version: v1
  metadata:
  - name: datacenter
    value: <REPLACE-WITH-DATA-CENTER> # 必需。例如:dc1
  - name: httpAddr
    value: <REPLACE-WITH-CONSUL-HTTP-ADDRESS> # 必需。例如:"consul.default.svc.cluster.local:8500"
  - name: aclToken
    value: <REPLACE-WITH-ACL-TOKEN> # 可选。默认:""
  - name: scheme
    value: <REPLACE-WITH-SCHEME> # 可选。默认:"http"
  - name: keyPrefixPath
    value: <REPLACE-WITH-TABLE> # 可选。默认:""

规范元数据字段

字段必需详情示例
datacenterY要使用的数据中心"dc1"
httpAddrYConsul 服务器的地址"consul.default.svc.cluster.local:8500"
aclTokenN每次请求的 ACL Token。默认为 """token"
schemeNConsul 服务器的 URI scheme。默认为 "http""http"
keyPrefixPathNConsul 中的键前缀路径。默认为 """dapr"

设置 HashiCorp Consul

你可以使用 Docker 在本地运行 Consul:

docker run -d --name=dev-consul -e CONSUL_BIND_INTERFACE=eth0 consul

然后可以使用 localhost:8500 与服务器交互。

在 Kubernetes 上安装 Consul 最简单的方法是使用 Helm chart

helm install consul stable/consul

这会将 Consul 安装到 default 命名空间中。 要与 Consul 交互,请使用以下命令查找服务:kubectl get svc consul

例如,如果使用上述示例安装,Consul 主机地址将是:

consul.default.svc.cluster.local:8500

相关链接

15 - Hazelcast

Hazelcast 状态存储组件的详细信息

创建 Dapr 组件

要设置 Hazelcast 状态存储,请创建类型为 state.hazelcast 的组件。有关如何创建和应用状态存储配置,请参阅本指南

apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
  name: <NAME>
spec:
  type: state.hazelcast
  version: v1
  metadata:
  - name: hazelcastServers
    value: <REPLACE-WITH-HOSTS> # Required. A comma delimited string of servers. Example: "hazelcast:3000,hazelcast2:3000"
  - name: hazelcastMap
    value: <REPLACE-WITH-MAP> # Required. Hazelcast map configuration.

规格元数据字段

FieldRequiredDetailsExample
hazelcastServersY服务器列表,以逗号分隔"hazelcast:3000,hazelcast2:3000"
hazelcastMapYHazelcast Map 配置"foo-map"

设置 Hazelcast

您可以使用 Docker 在本地运行 Hazelcast:

docker run -e JAVA_OPTS="-Dhazelcast.local.publicAddress=127.0.0.1:5701" -p 5701:5701 hazelcast/hazelcast

然后可以使用 127.0.0.1:5701 与服务器进行交互。

在 Kubernetes 上安装 Hazelcast 最简单的方法是使用 Helm chart

相关链接

16 - In-memory

内存状态组件的详细文档

内存状态存储组件将状态维护在 Dapr 边车的内存中。这主要用于开发目的。状态不会在多个边车之间复制,并且当 Dapr 边车重启时会丢失。

组件格式

要设置内存状态存储,请创建一个类型为 state.in-memory 的组件。请参阅本指南了解如何创建和应用状态存储配置。

apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
  name: <NAME>
spec:
  type: state.in-memory
  version: v1
  metadata: 
  # 如果您希望将 In-memory 用作 actor 的状态存储,请取消注释(可选)
  #- name: actorStateStore
  #  value: "true"

注意:虽然内存不需要任何特定元数据即可使组件工作,但 spec.metadata 是必需字段。

相关链接

17 - JetStream KV

关于 JetStream KV 状态存储组件的详细信息

组件格式

要设置 JetStream KV 状态存储,需创建一个类型为 state.jetstream 的组件。请参阅此指南了解如何创建和应用状态存储配置。

apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
  name: <NAME>
spec:
  type: state.jetstream
  version: v1
  metadata:
  - name: natsURL
    value: "nats://localhost:4222"
  - name: jwt
    value: "eyJhbGciOiJ...6yJV_adQssw5c" # 可选。用于去中心化 JWT 认证
  - name: seedKey
    value: "SUACS34K232O...5Z3POU7BNIL4Y" # 可选。用于去中心化 JWT 认证
  - name: bucket
    value: "<bucketName>"

规范元数据字段

字段必需详情示例
natsURLYNATS 服务器地址 URLnats://localhost:4222
jwtNNATS 去中心化认证 JWTeyJhbGciOiJ...6yJV_adQssw5c
seedKeyNNATS 去中心化认证种子密钥SUACS34K232O...5Z3POU7BNIL4Y
bucketYJetStream KV 存储桶名称"<bucketName>"

创建 NATS 服务器

你可以使用 Docker 在本地运行启用了 JetStream 的 NATS 服务器:

docker run -d -p 4222:4222 nats:latest -js

然后可以使用客户端端口与服务器交互:localhost:4222

使用 helm 在 Kubernetes 上安装 NATS JetStream:

helm repo add nats https://nats-io.github.io/k8s/helm/charts/
helm install my-nats nats/nats

这会在 default 命名空间中安装一个单节点 NATS 服务器。要与 NATS 交互,可以使用以下命令查找服务:kubectl get svc my-nats

创建 JetStream KV 存储桶

需要创建一个键值存储桶,这可以通过 NATS CLI 轻松完成。

nats kv add <bucketName>

相关链接

18 - Memcached

Memcached 状态存储组件的详细信息

组件格式

要设置 Memcached 状态存储,请创建一个类型为 state.memcached 的组件。请参阅本指南了解如何创建和应用状态存储配置。

apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
  name: <NAME>
spec:
  type: state.memcached
  version: v1
  metadata:
  - name: hosts
    value: <REPLACE-WITH-COMMA-DELIMITED-ENDPOINTS> # 必填。示例:"memcached.default.svc.cluster.local:11211"
  - name: maxIdleConnections
    value: <REPLACE-WITH-MAX-IDLE-CONNECTIONS> # 可选。默认:"2"
  - name: timeout
    value: <REPLACE-WITH-TIMEOUT> # 可选。默认:"1000"

规范元数据字段

字段必填详情示例
hostsY以逗号分隔的端点"memcached.default.svc.cluster.local:11211"
maxIdleConnectionsN空闲连接的最大数量。默认为 "2""3"
timeoutN调用的超时时间(毫秒)。默认为 "1000""1000"

设置 Memcached

你可以使用 Docker 在本地运行 Memcached:

docker run --name my-memcache -d memcached

然后你可以使用 localhost:11211 与服务器交互。

在 Kubernetes 上安装 Memcached 最简单的方法是使用 Helm chart

helm install memcached stable/memcached

这会将 Memcached 安装到 default 命名空间中。 要与 Memcached 交互,使用以下命令查找服务:kubectl get svc memcached

例如,如果使用上述示例安装,Memcached 主机地址将是:

memcached.default.svc.cluster.local:11211

相关链接

19 - Microsoft SQL Server & Azure SQL

Microsoft SQL Server 状态存储组件的详细信息

组件格式

此状态存储组件可用于 Microsoft SQL ServerAzure SQL

要设置此状态存储,请创建类型为 state.sqlserver 的组件。有关如何创建和应用状态存储配置,请参阅此指南

apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
  name: <NAME>
spec:
  type: state.sqlserver
  version: v2
  metadata:
    # 使用 SQL Server 凭据进行身份验证
    - name: connectionString
      value: |
        Server=myServerName\myInstanceName;Database=myDataBase;User Id=myUsername;Password=myPassword;

    # 使用 Microsoft Entra ID 进行身份验证(仅限 Azure SQL)
    # "useAzureAD" 必须设置为 "true"
    - name: useAzureAD
      value: true
    # Azure SQL 数据库的连接字符串或 URL,可选包含数据库名称
    - name: connectionString
      value: |
        sqlserver://myServerName.database.windows.net:1433?database=myDataBase

    # 其他可选字段(列出默认值)
    - name: tableName
      value: "state"
    - name: metadataTableName
      value: "dapr_metadata"
    - name: schema
      value: "dbo"
    - name: keyType
      value: "string"
    - name: keyLength
      value: "200"
    - name: indexedProperties
      value: ""
    - name: cleanupIntervalInSeconds
      value: "3600"
   # 如果希望将 Microsoft SQL Server 用作 actor 的状态存储,请取消注释此行(可选)
   #- name: actorStateStore
   #  value: "true"

如果希望将 SQL Server用作 actor 状态存储,请在元数据中添加以下内容:

  - name: actorStateStore
    value: "true"

规范元数据字段

使用 SQL Server 凭据进行身份验证

使用 SQL Server 凭据进行身份验证时,以下元数据选项是必需的。SQL Server 和 Azure SQL 都支持此方式。

字段必需详情示例
connectionStringY用于连接的连接字符串。
如果连接字符串包含数据库,则该数据库必须已存在。否则,如果省略数据库,将创建名为 “Dapr” 的默认数据库。
"Server=myServerName\myInstanceName;Database=myDataBase;User Id=myUsername;Password=myPassword;"

使用 Microsoft Entra ID 进行身份验证

仅 Azure SQL 支持使用 Microsoft Entra ID 进行身份验证。可以使用 Dapr 支持的所有身份验证方法,包括客户端凭据(“服务主体”)和托管标识。

字段必需详情示例
useAzureADY必须设置为 true 以使组件能够从 Microsoft Entra ID 获取访问令牌。"true"
connectionStringYAzure SQL 数据库的连接字符串或 URL,不包含凭据
如果连接字符串包含数据库,则该数据库必须已存在。否则,如果省略数据库,将创建名为 “Dapr” 的默认数据库。
"sqlserver://myServerName.database.windows.net:1433?database=myDataBase"
azureTenantIdNMicrosoft Entra ID 租户的 ID"cd4b2887-304c-47e1-b4d5-65447fdd542b"
azureClientIdN客户端 ID(应用程序 ID)"c7dd251f-811f-4ba2-a905-acd4d3f8f08b"
azureClientSecretN客户端密钥(应用程序密码)"Ecy3XG7zVZK3/vl/a2NSB+a1zXLa8RnMum/IgD0E"

其他元数据选项

字段必需详情示例
tableNameN要使用的表名。字母数字和下划线。默认为 "state""table_name"
metadataTableNameNDapr 用于存储少量元数据属性的表的名称。默认为 dapr_metadata"dapr_metadata"
keyTypeN使用的键类型。支持的值:"string"(默认)、"uuid""integer""string"
keyLengthN键的最大长度。如果 “keyType” 不是 string,则忽略此项。默认为 "200""200"
schemaN要使用的架构。默认为 "dbo""dapr","dbo"
indexedPropertiesN索引属性列表,作为包含 JSON 文档的字符串。'[{"column": "transactionid", "property": "id", "type": "int"}, {"column": "customerid", "property": "customer", "type": "nvarchar(100)"}]'
actorStateStoreN指示 Dapr 应为 actor 状态存储配置此组件(更多信息)。"true"
cleanupIntervalInSecondsN清理过期 TTL 行的间隔(以秒为单位)。默认:"3600"(即 1 小时)。将此值设置为 <=0 会禁用定期清理。"1800", "-1"

创建 Microsoft SQL Server/Azure SQL 实例

按照说明从 Azure 文档中了解如何创建 SQL 数据库。数据库必须先创建,Dapr 才能使用它。

为了将 SQL Server 设置为状态存储,您需要以下属性:

  • 连接字符串:SQL Server 连接字符串。例如:server=localhost;user id=sa;password=your-password;port=1433;database=mydatabase;
  • 架构:要使用的数据库架构(默认=dbo)。如果不存在,将创建该架构
  • 表名:数据库表名。如果不存在,将创建该表
  • 索引属性:来自 json 数据的可选属性,将被索引并作为单独的列持久化

创建专用用户

当使用专用用户(非 sa)连接时,用户需要这些授权 - 即使用户是所需数据库架构的所有者:

  • CREATE TABLE
  • CREATE TYPE

TTL 和清理

此状态存储支持使用 Dapr 存储的记录的生存时间(TTL)。使用 Dapr 存储数据时,您可以设置 ttlInSeconds 元数据属性来指示数据应在多少秒后被视为"过期"。

由于 SQL Server 没有内置的 TTL 支持,Dapr 通过在状态表中添加一列来实现此功能,指示数据何时应被视为"过期"。“过期"记录不会返回给调用者,即使它们仍物理存储在数据库中。后台"垃圾收集器"会定期扫描状态表中的过期行并删除它们。

您可以使用 cleanupIntervalInSeconds 元数据属性设置过期记录的删除间隔,默认为 3600 秒(即 1 小时)。

  • 较长的间隔需要对过期行进行不太频繁的扫描,但可能需要存储过期记录更长时间,从而可能需要更多存储空间。如果您计划在状态表中存储许多具有短 TTL 的记录,请考虑将 cleanupIntervalInSeconds 设置为较小的值 - 例如,300(300 秒,或 5 分钟)。
  • 如果您不打算将 TTL 与 Dapr 和 SQL Server 状态存储一起使用,您应该考虑将 cleanupIntervalInSeconds 设置为 <= 0 的值(例如 0-1)以禁用定期清理并减少数据库的负载。

状态存储在 ExpireDate 列上没有索引,这意味着每次清理操作都必须执行全表扫描。如果您打算向包含大量使用 TTL 的记录的表写入数据,您应该考虑在 ExpireDate 列上创建索引。索引使查询更快,但使用更多存储空间并略微减慢写入速度。

CREATE CLUSTERED INDEX expiredate_idx ON state(ExpireDate ASC)

高级

v1 和 v2 之间的区别

Sqlserver 状态存储 v1 在 Dapr 1.5 中引入。预先存在的 v1 仍然可用,并未被弃用。

在 v2 组件中,表模式已更改,目标是完全支持工作流。最值得注意的是,Dapr 存储的值现在属于 VARBINARY 类型,这允许工作流正确地存储数据。
然而,由于此更改,v2 组件不支持 Dapr 状态存储查询 API

由于这些更改,v1 和 v2 组件无法从同一个表读取或写入数据。也无法在组件的两个版本之间迁移数据。

相关链接

20 - Microsoft SQL Server & Azure SQL

Microsoft SQL Server 状态存储组件的详细信息

组件格式

此状态存储组件可与 Microsoft SQL ServerAzure SQL 一起使用。

要设置此状态存储,请创建类型为 state.sqlserver 的组件。请参阅本指南了解如何创建和应用状态存储配置。

apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
  name: <NAME>
spec:
  type: state.sqlserver
  version: v1
  metadata:
    # 使用 SQL Server 凭据进行身份验证
    - name: connectionString
      value: |
        Server=myServerName\myInstanceName;Database=myDataBase;User Id=myUsername;Password=myPassword;

    # 使用 Microsoft Entra ID 进行身份验证(仅限 Azure SQL)
    # "useAzureAD" 需要设置为 "true"
    - name: useAzureAD
      value: true
    # Azure SQL 数据库的连接字符串或 URL,可选择包含数据库
    - name: connectionString
      value: |
        sqlserver://myServerName.database.windows.net:1433?database=myDataBase

    # 其他可选字段(列出默认值)
    - name: tableName
      value: "state"
    - name: metadataTableName
      value: "dapr_metadata"
    - name: schema
      value: "dbo"
    - name: keyType
      value: "string"
    - name: keyLength
      value: "200"
    - name: indexedProperties
      value: ""
    - name: cleanupIntervalInSeconds
      value: "3600"
   # 如果您希望将 Microsoft SQL Server 用作 actor 的状态存储,请取消注释此行(可选)
   #- name: actorStateStore
   #  value: "true"

如果您希望将 SQL server 用作 actor 状态存储,请在元数据中附加以下内容:

  - name: actorStateStore
    value: "true"

规范元数据字段

使用 SQL Server 凭据进行身份验证

以下元数据选项是使用 SQL Server 凭据进行身份验证必需的。SQL Server 和 Azure SQL 都支持此功能。

字段必填详情示例
connectionStringY用于连接的连接字符串。
如果连接字符串包含数据库,则该数据库必须已存在。否则,如果省略数据库,则会创建名为 “Dapr” 的默认数据库。
"Server=myServerName\myInstanceName;Database=myDataBase;User Id=myUsername;Password=myPassword;"

使用 Microsoft Entra ID 进行身份验证

仅 Azure SQL 支持使用 Microsoft Entra ID 进行身份验证。可以使用 Dapr 支持的所有身份验证方法,包括客户端凭据(“服务主体”)和托管标识。

字段必填详情示例
useAzureADY必须设置为 true 以使组件能够从 Microsoft Entra ID 获取访问令牌。"true"
connectionStringYAzure SQL 数据库的连接字符串或 URL,不带凭据
如果连接字符串包含数据库,则该数据库必须已存在。否则,如果省略数据库,则会创建名为 “Dapr” 的默认数据库。
"sqlserver://myServerName.database.windows.net:1433?database=myDataBase"
azureTenantIdNMicrosoft Entra ID 租户的 ID"cd4b2887-304c-47e1-b4d5-65447fdd542b"
azureClientIdN客户端 ID(应用程序 ID)"c7dd251f-811f-4ba2-a905-acd4d3f8f08b"
azureClientSecretN客户端密钥(应用程序密码)"Ecy3XG7zVZK3/vl/a2NSB+a1zXLa8RnMum/IgD0E"

其他元数据选项

字段必填详情示例
tableNameN要使用的表的名称。字母数字和下划线。默认为 "state""table_name"
metadataTableNameNDapr 用于存储少量元数据属性的表的名称。默认为 dapr_metadata"dapr_metadata"
keyTypeN使用的键类型。支持的值:"string"(默认)、"uuid""integer""string"
keyLengthN键的最大长度。如果 “keyType” 不是 string,则忽略此项。默认为 "200""200"
schemaN要使用的架构。默认为 "dbo""dapr""dbo"
indexedPropertiesN索引属性列表,以包含 JSON 文档的字符串形式提供。'[{"column": "transactionid", "property": "id", "type": "int"}, {"column": "customerid", "property": "customer", "type": "nvarchar(100)"}]'
actorStateStoreN指示 Dapr 应为 actor 状态存储配置此组件([更多信息](https://docs.dapr.io/zh-hans/reference/api/state_api/#configuring-state-store-for-actors))。"true"
cleanupIntervalInSecondsN清理过期 TTL 行的间隔(秒)。默认:"3600"(即 1 小时)。将此值设置为 <=0 会禁用定期清理。"1800""-1"

创建 Microsoft SQL Server/Azure SQL 实例

按照说明从 Azure 文档中了解如何创建 SQL 数据库。数据库必须在 Dapr 使用它之前创建。

为了将 SQL Server 设置为状态存储,您需要以下属性:

  • 连接字符串:SQL Server 连接字符串。例如:server=localhost;user id=sa;password=your-password;port=1433;database=mydatabase;
  • 架构:要使用的数据库架构(默认=dbo)。如果不存在则创建
  • 表名称:数据库表名称。如果不存在则创建
  • 索引属性:来自 json 数据的可选属性,将被索引并作为单独的列持久化

创建专用用户

当使用专用用户(不是 sa)连接时,即使用户是所需数据库架构的所有者,也需要为用户授予以下授权:

  • CREATE TABLE
  • CREATE TYPE

TTL 和清理

此状态存储支持使用 Dapr 存储的记录的 Time-To-Live (TTL)。使用 Dapr 存储数据时,您可以设置 ttlInSeconds 元数据属性来指示数据应该在多少秒后被视为"过期"。

由于 SQL Server 没有内置的 TTL 支持,Dapr 通过在状态表中添加一列来指示数据何时应被视为"过期"来实现此功能。“过期"记录不会返回给调用者,即使它们仍然物理存储在数据库中。后台"垃圾回收器"定期扫描状态表中的过期行并删除它们。

您可以使用 cleanupIntervalInSeconds 元数据属性设置删除过期记录的间隔,该属性默认为 3600 秒(即 1 小时)。

  • 较长的间隔需要较少的过期行扫描频率,但可能需要存储过期记录更长时间,从而可能需要更多的存储空间。如果您计划在状态表中存储许多具有短 TTL 的记录,请考虑将 cleanupIntervalInSeconds 设置为较小的值 - 例如,300(300 秒,或 5 分钟)。
  • 如果您不打算将 TTL 与 Dapr 和 SQL Server 状态存储一起使用,您应该考虑将 cleanupIntervalInSeconds 设置为 <= 0 的值(例如 0-1)以禁用定期清理并减少数据库的负载。

状态存储在 ExpireDate 列上没有索引,这意味着每次清理操作都必须执行全表扫描。如果您打算向使用 TTL 的大量记录的表写入数据,您应该考虑在 ExpireDate 列上创建索引。索引使查询更快,但使用更多的存储空间并稍微降低写入速度。

CREATE CLUSTERED INDEX expiredate_idx ON state(ExpireDate ASC)

相关链接

21 - MongoDB

MongoDB 状态存储组件的详细信息

组件格式

要设置 MongoDB 状态存储,请创建类型为 state.mongodb 的组件。请参阅此指南以了解如何创建和应用状态存储配置。

apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
  name: <NAME>
spec:
  type: state.mongodb
  version: v1
  metadata:
  - name: server
    value: <REPLACE-WITH-SERVER> # 除非设置了 "host" 字段,否则必填。示例:"server.example.com"
  - name: host
    value: <REPLACE-WITH-HOST> # 除非设置了 "server" 字段,否则必填。示例:"mongo-mongodb.default.svc.cluster.local:27017"
  - name: username
    value: <REPLACE-WITH-USERNAME> # 可选。示例:"admin"
  - name: password
    value: <REPLACE-WITH-PASSWORD> # 可选。
  - name: databaseName
    value: <REPLACE-WITH-DATABASE-NAME> # 可选。默认值:"daprStore"
  - name: collectionName
    value: <REPLACE-WITH-COLLECTION-NAME> # 可选。默认值:"daprCollection"
  - name: writeConcern
    value: <REPLACE-WITH-WRITE-CONCERN> # 可选。
  - name: readConcern
    value: <REPLACE-WITH-READ-CONCERN> # 可选。
  - name: operationTimeout
    value: <REPLACE-WITH-OPERATION-TIMEOUT> # 可选。默认值:"5s"
  - name: params
    value: <REPLACE-WITH-ADDITIONAL-PARAMETERS> # 可选。示例:"?authSource=daprStore&ssl=true"
  # 如果希望将 MongoDB 作为 actor 的状态存储,请取消注释(可选)
  #- name: actorStateStore
  #  value: "true"

Actor 状态存储和事务支持

当用作 actor 状态存储或利用事务时,MongoDB 必须在副本集中运行。

如果希望将 MongoDB 用作 actor 存储,请在组件 YAML 中添加此元数据选项:

  - name: actorStateStore
    value: "true"

规格元数据字段

字段必填详情示例
serverY1使用 DNS SRV 记录时要连接的服务器"server.example.com"
hostY1要连接的主机"mongo-mongodb.default.svc.cluster.local:27017"
usernameN连接用户的用户名(与 host 结合使用时适用)"admin"
passwordN用户的密码(与 host 结合使用时适用)"password"
databaseNameN要使用的数据库的名称。默认为 "daprStore""daprStore"
collectionNameN要使用的集合的名称。默认为 "daprCollection""daprCollection"
writeConcernN要使用的写入关注点"majority"
readConcernN要使用的读取关注点"majority", "local","available", "linearizable", "snapshot"
operationTimeoutN操作的超时时间。默认为 "5s""5s"
paramsN2要使用的附加参数"?authSource=daprStore&ssl=true"
actorStateStoreN将此状态存储用于 actor。默认为 "false""true", "false"

[1] serverhost 字段互斥。如果两者都未设置或同时设置,Dapr 将返回错误。

[2] params 字段接受一个查询字符串,将连接特定选项指定为 <name>=<value> 对,用 & 分隔并以 ? 为前缀。例如,要使用 “daprStore” 数据库作为身份验证数据库并在连接中启用 SSL/TLS,请将 params 指定为 ?authSource=daprStore&ssl=true。有关可用选项及其用例的列表,请参阅 mongodb 手册

设置 MongoDB

您可以使用 Docker 在本地运行单个 MongoDB 实例:

docker run --name some-mongo -d -p 27017:27017 mongo

然后可以通过 localhost:27017 与服务器交互。如果您在组件定义中没有指定 databaseName 值,请确保创建一个名为 daprStore 的数据库。

为了将 MongoDB 状态存储用于事务和 actor 状态存储,您需要以副本集的方式运行 MongoDB。有关使用 Docker 创建三节点副本集的方法,请参阅官方文档

您可以使用 Bitnami 打包的 Helm chart 在 Kubernetes 上方便地安装 MongoDB。请参阅 Helm chart 的文档以部署 MongoDB,包括作为独立服务器和使用副本集(使用事务和 actor 所必需)。 这会将 MongoDB 安装到 default 命名空间。 要与服务进行交互,可以使用以下命令:kubectl get svc mongo-mongodb。 例如,如果使用上面的 Helm 默认设置进行安装,MongoDB 主机地址将是: mongo-mongodb.default.svc.cluster.local:27017 按照屏幕上的说明获取 MongoDB 的 root 密码。 默认情况下,用户名通常为 admin

TTLs 和清理

此状态存储支持为 Dapr 存储的记录设置生存时间(TTL)。使用 Dapr 存储数据时,您可以设置 ttlInSeconds 元数据属性来指示数据应被视为"过期"的时间。

相关链接

22 - MySQL & MariaDB

MySQL 状态存储组件的详细信息

组件格式

MySQL 状态存储组件允许连接到 MySQL 和 MariaDB 数据库。在本文档中,我们使用 “MySQL” 来指代这两种数据库。

要设置 MySQL 状态存储,请创建一个类型为 state.mysql 的组件。请参阅此指南了解如何创建和应用状态存储配置。

apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
  name: <NAME>
spec:
  type: state.mysql
  version: v1
  metadata:
  - name: connectionString
    value: "<CONNECTION STRING>"
  - name: schemaName
    value: "<SCHEMA NAME>"
  - name: tableName
    value: "<TABLE NAME>"
  - name: timeoutInSeconds
    value: "30"
  - name: pemPath # 如果未提供 pemContents 则必需。Pem 文件的路径。
    value: "<PEM PATH>"
  - name: pemContents # 如果未提供 pemPath 则必需。Pem 值。
    value: "<PEM CONTENTS>"    
# 如果您希望将 MySQL & MariaDB 用作 actor 的状态存储,请取消此注释(可选)
  #- name: actorStateStore
  #  value: "true"

如果您希望将 MySQL 用作 actor 存储,请在 yaml 中添加以下内容。

  - name: actorStateStore
    value: "true"

规范元数据字段

字段必填详情示例
connectionStringY连接到 MySQL 的连接字符串。不要将 schema 添加到连接字符串中非 SSL 连接"<user>:<password>@tcp(<server>:3306)/?allowNativePasswords=true"强制 SSL 连接"<user>:<password>@tcp(<server>:3306)/?allowNativePasswords=true&tls=custom"
schemaNameN要使用的 schema 名称。如果 schema 不存在将创建。默认为 "dapr_state_store""custom_schema""dapr_schema"
tableNameN要使用的表名称。如果表不存在将创建。默认为 "state""table_name""dapr_state"
timeoutInSecondsN所有数据库操作的超时时间。默认为 2030
pemPathN用于强制 SSL 连接的 PEM 文件的完整路径,如果未提供 pemContents 则必需。不能在 K8s 环境中使用"/path/to/file.pem""C:\path\to\file.pem"
pemContentsN用于强制 SSL 连接的 PEM 文件内容,如果未提供 pemPath 则必需。可在 K8s 环境中使用"pem value"
cleanupIntervalInSecondsN清理过期 TTL 行的间隔(秒)。默认:3600(即 1 小时)。将此值设置为 <=0 将禁用定期清理。1800-1
actorStateStoreN将此状态存储用于 actor。默认为 "false""true""false"

设置 MySQL

Dapr 可以使用任何 MySQL 实例——容器化的、在本地开发机器上运行的,或托管云服务。

运行一个 MySQL 实例。您可以使用以下命令在 Docker CE 中运行本地 MySQL 实例:

此示例未描述生产配置,因为它以纯文本形式设置密码,并且用户名保留为 MySQL 默认值 “root”。

docker run --name dapr-mysql -p 3306:3306 -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:latest

我们可以使用 Helm 在 Kubernetes 集群中快速创建 MySQL 实例。此方法需要安装 Helm

  1. 将 MySQL 安装到您的集群中。

    helm repo add bitnami https://charts.bitnami.com/bitnami
    helm install dapr-mysql bitnami/mysql
    
  2. 运行 kubectl get pods 查看集群中现在正在运行的 MySQL 容器。

  3. 接下来,我们将获取密码,根据我们使用的操作系统,密码的获取方式略有不同:

    • Windows:运行 [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($(kubectl get secret --namespace default dapr-mysql -o jsonpath="{.data.mysql-root-password}"))) 并复制输出的密码。

    • Linux/MacOS:运行 kubectl get secret --namespace default dapr-mysql -o jsonpath="{.data.mysql-root-password}" | base64 --decode 并复制输出的密码。

  4. 使用密码您可以构建连接字符串。

Azure MySQL

如果您使用 Azure 上的 MySQL,请参阅 Azure 关于 SSL 数据库连接的文档,了解如何下载所需证书的信息。

非 SSL 连接

<CONNECTION STRING> 值替换为您的连接字符串。连接字符串是标准的 MySQL 连接字符串。例如,"<user>:<password>@tcp(<server>:3306)/?allowNativePasswords=true"

强制 SSL 连接

如果您的服务器需要 SSL,连接字符串必须以 &tls=custom 结尾,例如,"<user>:<password>@tcp(<server>:3306)/?allowNativePasswords=true&tls=custom"。您必须将 <PEM PATH> 替换为 PEM 文件的完整路径。与 MySQL 的连接需要最低 1.2 版本的 TLS。

TTL 和清理

此状态存储支持 Dapr 存储记录的 Time-To-Live (TTL)。使用 Dapr 存储数据时,您可以设置 ttlInSeconds 元数据属性以指示何时应将数据视为"过期"。

由于 MySQL 没有对 TTL 的内置支持,这是通过在状态表中添加一列来实现的,该列指示数据何时被视为"过期"。被视为"过期"的记录不会返回给调用者,即使它们仍然物理存储在数据库中。后台"垃圾收集器"会定期扫描状态表中的过期行并将其删除。

删除过期记录的间隔是通过 cleanupIntervalInSeconds 元数据属性设置的,默认为 3600 秒(即 1 小时)。

  • 较长的间隔需要较少频率地扫描过期行,但可能需要存储过期记录更长的时间,可能需要更多的存储空间。如果您计划在状态表中存储许多具有短 TTL 的记录,请考虑将 cleanupIntervalInSeconds 设置为较小的值,例如 300(300 秒,或 5 分钟)。
  • 如果您不计划对 Dapr 和 MySQL 状态存储使用 TTL,您应该考虑将 cleanupIntervalInSeconds 设置为 <= 0 的值(例如 0-1)以禁用定期清理并减少数据库的负载。

相关链接

23 - OCI 对象存储

OCI 对象存储状态存储组件的详细信息

组件格式

要设置 OCI 对象存储状态存储,请创建类型为 state.oci.objectstorage 的组件。有关如何创建和应用状态存储配置,请参阅此指南

apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
  name: <NAME>
spec:
  type: state.oci.objectstorage
  version: v1
  metadata:
 - name: instancePrincipalAuthentication
   value: <"true" or "false">  # 可选。默认值:"false" 
 - name: configFileAuthentication
   value: <"true" or "false">  # 可选。默认值:"false" 。当 instancePrincipalAuthentication == "true" 时不使用 
 - name: configFilePath
   value: <REPLACE-WITH-FULL-QUALIFIED-PATH-OF-CONFIG-FILE>  # 可选。无默认值。仅在 configFileAuthentication == "true" 时使用 
 - name: configFileProfile
   value: <REPLACE-WITH-NAME-OF-PROFILE-IN-CONFIG-FILE>  # 可选。默认值:"DEFAULT" 。仅在 configFileAuthentication == "true" 时使用 
 - name: tenancyOCID
   value: <REPLACE-WITH-TENANCY-OCID>  # 当 configFileAuthentication == "true" 或 instancePrincipalAuthentication == "true" 时不使用 
 - name: userOCID
   value: <REPLACE-WITH-USER-OCID>  # 当 configFileAuthentication == "true" 或 instancePrincipalAuthentication == "true" 时不使用 
 - name: fingerPrint
   value: <REPLACE-WITH-FINGERPRINT>  # 当 configFileAuthentication == "true" 或 instancePrincipalAuthentication == "true" 时不使用 
 - name: privateKey  # 当 configFileAuthentication == "true" 或 instancePrincipalAuthentication == "true" 时不使用 
   value: |
          -----BEGIN RSA PRIVATE KEY-----
          REPLACE-WITH-PRIVATE-KEY-AS-IN-PEM-FILE
          -----END RSA PRIVATE KEY-----    
 - name: region
   value: <REPLACE-WITH-OCI-REGION>  # 当 configFileAuthentication == "true" 或 instancePrincipalAuthentication == "true" 时不使用 
 - name: bucketName
	 value: <REPLACE-WITH-BUCKET-NAME>
 - name: compartmentOCID
   value: <REPLACE-WITH-COMPARTMENT-OCID>

规范元数据字段

字段必填详情示例
instancePrincipalAuthenticationN布尔值,指示是否使用基于实例主体(instance principal)的身份验证。默认值:"false""true""false"
configFileAuthenticationN布尔值,指示是否通过配置文件提供身份凭据详细信息。默认值:"false" 当 instancePrincipalAuthentication 为 true 时不需要也不使用。"true""false"
configFilePathNOCI 配置文件的完整路径名。不存在默认值。当 instancePrincipalAuthentication 为 true 时不使用。注意:不支持 ~/ 前缀。"/home/apps/configuration-files/myOCIConfig.txt"
configFileProfileN配置文件中要使用的配置文件(profile)名称。默认值:"DEFAULT" 当 instancePrincipalAuthentication 为 true 时不使用。"DEFAULT""PRODUCTION"
tenancyOCIDYOCI 租户标识符。当 instancePrincipalAuthentication 为 true 时不需要也不使用。"ocid1.tenancy.oc1..aaaaaaaag7c7sljhsdjhsdyuwe723"
userOCIDYOCI 账户的 OCID(此账户需要访问 OCI 对象存储的权限)。当 instancePrincipalAuthentication 为 true 时不需要也不使用。"ocid1.user.oc1..aaaaaaaaby4oyyyuqwy7623yuwe76"
fingerPrintY公钥的指纹。当 instancePrincipalAuthentication 为 true 时不需要也不使用。"02:91:6c:49:e2:94:21:15:a7:6b:0e:a7:34:e1:3d:1b"
privateKeyYRSA 密钥对的私钥。当 instancePrincipalAuthentication 为 true 时不需要也不使用。"MIIEoyuweHAFGFG2727as+7BTwQRAIW4V"
regionYOCI 区域。当 instancePrincipalAuthentication 为 true 时不需要也不使用。"us-ashburn-1"
bucketNameY写入和读取(并在必要时创建)的存储桶的名称"application-state-store-bucket"
compartmentOCIDY包含存储桶的区间(compartment)的 OCID"ocid1.compartment.oc1..aaaaaaaacsssekayyuq7asjh78"

设置 OCI 对象存储

OCI 对象存储状态存储需要与 Oracle Cloud Infrastructure 进行交互。状态存储支持两种不同的身份验证方法。一种基于身份(用户或服务账户),另一种是利用授予运行应用程序工作负载的计算实例的权限的实例主体身份验证。注意:资源主体身份验证——用于非实例资源(如无服务器函数)——目前不支持。

在 Oracle Cloud Infrastructure 上运行的 Dapr 应用程序——在计算实例中或作为 Kubernetes 上的容器——可以利用实例主体身份验证。有关更多背景信息,请参阅 OCI 文档关于从实例调用 OCI 服务。简而言之:实例需要是动态组的成员,并且该动态组需要通过 IAM 策略获得与对象存储服务交互的权限。对于此类实例主体身份验证,将属性 instancePrincipalAuthentication 指定为 "true"。您不需要配置属性 tenancyOCID、userOCID、region、fingerPrint 和 privateKey——如果您为它们定义了值,这些将被忽略。

基于身份的身份验证通过一个 OCI 账户与 OCI 进行交互,该账户具有通过 OCI 对象存储在指定存储桶中创建、读取和删除对象的权限,并且如果未预先创建存储桶,则允许在指定区间中创建存储桶。OCI 文档描述了如何创建 OCI 账户。状态存储的交互使用公钥的指纹和为 OCI 账户生成的 RSA 密钥对的私钥进行。生成密钥对并获取所需信息的说明可在 OCI 文档中找到。

用于与 OCI 交互的身份和身份凭据的详细信息可以直接在 Dapr 组件属性文件中提供——使用属性 tenancyOCID、userOCID、fingerPrint、privateKey 和 region——或者可以从配置文件中提供,这是许多 OCI 相关工具(如 CLI 和 Terraform)和 SDK 的常见做法。在后一种情况下,必须通过属性 configFilePath 提供确切的文件名和完整路径。注意:路径中不支持 ~/ 前缀。配置文件可以包含多个配置文件(profile);所需的配置文件可以通过属性 configFileProfile 指定。如果未提供值,则使用 DEFAULT 作为要使用的配置文件的名称。注意:如果找不到指定的配置文件,则使用 DEFAULT 配置文件(如果存在)。OCI SDK 文档提供了有关配置文件定义的详细信息

如果您希望为 Dapr 创建要使用的存储桶,可以预先执行此操作。但是,对象存储状态提供程序将自动在指定区间中为您创建一个(如果它不存在)。

为了将 OCI 对象存储设置为状态存储,您需要以下属性:

  • instancePrincipalAuthentication:指示是否应使用基于实例主体的身份验证的标志。
  • configFileAuthentication:指示是否通过配置文件提供 OCI 身份凭据详细信息的标志。当 instancePrincipalAuthentication 为 true 时不使用。
  • configFilePath:OCI 配置文件的完整路径名。当 instancePrincipalAuthentication 为 true 或 configFileAuthentication 不为 true 时不使用。
  • configFileProfile:配置文件中要使用的配置文件(profile)名称。默认值:"DEFAULT" 当 instancePrincipalAuthentication 为 true 或 configFileAuthentication 不为 true 时不需要也不使用。当在配置文件中找不到指定的配置文件时,如果存在 DEFAULT 配置文件,则使用它。
  • tenancyOCID:OCI 云租户的标识符,状态将存储在其中。当 instancePrincipalAuthentication 为 true 或 configFileAuthentication 为 true 时不使用。
  • userOCID:状态存储组件用于连接到 OCI 的账户的标识符;这必须是在指定区间和存储桶中对 OCI 对象存储服务具有适当权限的账户。当 instancePrincipalAuthentication 为 true 或 configFileAuthentication 为 true 时不使用。
  • fingerPrint:为 userOCID 指示的账户生成的 RSA 密钥对中公钥的指纹。当 instancePrincipalAuthentication 为 true 或 configFileAuthentication 为 true 时不使用。
  • privateKey:为 userOCID 指示的账户生成的 RSA 密钥对中的私钥。当 instancePrincipalAuthentication 为 true 或 configFileAuthentication 为 true 时不使用。
  • region:OCI 区域——例如 us-ashburn-1eu-amsterdam-1ap-mumbai-1。当 instancePrincipalAuthentication 为 true 时不使用
  • bucketName:OCI 对象存储上将创建状态的存储桶名称。此存储桶在状态存储初始化时可能已存在,或将在状态存储初始化期间创建。请注意,存储桶名称在命名空间内是唯一的。
  • compartmentOCID:租户中区间的标识符,存储桶在其中存在或将被创建。

运行时会发生什么?

每个状态条目在 OCI 对象存储中都由一个对象表示。OCI 对象存储状态存储使用在对 Dapr API 的请求中提供的 key 属性来确定对象的名称。value 作为对象的(字面)内容存储。每个对象都被分配一个唯一的 ETag 值——每当它被创建或更新(即覆盖)时;这是 OCI 对象存储的本机行为。状态存储为它写入的每个对象分配一个元数据标签;该标签是 category,其值是 dapr-state-store。这允许识别为 Dapr 应用程序的状态而创建的对象。

例如,以下操作

curl -X POST http://localhost:3500/v1.0/state \
  -H "Content-Type: application/json"
  -d '[
        {
          "key": "nihilus",
          "value": "darth"
        }
      ]'

创建以下对象:

存储桶目录对象名称对象内容元标签
components.yaml 中由 bucketName 指定-(根目录)nihilusdarthcategory: dapr-state-store

Dapr 使用具有复合键的固定键方案在应用程序之间分区状态。对于一般状态,键格式为: App-ID||state key OCI 对象存储状态存储将第一个键段(用于 App-ID)映射到存储桶内的目录,使用 OCI 对象存储文档中描述的用于模拟目录结构的前缀和层次结构

因此,以下操作(注意复合键)

curl -X POST http://localhost:3500/v1.0/state \
  -H "Content-Type: application/json"
  -d '[
        {
          "key": "myApplication||nihilus",
          "value": "darth"
        }
      ]'

将创建以下对象:

存储桶目录对象名称对象内容元标签
components.yaml 中由 bucketName 指定myApplicationnihilusdarthcategory: dapr-state-store

您将能够通过控制台、API、CLI 或 SDK 检查存储桶的内容来检查通过 OCI 对象存储状态存储存储的所有状态。通过直接访问存储桶,您可以准备在运行时作为状态提供给您的应用程序的状态。

生存时间和状态过期

OCI 对象存储状态存储支持 Dapr 的生存时间(TTL)逻辑,确保过期后无法检索状态。有关详细信息,请参阅有关设置状态生存时间的操作指南

OCI 对象存储本身不支持生存时间设置。此组件中的实现使用放在为其指定了 TTL 的每个对象上的元数据标签。该标签称为 expiry-time-from-ttl,它包含 ISO 日期时间格式的字符串,带有基于 UTC 的过期时间。当通过调用 Get 检索状态时,此组件检查是否设置了 expiry-time-from-ttl,如果设置了,则检查它是否已过期。在这种情况下,不返回状态。

因此,以下操作(注意复合键)

curl -X POST http://localhost:3500/v1.0/state \
  -H "Content-Type: application/json"
  -d '[
        {
          "key": "temporary",
          "value": "ephemeral",
          "metadata": {"ttlInSeconds": "120"}}
        }
      ]'

创建以下对象:

存储桶目录对象名称对象内容元标签
components.yaml 中由 bucketName 指定-nihilusdarthcategory: dapr-state-store , expiry-time-from-ttl: 2022-01-06T08:34:32

expiry-time-from-ttl 的确切值当然取决于状态创建的时间,并且将是该时间之后 120 秒。

请注意,此组件不会从状态存储中删除过期的状态。应用程序操作员可以决定运行定期作业以执行某种形式的垃圾回收,以显式删除所有具有时间戳已过去的 expiry-time-from-ttl 标签的状态。

并发性

OCI 对象存储状态并发性是通过使用 ETag 实现的。OCI 对象存储中的每个对象在创建或更新(即替换)时都会被分配一个唯一的 ETag。当此状态存储的 SetDelete 请求指定 FirstWrite 并发策略时,请求需要提供要写入或删除的状态的实际 ETag 值,请求才能成功。

一致性

OCI 对象存储状态不支持事务。

查询

OCI 对象存储状态不支持查询 API。

相关链接

24 - Oracle Database

Oracle Database 状态存储组件的详细信息

组件格式

创建一个组件属性 yaml 文件,例如命名为 oracle.yaml(但可以命名为任何名称),粘贴以下内容并将 <CONNECTION STRING> 值替换为你的连接字符串。连接字符串是一个标准的 Oracle Database 连接字符串,格式为:"oracle://user/password@host:port/servicename",例如 "oracle://demo:demo@localhost:1521/xe"

如果你使用 Oracle Wallet 连接数据库,应该为 oracleWalletLocation 属性指定一个值,例如:"/home/app/state/Wallet_daprDB/";这应该指向本地文件系统目录,该目录包含从 Oracle Wallet 归档文件中提取的 cwallet.sso 文件。

apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
  name: <NAME>
spec:
  type: state.oracledatabase
  version: v1
  metadata:
  - name: connectionString
    value: "<CONNECTION STRING>"
  - name: oracleWalletLocation
    value: "<FULL PATH TO DIRECTORY WITH ORACLE WALLET CONTENTS >"  # 可选,无默认值
  - name: tableName
    value: "<NAME OF DATABASE TABLE TO STORE STATE IN >" # 可选,默认为 STATE
  # 如果你想将 Oracle Database 用作 actor 的状态存储,请取消注释(可选)
  #- name: actorStateStore
  #  value: "true"

规范元数据字段

FieldRequiredDetailsExample
connectionStringYOracle Database 的连接字符串例如 "oracle://user/password@host:port/servicename""oracle://demo:demo@localhost:1521/xe",对于 Autonomous Database 则为 "oracle://states_schema:State12345pw@adb.us-ashburn-1.oraclecloud.com:1522/k8j2agsqjsw_daprdb_low.adb.oraclecloud.com"
oracleWalletLocationNOracle Wallet 文件内容的位置(连接 OCI 上的 Autonomous Database 所需)"/home/app/state/Wallet_daprDB/"
tableNameN此状态存储实例记录数据的数据库表名称,默认为 "STATE""MY_APP_STATE_STORE"
actorStateStoreN是否将此状态存储用于 actor。默认为 "false""true", "false"

运行时会发生什么?

当状态存储组件初始化时,它会连接到 Oracle Database 并检查是否存在与 tableName 指定名称相同的表。如果不存在,它会创建此表(包含 Key、Value、Binary_YN、ETag、Creation_Time、Update_Time、Expiration_time 列)。

每个状态条目由数据库表中的一条记录表示。请求中提供的 key 属性用于确定存储在 KEY 列中的对象的名称。value 作为对象的内容存储。二进制内容以 Base64 编码文本的形式存储。每个对象在创建或更新时都会被分配一个唯一的 ETag 值。

例如,以下操作

curl -X POST http://localhost:3500/v1.0/state \
  -H "Content-Type: application/json"
  -d '[
        {
          "key": "nihilus",
          "value": "darth"
        }
      ]'

会在表 STATE 中创建以下记录:

KEYVALUECREATION_TIMEBINARY_YNETAG
nihilusdarth2022-02-14T22:11:00N79dfb504-5b27-43f6-950f-d55d5ae0894f

Dapr 使用固定 key 方案和组合键在应用程序之间分区状态。对于一般状态,key 格式为: App-ID||state key。Oracle Database 状态存储将此 key 完整映射到 KEY 列。

你可以轻松地使用 SQL 查询检查 tableName 表中存储的所有状态,例如 STATE 表。

生存时间和状态过期

Oracle Database 状态存储组件支持 Dapr 的生存时间逻辑,确保过期后无法检索状态。有关详细信息,请参阅关于设置状态生存时间的 How To

Oracle Database 没有对生存时间设置的内置支持。此组件中的实现使用名为 EXPIRATION_TIME 的列来保存记录被视为过期之后的时间。只有在 Set 请求中指定了 TTL 时,才会设置此列中的值。它被计算为当前 UTC 时间戳加上 TTL 周期。当通过 Get 调用检索状态时,此组件会检查是否设置了 EXPIRATION_TIME,如果设置了,它会检查该时间是否已过去。在这种情况下,不返回任何状态。

以下操作:

curl -X POST http://localhost:3500/v1.0/state \
  -H "Content-Type: application/json"
  -d '[
        {
          "key": "temporary",
          "value": "ephemeral",
          "metadata": {"ttlInSeconds": "120"}}
        }
      ]'

创建以下对象:

KEYVALUECREATION_TIMEEXPIRATION_TIMEBINARY_YNETAG
temporaryephemeral2022-03-31T22:11:002022-03-31T22:13:00N79dfb504-5b27-43f6-950f-d55d5ae0894f

其中 EXPIRATION_TIME 被设置为比 CREATION_TIME 晚 2 分钟(120 秒)的时间戳

请注意,过期状态不会被此组件从状态存储中删除。应用程序操作员可能会决定运行一个定期作业来执行某种形式的垃圾回收,以显式删除所有 EXPIRATION_TIME 在过去的记录。用于收集过期垃圾记录的 SQL 语句:

 delete dapr_state 
 where  expiration_time < SYS_EXTRACT_UTC(SYSTIMESTAMP);

并发

Oracle Database 状态存储中的并发是通过使用 ETag 实现的。在 Oracle Database 状态存储中记录的每条状态在创建或更新时都会被分配一个唯一的 ETag——一个存储在 ETag 列中的生成的唯一字符串。注意:当对现有记录执行 Set 操作时,UPDATE_TIME 列也会被更新。

只有当此状态存储的 SetDelete 请求指定 FirstWrite 并发策略时,请求才需要提供要写入或删除的状态的实际 ETag 值,请求才能成功。如果指定了不同或没有并发策略,则不会对 ETag 值执行检查。

一致性

Oracle Database 状态存储支持事务。多个 SetDelete 命令可以组合在一个请求中,该请求作为单个原子事务处理。

注意:简单的 SetDelete 操作本身就是事务;当 SetDelete 请求返回 HTTP-20X 结果时,数据库事务已成功提交。

查询

Oracle Database 状态存储目前不支持查询 API。

创建 Oracle Database 和用户模式

  1. 运行 Oracle Database 实例。你可以使用以下命令在 Docker CE 中运行 Oracle Database 的本地实例——或者当然使用现有的 Oracle Database:

    docker run -d -p 1521:1521 -e ORACLE_PASSWORD=TheSuperSecret1509! gvenzl/oracle-xe
    

    此示例未描述生产配置,因为它以纯文本形式为用户 SYSSYSTEM 设置密码。

    当命令的输出指示容器正在运行时,使用 docker ps 命令了解容器 id。然后使用以下命令启动 shell 会话:

    docker exec -it <container id> /bin/bash
    

    随后运行 SQL*Plus 客户端,以 SYS 用户身份连接到数据库:

    sqlplus sys/TheSuperSecret1509! as sysdba
    
  2. 为状态数据创建数据库模式。创建一个新的用户模式——例如名为 dapr——用于存储状态数据。授予此用户(模式)创建表和在关联表空间中存储数据的权限。

    要在 Oracle Database 中创建新的用户模式,请运行以下 SQL 命令:

    create user dapr identified by DaprPassword4239 default tablespace users quota unlimited on users;
    grant create session, create table to dapr;
    
  3. (可选)创建用于存储状态记录的表。 Oracle Database 状态存储组件检查存储状态的表是否已存在于它连接的数据库用户模式中,如果不存在,它会创建该表。但是,除了让 Oracle Database 状态存储组件在运行时创建用于存储状态记录的表之外,你还可以提前创建表。这为你——或数据库的 DBA——提供对表的物理配置的更多控制。这也意味着你不必将创建表权限授予用户模式。

    运行以下 DDL 语句以在 dapr 数据库用户模式中创建用于存储状态的表:

    CREATE TABLE dapr_state (
    		key varchar2(2000) NOT NULL PRIMARY KEY,
    		value clob NOT NULL,
    		binary_yn varchar2(1) NOT NULL,
    		etag varchar2(50)  NOT NULL,
    		creation_time TIMESTAMP WITH TIME ZONE DEFAULT SYSTIMESTAMP NOT NULL ,
    		expiration_time TIMESTAMP WITH TIME ZONE NULL,
    		update_time TIMESTAMP WITH TIME ZONE NULL
      )
    
  1. 在 Oracle Cloud Infrastructure 上创建免费(或付费)的自治事务处理(ATP)或 ADW(自治数据仓库)实例,如 OCI 永久免费自治数据库文档 中所述。

    你需要提供用户 ADMIN 的密码。你使用此帐户(至少最初)用于数据库管理活动。你可以在基于 Web 的 SQL Developer 工具、其桌面对应工具或许多数据库开发工具中的任何一个中工作。

  2. 为状态数据创建模式。 在 Oracle Database 中创建一个新的用户模式用于存储状态数据——例如使用 ADMIN 帐户。授予这个新用户(模式)创建表和在关联表空间中存储数据的权限。

    要在 Oracle Database 中创建新的用户模式,请运行以下 SQL 命令:

    create user dapr identified by DaprPassword4239 default tablespace users quota unlimited on users;
    grant create session, create table to dapr;
    
  3. (可选)创建用于存储状态记录的表。 Oracle Database 状态存储组件检查存储状态的表是否已存在于它连接的数据库用户模式中,如果不存在,它会创建该表。但是,除了让 Oracle Database 状态存储组件在运行时创建用于存储状态记录的表之外,你还可以提前创建表。这为你——或数据库的 DBA——提供对表的物理配置的更多控制。这也意味着你不必将创建表权限授予用户模式。

    运行以下 DDL 语句以在 dapr 数据库用户模式中创建用于存储状态的表:

    CREATE TABLE dapr_state (
    		key varchar2(2000) NOT NULL PRIMARY KEY,
    		value clob NOT NULL,
    		binary_yn varchar2(1) NOT NULL,
    		etag varchar2(50)  NOT NULL,
    		creation_time TIMESTAMP WITH TIME ZONE DEFAULT SYSTIMESTAMP NOT NULL ,
    		expiration_time TIMESTAMP WITH TIME ZONE NULL,
    		update_time TIMESTAMP WITH TIME ZONE NULL
      )
    

相关链接

25 - PostgreSQL

PostgreSQL 状态存储组件的详细信息

此组件允许使用 PostgreSQL (Postgres) 作为 Dapr 的状态存储,使用 “v2” 组件。请参阅此指南了解如何创建和应用状态存储配置。

apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
  name: <NAME>
spec:
  type: state.postgresql
  # 注意:设置 "version" 为 "v2" 是使用组件 v2 的必需项
  version: v2
  metadata:
    # 连接字符串
    - name: connectionString
      value: "<CONNECTION STRING>"
    # 单独的连接参数 - 可用于覆盖 connectionString 参数
    #- name: host
    #  value: "localhost"
    #- name: hostaddr
    #  value: "127.0.0.1"
    #- name: port
    #  value: "5432"
    #- name: database
    #  value: "my_db"
    #- name: user
    #  value: "postgres"
    #- name: password
    #  value: "example"
    #- name: sslRootCert
    #  value: "/path/to/ca.crt"
    # 数据库操作超时时间,作为 Go duration 或秒数(可选)
    #- name: timeout
    #  value: 20
    # 存储数据的表前缀(可选)
    #- name: tablePrefix
    #  value: ""
    # Dapr 用于存储元数据的表名称(可选)
    #- name: metadataTableName
    #  value: "dapr_metadata"
    # 清理过期行的时间间隔(秒)(可选)
    #- name: cleanupInterval
    #  value: "1h"
    # 此组件连接池的最大连接数(可选)
    #- name: maxConns
    #  value: 0
    # 连接的最大空闲时间,超过此时间后将关闭连接(可选)
    #- name: connectionMaxIdleTime
    #  value: 0
    # 控制执行查询的默认模式(可选)
    #- name: queryExecMode
    #  value: ""
    # 如果希望将 PostgreSQL 用作 actor 或工作流的状态存储,请取消注释(可选)
    #- name: actorStateStore
    #  value: "true"

规范元数据字段

使用连接字符串进行身份验证

以下元数据选项是使用 PostgreSQL 连接字符串进行身份验证的必需项。

字段必需详情示例
connectionStringYPostgreSQL 数据库的连接字符串。有关如何定义连接字符串的信息,请参阅 PostgreSQL 数据库连接文档"host=localhost user=postgres password=example port=5432 connect_timeout=10 database=my_db"

使用单独的连接参数进行身份验证

除了使用连接字符串外,您还可以选择指定单独的连接参数。这些参数等同于标准 PostgreSQL 连接参数。

字段必需详情示例
hostYPostgreSQL 服务器的主机名或 IP 地址"localhost"
hostaddrNPostgreSQL 服务器的 IP 地址(host 的替代方案)"127.0.0.1"
portYPostgreSQL 服务器的端口号"5432"
databaseY要连接的数据库名称"my_db"
userY用于连接的 PostgreSQL 用户"postgres"
passwordYPostgreSQL 用户的密码"example"
sslRootCertNSSL 根证书文件的路径"/path/to/ca.crt"

使用 Microsoft Entra ID 进行身份验证

Azure Database for PostgreSQL 支持使用 Microsoft Entra ID 进行身份验证。可以使用 Dapr 支持的所有身份验证方法,包括客户端凭据(“服务主体”)和托管标识。

字段必需详情示例
useAzureADY必须设置为 true 以启用组件从 Microsoft Entra ID 获取访问令牌。"true"
connectionStringYPostgreSQL 数据库的连接字符串。
必须包含用户,对应于在 PostgreSQL 内部创建的映射到 Microsoft Entra ID 标识的用户名称。这通常是对应主体的名称(例如,Microsoft Entra ID 应用程序的名称)。此连接字符串不应包含任何密码。
"host=mydb.postgres.database.azure.com user=myapplication port=5432 database=my_db sslmode=require"
azureTenantIdNMicrosoft Entra ID 租户的 ID"cd4b2887-304c-…"
azureClientIdN客户端 ID(应用程序 ID)"c7dd251f-811f-…"
azureClientSecretN客户端密钥(应用程序密码)"Ecy3X…"

使用 AWS IAM 进行身份验证

所有版本的 PostgreSQL 类型组件都支持使用 AWS IAM 进行身份验证。 连接字符串中指定的用户必须是数据库中已存在的用户,并且是已授予 rds_iam 数据库角色的 AWS IAM 启用用户。 身份验证基于 AWS 身份验证配置文件或提供的 AccessKey/SecretKey。 AWS 身份验证令牌将在其过期时间之前与 AWS 动态轮换。

字段必需详情示例
useAWSIAMY必须设置为 true 以启用组件从 AWS IAM 获取访问令牌。此身份验证方法仅适用于 AWS Relational Database Service 的 PostgreSQL 数据库。"true"
connectionStringYPostgreSQL 数据库的连接字符串。
必须包含已存在的用户,对应于在 PostgreSQL 内部创建的映射到 AWS IAM 策略的用户名称。此连接字符串不应包含任何密码。请注意,数据库名字段在 AWS 中表示为 dbname。
"host=mydb.postgres.database.aws.com user=myapplication port=5432 dbname=my_db sslmode=require"
awsRegionN这保持与现有字段的向后兼容性。它将在 Dapr 1.17 起被弃用。请改用 ‘region’。部署 AWS Relational Database Service 的 AWS 区域。"us-east-1"
awsAccessKeyN这保持与现有字段的向后兼容性。它将在 Dapr 1.17 起被弃用。请改用 ‘accessKey’。与 IAM 账户关联的 AWS 访问密钥"AKIAIOSFODNN7EXAMPLE"
awsSecretKeyN这保持与现有字段的向后兼容性。它将在 Dapr 1.17 起被弃用。请改用 ‘secretKey’。与访问密钥关联的密钥"wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"
awsSessionTokenN这保持与现有字段的向后兼容性。它将在 Dapr 1.17 起被弃用。请改用 ‘sessionToken’。要使用的 AWS 会话令牌。仅当您使用临时安全凭证时才需要会话令牌。"TOKEN"

其他元数据选项

字段必需详情示例
tablePrefixN存储数据的表的前缀。可以选择性地将架构名称作为前缀,例如 public.prefix_"prefix_", "public.prefix_"
metadataTableNameNDapr 用于存储一些元数据属性的表的名称。默认为 dapr_metadata。可以选择性地将架构名称作为前缀,例如 public.dapr_metadata"dapr_metadata", "public.dapr_metadata"
timeoutN数据库操作的超时时间,作为 Go duration。整数被解释为秒数。默认为 20s"30s", 30
cleanupIntervalN清理过期 TTL 行的时间间隔,作为 Go duration 或秒数。默认:1h(1 小时)。将此设置为 <= 0 的值将禁用定期清理。"30m", 1800, -1
maxConnsN此组件连接池的最大连接数。设置为 0 或更低以使用默认值,即 4 或 CPU 数量中的较大者。"4"
connectionMaxIdleTimeN未使用的连接在连接池中自动关闭前的最大空闲时间。默认情况下,没有值,这留给数据库驱动程序选择。"5m"
queryExecModeN控制执行查询的默认模式。默认情况下,Dapr 使用扩展协议并自动准备和缓存预处理语句。然而,这可能与 PGBouncer 等代理不兼容。在这种情况下,最好使用 execsimple_protocol"simple_protocol"
actorStateStoreN将此状态存储用于 actor。默认为 "false""true", "false"

设置 PostgreSQL

  1. 运行 PostgreSQL 实例。您可以使用以下命令在 Docker 中运行本地 PostgreSQL 实例:

    docker run -p 5432:5432 -e POSTGRES_PASSWORD=example postgres
    

    此示例未描述生产环境配置,因为它以纯文本设置密码,用户名保留为 PostgreSQL 默认的 “postgres”。

  2. 为状态数据创建数据库。
    可以使用默认的 “postgres” 数据库,也可以创建一个新数据库来存储状态数据。

    要在 PostgreSQL 中创建新数据库,请运行以下 SQL 命令:

    CREATE DATABASE my_dapr;
    

高级

v1 和 v2 之间的差异

PostgreSQL 状态存储 v2 在 Dapr 1.13 中引入。现有的 v1 仍然可用,并未被弃用。

在 v2 组件中,表架构已进行了重大更改,旨在提高性能和可靠性。最值得注意的是,Dapr 存储的值现在为 BYTEA 类型,这允许更快的查询,并且在某些情况下比以前使用的 JSONB 列更节省空间。
然而,由于此更改,v2 组件不支持 Dapr 状态存储查询 API

此外,在 v2 组件中,ETag 现在是随机 UUID,这确保了与其他 PostgreSQL 兼容数据库(如 CockroachDB)的更好兼容性。

由于这些更改,v1 和 v2 组件无法从同一个表读取或写入数据。在此阶段,也无法在两个版本的组件之间迁移数据。

以人类可读格式显示数据

PostgreSQL v2 组件将状态的值存储在 value 列中,该列的类型为 BYTEA。大多数 PostgreSQL 工具(包括 pgAdmin)将值视为二进制,默认情况下不会以人类可读的形式显示。

如果您想检查状态存储中的值,并且您知道它不是二进制数据(例如,JSON 数据),您可以使用如下查询以人类可读的形式显示值:

-- 将 "state" 替换为您环境中的状态表的名称
SELECT *, convert_from(value, 'utf-8') FROM state;

TTL 和清理

此状态存储支持使用 Dapr 存储的记录的生存时间(TTL)。使用 Dapr 存储数据时,您可以设置 ttlInSeconds 元数据属性来指示数据应在多少秒后被视为"过期"。

由于 PostgreSQL 没有内置的 TTL 支持,这是通过在状态表中添加一个列来实现的,该列指示数据何时应被视为"过期"。即使仍物理存储在数据库中,“过期"的记录也不会返回给调用方。后台"垃圾收集器"会定期扫描状态表中的过期行并删除它们。

您可以使用 cleanupInterval 元数据属性设置过期记录的删除时间间隔,默认为 3600 秒(即 1 小时)。

  • 较长的间隔需要较少的过期行扫描频率,但可能需要存储过期记录更长时间,可能需要更多的存储空间。如果您计划在状态表中存储许多具有短 TTL 的记录,请考虑将 cleanupInterval 设置为较小的值;例如,5m(5 分钟)。
  • 如果您不计划将 TTL 与 Dapr 和 PostgreSQL 状态存储一起使用,您应该考虑将 cleanupInterval 设置为 <= 0 的值(例如,0-1)以禁用定期清理并减少数据库的负载。

相关链接

26 - PostgreSQL v1

关于 PostgreSQL v1 状态存储组件的详细信息

该组件允许使用 PostgreSQL (Postgres) 作为 Dapr 的状态存储,使用 “v1” 组件。请参阅此指南了解如何创建和应用状态存储配置。

apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
  name: <NAME>
spec:
  type: state.postgresql
  version: v1
  metadata:
    # 连接字符串
    - name: connectionString
      value: "<CONNECTION STRING>"
    # 单独的连接参数 - 可用于覆盖 connectionString 参数
    #- name: host
    #  value: "localhost"
    #- name: hostaddr
    #  value: "127.0.0.1"
    #- name: port
    #  value: "5432"
    #- name: database
    #  value: "my_db"
    #- name: user
    #  value: "postgres"
    #- name: password
    #  value: "example"
    #- name: sslRootCert
    #  value: "/path/to/ca.crt"
    # 数据库操作超时时间,以 Go duration 或秒数表示(可选)
    #- name: timeout
    #  value: 20
    # 用于存储状态的表名(可选)
    #- name: tableName
    #  value: "state"
    # 用于存储 Dapr 元数据的表名(可选)
    #- name: metadataTableName
    #  value: "dapr_metadata"
    # 清理间隔(秒),用于删除过期的行(可选)
    #- name: cleanupInterval
    #  value: "1h"
    # 该组件池化的最大连接数(可选)
    #- name: maxConns
    #  value: 0
    # 连接关闭前的最大空闲时间(可选)
    #- name: connectionMaxIdleTime
    #  value: 0
    # 控制执行查询的默认模式(可选)
    #- name: queryExecMode
    #  value: ""
    # 如果您希望将 PostgreSQL 用作 actor 或工作流的状态存储,请取消注释(可选)
    #- name: actorStateStore
    #  value: "true"

规范元数据字段

使用连接字符串进行身份验证

使用 PostgreSQL 连接字符串进行身份验证时,以下元数据选项是必需的

字段必需详情示例
connectionStringYPostgreSQL 数据库的连接字符串。有关如何定义连接字符串的信息,请参阅 PostgreSQL 数据库连接文档"host=localhost user=postgres password=example port=5432 connect_timeout=10 database=my_db"

使用单独的连接参数进行身份验证

除了使用连接字符串外,您还可以选择指定单独的连接参数。这些参数等同于标准 PostgreSQL 连接参数。

字段必需详情示例
hostYPostgreSQL 服务器的主机名或 IP 地址"localhost"
hostaddrNPostgreSQL 服务器的 IP 地址(host 的替代方案)"127.0.0.1"
portYPostgreSQL 服务器的端口号"5432"
databaseY要连接的数据库名称"my_db"
userY要连接的 PostgreSQL 用户"postgres"
passwordYPostgreSQL 用户的密码"example"
sslRootCertNSSL 根证书文件的路径"/path/to/ca.crt"

使用 Microsoft Entra ID 进行身份验证

支持使用 Microsoft Entra ID 进行身份验证,适用于 Azure Database for PostgreSQL。Dapr 支持的所有身份验证方法都可以使用,包括客户端凭据(“服务主体”)和托管标识。

字段必需详情示例
useAzureADY必须设置为 true 以启用组件从 Microsoft Entra ID 获取访问令牌。"true"
connectionStringYPostgreSQL 数据库的连接字符串。
这必须包含用户,对应于在 PostgreSQL 中创建的映射到 Microsoft Entra ID 标识的用户名称;这通常是相应主体的名称(例如 Microsoft Entra ID 应用程序的名称)。此连接字符串不应包含任何密码。
"host=mydb.postgres.database.azure.com user=myapplication port=5432 database=my_db sslmode=require"
azureTenantIdNMicrosoft Entra ID 租户的 ID"cd4b2887-304c-…"
azureClientIdN客户端 ID(应用程序 ID)"c7dd251f-811f-…"
azureClientSecretN客户端密钥(应用程序密码)"Ecy3X…"

使用 AWS IAM 进行身份验证

支持使用 AWS IAM 进行身份验证,适用于所有版本的 PostgreSQL 类型组件。 连接字符串中指定的用户必须是数据库中已存在的用户,并且是被授予 rds_iam 数据库角色的 AWS IAM 启用用户。 身份验证基于 AWS 身份验证配置文件,或提供的 AccessKey/SecretKey。 AWS 身份验证令牌将在其过期时间之前由 AWS 动态轮换。

字段必需详情示例
useAWSIAMY必须设置为 true 以启用组件从 AWS IAM 获取访问令牌。此身份验证方法仅适用于 AWS Relational Database Service for PostgreSQL 数据库。"true"
connectionStringYPostgreSQL 数据库的连接字符串。
这必须包含已存在的用户,对应于在 PostgreSQL 中创建的映射到 AWS IAM 策略的用户名称。此连接字符串不应包含任何密码。请注意,使用 AWS 时数据库名称字段表示为 dbname。
"host=mydb.postgres.database.aws.com user=myapplication port=5432 dbname=my_db sslmode=require"
awsRegionN部署 AWS Relational Database Service 的 AWS 区域。"us-east-1"
awsAccessKeyN与 IAM 账户关联的 AWS 访问密钥"AKIAIOSFODNN7EXAMPLE"
awsSecretKeyN与访问密钥关联的密钥"wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"
awsSessionTokenN要使用的 AWS 会话令牌。仅在使用临时安全凭证时才需要会话令牌。"TOKEN"

其他元数据选项

字段必需详情示例
tableNameN存储数据的表的名称。默认为 state。可以选择性地将架构名称作为前缀,例如 public.state"state", "public.state"
metadataTableNameNDapr 用于存储少量元数据属性的表的名称。默认为 dapr_metadata。可以选择性地将架构名称作为前缀,例如 public.dapr_metadata"dapr_metadata", "public.dapr_metadata"
timeoutN数据库操作的超时时间,以 Go duration 表示。整数被解释为秒数。默认为 20s"30s", 30
cleanupIntervalN清理 TTL 过期的行的时间间隔,以 Go duration 或秒数表示。默认值:1h(1 小时)。将此值设置为 <= 0 会禁用定期清理。"30m", 1800, -1
maxConnsN该组件池化的最大连接数。设置为 0 或更低以使用默认值,即 4 或 CPU 数量中的较大者。"4"
connectionMaxIdleTimeN未使用的连接在连接池中自动关闭前的最大空闲时间。默认情况下,没有值,这留给数据库驱动程序选择。"5m"
queryExecModeN控制执行查询的默认模式。默认情况下,Dapr 使用扩展协议并自动准备和缓存预处理语句。但是,这可能与 PGBouncer 等代理不兼容。在这种情况下,使用 execsimple_protocol 可能更可取。"simple_protocol"
actorStateStoreN将此状态存储用于 Actor。默认为 "false""true", "false"

设置 PostgreSQL

  1. 运行一个 PostgreSQL 实例。您可以使用以下命令在 Docker CE 中运行本地 PostgreSQL 实例:

    docker run -p 5432:5432 -e POSTGRES_PASSWORD=example postgres
    

    此示例未描述生产配置,因为它以纯文本设置密码,并且用户名保留为 PostgreSQL 默认值 “postgres”。

  2. 为状态数据创建一个数据库。
    可以使用默认的 “postgres” 数据库,也可以创建一个新数据库来存储状态数据。

    要在 PostgreSQL 中创建新数据库,请运行以下 SQL 命令:

    CREATE DATABASE my_dapr;
    

高级

TTL 和清理

该状态存储支持使用 Dapr 存储的记录的 Time-To-Live (TTL)。使用 Dapr 存储数据时,您可以设置 ttlInSeconds 元数据属性来指示数据应在多少秒后被视为"过期"。

由于 PostgreSQL 没有内置的 TTL 支持,这是在 Dapr 中通过在状态表中添加一个列来实现的,该列指示数据何时被视为"过期"。即使"过期"记录仍物理存储在数据库中,也不会返回给调用者。后台"垃圾收集器"定期扫描状态表中的过期行并删除它们。

您可以使用 cleanupInterval 元数据属性设置过期记录的删除间隔,默认为 3600 秒(即 1 小时)。

  • 较长的间隔需要较少的过期行扫描频率,但可能需要存储过期记录更长时间,可能需要更多存储空间。如果您计划在状态表中存储许多具有短 TTL 的记录,请考虑将 cleanupInterval 设置为更小的值;例如,5m(5 分钟)。
  • 如果您不打算将 TTL 与 Dapr 和 PostgreSQL 状态存储一起使用,应考虑将 cleanupInterval 设置为 <= 0 的值(例如 0-1)以禁用定期清理并减少数据库负载。

状态表中存储记录过期日期的列 expiredate 默认没有索引,因此每次定期清理都必须执行全表扫描。如果您的表中有大量记录,并且只有其中一些使用 TTL,您可能会发现在该列上创建索引很有用。假设您的状态表名称是 state(默认值),您可以使用此查询:

CREATE INDEX expiredate_idx
    ON state
    USING btree (expiredate ASC NULLS LAST);

相关链接

27 - RavenDB

RavenDB 状态存储组件的详细信息

组件格式

要设置 RavenDB 状态存储,需创建类型为 state.ravendb 的组件。请参阅此指南了解如何创建和应用状态存储配置。

apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
  name: <NAME>
spec:
  type: state.ravendb
  version: v1
  metadata:
  - name: serverURL
    value: <REPLACE-WITH-SERVER-URL> # 必填。示例:"http://localhost:8080"
  - name: databaseName
    value: <REPLACE-WITH-DATABASE-NAME> # 可选。默认值:"daprStore"
  - name: certPath
    value: <REPLACE-WITH-CERT-PATH> # 除非服务器不安全,否则必填。
  - name: keyPath
    value: <REPLACE-WITH-KEY-PATH> # 除非服务器不安全,否则必填。
  - name: EnableTTL
    value: <REPLACE-WITH-ENABLE-TTL> # 可选。默认值:"true"
  - name: TTLFrequency
    value: <REPLACE-WITH-TTL-FREQUENCY> # 可选。示例:"15"。默认值:"60"

规范元数据字段

FieldRequiredDetailsExample
serverURLYRavenDB 实例的 URL"http://localhost:8080"
databaseNameN要使用的数据库名称。默认为 "daprStore""daprStore"
certPathN1证书文件路径"/path/to/client.certificate.crt"
keyPathN1密钥文件路径"/path/to/certificate.key"
EnableTTLN启用 TTL 功能的布尔值。默认为 "true""true"
TTLFrequencyNTTL 清理频率(秒)。默认为 "60""60"

[1] 如果服务器 URL 为 http,则 certPathkeyPath 字段不是必填的。但是,如果服务器 URL 为 https 且未提供 certPathkeyPath,则 Dapr 会返回错误。

TTL 与清理

此状态存储支持使用 Dapr 存储记录的生存时间(Time-To-Live,TTL)。使用 Dapr 存储数据时,可以设置 ttlInSeconds 元数据属性来指示数据何时应被视为"过期"。

相关链接

28 - Redis

Redis 状态存储组件的详细信息

组件格式

要设置 Redis 状态存储,请创建一个类型为 state.redis 的组件。请参阅本指南了解如何创建和应用状态存储配置。

apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
  name: <NAME>
spec:
  type: state.redis
  version: v1
  metadata:
  - name: redisHost
    value: <HOST>
  - name: redisPassword # 可选
    value: <PASSWORD>
  - name: useEntraID
    value: <bool> # 可选,允许值:true, false
  - name: enableTLS
    value: <bool> # 可选,允许值:true, false
  - name: clientCert
    value: # 可选
  - name: clientKey
    value: # 可选    
  - name: maxRetries
    value: # 可选
  - name: maxRetryBackoff
    value: # 可选
  - name: failover
    value: <bool> # 可选,允许值:true, false
  - name: sentinelMasterName
    value: <string> # 可选
  - name: sentinelUsername
    value: # 可选
  - name: sentinelPassword
    value: # 可选
  - name: redeliverInterval
    value: # 可选
  - name: processingTimeout
    value: # 可选
  - name: redisType
    value: # 可选
  - name: redisDB
    value: # 可选
  - name: redisMaxRetries
    value: # 可选
  - name: redisMinRetryInterval
    value: # 可选
  - name: redisMaxRetryInterval
    value: # 可选
  - name: dialTimeout
    value: # 可选
  - name: readTimeout
    value: # 可选
  - name: writeTimeout
    value: # 可选
  - name: poolSize
    value: # 可选
  - name: poolTimeout
    value: # 可选
  - name: maxConnAge
    value: # 可选
  - name: minIdleConns
    value: # 可选
  - name: idleCheckFrequency
    value: # 可选
  - name: idleTimeout
    value: # 可选
  - name: ttlInSeconds
    value: <int> # 可选
  - name: queryIndexes
    value: <string> # 可选
  # 如果希望将 Redis 用作 actor 的状态存储,请取消注释此行(可选)
  #- name: actorStateStore
  #  value: "true"

如果您希望将 Redis 用作 actor 存储,请在 yaml 中追加以下内容。

  - name: actorStateStore
    value: "true"

规范元数据字段

字段必填说明示例
redisHostYRedis 主机的连接字符串。如果 "redisType""cluster",可以是多个以逗号分隔的主机或单个主机。使用 Redis Sentinel("failover""true")时,也可以提供多个以逗号分隔的 sentinel 地址。localhost:6379redis-master.default.svc.cluster.local:6379sentinel1:26379,sentinel2:26379,sentinel3:26379
redisPasswordNRedis 主机的密码。无默认值。可以使用 secretKeyRef 来使用密钥引用"""KeFg23!"
redisUsernameNRedis 主机的用户名。默认为空。请确保您的 Redis 服务器版本为 6 或以上,并已正确创建 ACL 规则。"""default"
useEntraIDN为 Azure Cache for Redis 实现 EntraID 支持。启用此功能之前:
  • 必须以 "server:port" 的格式指定 redisHost 名称
  • 必须启用 TLS
创建 Redis 实例 > Azure Cache for Redis下了解有关此设置的更多信息
"true""false"
enableTLSN如果 Redis 实例支持使用公共证书的 TLS,可以配置为启用或禁用。默认为 "false""true""false"
clientCertN客户端证书的内容,用于需要客户端证书的 Redis 实例。必须与 clientKey 一起使用,且 enableTLS 必须设置为 true。建议按照此处的描述使用密钥存储"----BEGIN CERTIFICATE-----\nMIIC..."
clientKeyN客户端私钥的内容,与 clientCert 结合使用进行身份验证。建议按照此处的描述使用密钥存储"----BEGIN PRIVATE KEY-----\nMIIE..."
maxRetriesN放弃前的最大重试次数。默认为 3510
maxRetryBackoffN每次重试之间的最大退避时间。默认为 2 秒;"-1" 禁用退避。3000000000
failoverN启用故障转移配置的属性。需要设置 sentinelMasterName。启用时,redisHost 应包含 sentinel 地址。默认为 "false""true""false"
sentinelMasterNameNSentinel 主节点名称。请参阅 Redis Sentinel 文档"""mymaster"
sentinelUsernameNRedis Sentinel 的用户名。仅当 “failover” 为 true 且 Redis Sentinel 已启用身份验证时适用"username"
sentinelPasswordNRedis Sentinel 的密码。仅当 “failover” 为 true 且 Redis Sentinel 已启用身份验证时适用"password"
redeliverIntervalN检查待重新投递消息的间隔时间。默认为 "60s""0" 禁用重新投递。"30s"
processingTimeoutN消息在尝试重新投递之前必须保持待处理状态的时间量。默认为 "15s""0" 禁用重新投递。"30s"
redisTypeNRedis 的类型。有两个有效值,一个是 "node" 用于单节点模式,另一个是 "cluster" 用于 Redis 集群模式。默认为 "node""cluster"
redisDBN连接到 Redis 后选择的数据库。如果 "redisType""cluster",则忽略此选项。默认为 "0""0"
redisMaxRetriesNmaxRetries 的别名。如果两个值都已设置,则忽略 maxRetries"5"
redisMinRetryIntervalN每次重试之间 Redis 命令的最小退避时间。默认为 "8ms""-1" 禁用退避。"8ms"
redisMaxRetryIntervalNmaxRetryBackoff 的别名。如果两个值都已设置,则忽略 maxRetryBackoff"5s"
dialTimeoutN建立新连接的拨号超时时间。默认为 "5s""5s"
readTimeoutN套接字读取的超时时间。如果达到此时间,Redis 命令将以超时失败而不是阻塞。默认为 "3s""-1" 表示无超时。"3s"
writeTimeoutN套接字写入的超时时间。如果达到此时间,Redis 命令将以超时失败而不是阻塞。默认为 readTimeout。"3s"
poolSizeN套接字连接的最大数量。默认为每个 CPU 10 个连接,由 runtime.NumCPU 报告。"20"
poolTimeoutN如果所有连接都忙,客户端等待连接的时间,然后返回错误。默认为 readTimeout + 1 秒。"5s"
maxConnAgeN客户端退役(关闭)连接的连接时长。默认为不关闭旧连接。"30m"
minIdleConnsN保持打开的最小空闲连接数,以避免与创建新连接相关的性能下降。默认为 "0""2"
idleCheckFrequencyN空闲连接清理器执行的空闲检查频率。默认为 "1m""-1" 禁用空闲连接清理器。"-1"
idleTimeoutN客户端关闭空闲连接之后的时间量。应小于服务器的超时时间。默认为 "5m""-1" 禁用空闲超时检查。"10m"
ttlInSecondsN允许指定以秒为单位的默认生存时间(TTL),该时间将应用于每个状态存储请求,除非通过请求元数据显式定义 TTL。600
queryIndexesN用于查询 JSON 对象的索引模式参见查询 JSON 对象
actorStateStoreN将此状态存储用于 actor。默认为 "false""true""false"

设置 Redis

Dapr 可以使用任何 Redis 实例:容器化的、在本地开发机器上运行的或托管的云服务。

当您运行 dapr init 时,会自动创建一个 Redis 实例作为 Docker 容器

您可以使用 Helm 在 Kubernetes 集群中快速创建 Redis 实例。此方法需要安装 Helm

  1. 将 Redis 安装到您的集群中。请注意,我们显式设置了镜像标签以获取大于 5 的版本,这是 Dapr 的发布订阅功能所需的。如果您仅打算将 Redis 用作状态存储(而不是用于发布订阅),则不必设置镜像版本。

    helm repo add bitnami https://charts.bitnami.com/bitnami
    helm install redis bitnami/redis
    
  2. 运行 kubectl get pods 以查看 Redis 容器现在正在集群中运行。

  3. redis-master:6379 作为 redisHost 添加到您的 redis.yaml 文件中。例如:

        metadata:
        - name: redisHost
          value: redis-master:6379
    
  4. 接下来,获取 Redis 密码,根据我们使用的操作系统,这略有不同:

    • Windows:运行 kubectl get secret --namespace default redis -o jsonpath="{.data.redis-password}" > encoded.b64,这将创建一个包含编码密码的文件。接下来,运行 certutil -decode encoded.b64 password.txt,这将把您的 redis 密码放入名为 password.txt 的文本文件中。复制密码并删除这两个文件。

    • Linux/MacOS:运行 kubectl get secret --namespace default redis -o jsonpath="{.data.redis-password}" | base64 --decode 并复制输出的密码。

    将此密码作为 redisPassword 值添加到您的 redis.yaml 文件中。例如:

        metadata:
        - name: redisPassword
          value: lhDOkwTlp0
    
  1. 使用 Microsoft 官方文档创建 Azure Cache for Redis 实例。

  2. 创建实例后,从 Azure 门户获取主机名(FQDN)和访问密钥。

    • 对于主机名:
      • 导航到资源的概览页面。
      • 复制主机名值。
    • 对于访问密钥:
      • 导航到设置 > 访问密钥
      • 复制并保存您的密钥。
  3. 将您的密钥和主机名添加到 Dapr 可以应用到集群的 redis.yaml 文件中。

    • 如果您正在运行示例,请将主机和密钥添加到提供的 redis.yaml 中。
    • 如果您是从头开始创建项目,请按照组件格式部分中的说明创建 redis.yaml 文件。
  4. redisHost 键设置为 [上一步的主机名]:6379,将 redisPassword 键设置为之前保存的密钥。

    注意: 在生产级应用程序中,请遵循密钥管理说明来安全地管理您的密钥。

  5. 启用 EntraID 支持:

    • 在 Azure Redis 服务器上启用 Entra ID 身份验证。这可能需要几分钟。
    • useEntraID 设置为 "true" 以为 Azure Cache for Redis 实现 EntraID 支持。
  6. enableTLS 设置为 "true" 以支持 TLS。

注意:useEntraID 假定您的 UserPrincipal(通过 AzureCLICredential)或系统分配的托管身份具有 RedisDataOwner 角色权限。如果使用用户分配的托管身份,您需要指定 azureClientID 属性

查询 JSON 对象(可选)

除了支持以键值对的形式存储和查询状态数据外,Redis 状态存储还可选支持 JSON 对象查询,以满足更复杂的查询或过滤需求。要启用此功能,需要执行以下步骤:

  1. Redis 存储必须支持 Redis 模块,特别是 Redisearch 和 RedisJson。如果您正在部署和运行 Redis,则在部署 Redis 服务时加载 redisearchredisjson 模块。

  2. 在组件配置的元数据中指定 queryIndexes 条目。queryIndexes 的值是以下格式的 JSON 数组:

[
  {
    "name": "<索引名称>",
    "indexes": [
      {
        "key": "<文档内选定元素的 JSONPath 类似语法>",
        "type": "<值类型(支持的类型:TEXT、NUMERIC)>",
      },
      ...
    ]
  },
  ...
]
  1. 调用状态管理 API 时,将以下元数据添加到 API 调用中:
  • 保存状态获取状态删除状态
    • 向 HTTP API 请求添加 metadata.contentType=application/json URL 查询参数
    • 向 gRPC API 请求的元数据中添加 "contentType": "application/json" 键值对
  • 查询状态
    • 向 HTTP API 请求添加 metadata.contentType=application/json&metadata.queryIndexName=<索引名称> URL 查询参数
    • 向 gRPC API 请求的元数据中添加 "contentType" : "application/json""queryIndexName" : "<索引名称>" 键值对

考虑一个示例,您存储如下文档:

{
  "key": "1",
  "value": {
    "person": {
      "org": "Dev Ops",
      "id": 1036
    },
    "city": "Seattle",
    "state": "WA"
  }
}

包含相应索引模式的组件配置文件如下所示:

apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
  name: statestore
spec:
  type: state.redis
  version: v1
  initTimeout: 1m
  metadata:
  - name: redisHost
    value: "localhost:6379"
  - name: redisPassword
    value: ""
  - name: queryIndexes
    value: |
      [
        {
          "name": "orgIndx",
          "indexes": [
            {
              "key": "person.org",
              "type": "TEXT"
            },
            {
              "key": "person.id",
              "type": "NUMERIC"
            },
            {
              "key": "state",
              "type": "TEXT"
            },
            {
              "key": "city",
              "type": "TEXT"
            }
          ]
        }
      ]

因此,您现在可以存储、检索和查询这些文档。

考虑“操作方法:查询状态”指南中的示例。让我们使用 Redis 来运行它。

如果您使用的是 Dapr 的自托管部署,当您运行 dapr init 时,会自动创建一个没有 JSON 模块的 Redis 实例作为 Docker 容器。

或者,您可以通过运行以下命令创建 Redis 实例:

docker run -p 6379:6379 --name redis --rm redis

在 dapr init 时创建的或通过上述命令创建的 Redis 容器不能单独与状态存储查询 API 一起使用。您可以在与已安装的 Redis 使用的端口不同的端口上运行 redislabs/rejson docker 镜像,以使用查询 API。

注意:redislabs/rejson 仅支持 amd64 架构。

使用以下命令创建与查询 API 兼容的 redis 实例。

docker run -p 9445:9445 --name rejson --rm redislabs/rejson:2.0.6

按照 Redis 在 Kubernetes 中部署的说明操作,但有一个额外的细节。

安装 Redis Helm 软件包时,提供一个指定容器镜像并启用所需模块的配置文件:

helm install redis bitnami/redis --set image.tag=6.2 -f values.yaml

其中 values.yaml 如下所示:

image:
  repository: redislabs/rejson
  tag: 2.0.6

master:
  extraFlags:
   - --loadmodule
   - /usr/lib/redis/modules/rejson.so
   - --loadmodule
   - /usr/lib/redis/modules/redisearch.so

按照 Redis 在 AWS 中部署的说明操作。

接下来是启动 Dapr 应用程序。请参阅此组件配置文件,其中包含查询索引模式。确保修改 redisHost 以反映 redislabs/rejson 使用的本地转发端口。

dapr run --app-id demo --dapr-http-port 3500 --resources-path query-api-examples/components/redis

现在使用员工数据集填充状态存储,以便您稍后查询它。

curl -X POST -H "Content-Type: application/json" -d @query-api-examples/dataset.json \
  http://localhost:3500/v1.0/state/querystatestore?metadata.contentType=application/json

为了确保数据已正确存储,您可以检索特定对象

curl http://localhost:3500/v1.0/state/querystatestore/1?metadata.contentType=application/json

结果将是:

{
  "city": "Seattle",
  "state": "WA",
  "person": {
    "org": "Dev Ops",
    "id": 1036
  }
}

现在,让我们查找加利福尼亚州的所有员工,并按其员工 ID 降序排序。

这是查询

{
    "filter": {
        "EQ": { "state": "CA" }
    },
    "sort": [
        {
            "key": "person.id",
            "order": "DESC"
        }
    ]
}

使用以下命令执行查询:

curl -s -X POST -H "Content-Type: application/json" -d @query-api-examples/query1.json \
  'http://localhost:3500/v1.0-alpha1/state/querystatestore/query?metadata.contentType=application/json&metadata.queryIndexName=orgIndx'

结果将是:

{
  "results": [
    {
      "key": "3",
      "data": {
        "person": {
          "org": "Finance",
          "id": 1071
        },
        "city": "Sacramento",
        "state": "CA"
      },
      "etag": "1"
    },
    {
      "key": "7",
      "data": {
        "person": {
          "org": "Dev Ops",
          "id": 1015
        },
        "city": "San Francisco",
        "state": "CA"
      },
      "etag": "1"
    },
    {
      "key": "5",
      "data": {
        "person": {
          "org": "Hardware",
          "id": 1007
        },
        "city": "Los Angeles",
        "state": "CA"
      },
      "etag": "1"
    },
    {
      "key": "9",
      "data": {
        "person": {
          "org": "Finance",
          "id": 1002
        },
        "city": "San Diego",
        "state": "CA"
      },
      "etag": "1"
    }
  ]
}

查询语法和文档可在此处找到

Redis Sentinel 配置

使用 Redis Sentinel 实现高可用性时,将 redisType 设置为 "node",使用 failover: "true" 启用故障转移模式,并提供 sentinel 主节点名称。可以在 redisHost 字段中指定多个以逗号分隔的 sentinel 地址以实现冗余。

```yaml
apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
  name: redis-pubsub
spec:
  type: pubsub.redis
  version: v1
  metadata:
  - name: redisHost
    value: "sentinel1:26379,sentinel2:26379,sentinel3:26379"
  - name: redisType
    value: "node"
  - name: failover
    value: "true"
  - name: sentinelMasterName
    value: "mymaster"
```

相关链接

29 - RethinkDB

RethinkDB 状态存储组件的详细信息

组件格式

要设置 RethinkDB 状态存储,请创建一个类型为 state.rethinkdb 的组件。请参阅如何操作指南来创建和应用状态存储配置。

apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
  name: <NAME>
spec:
  type: state.rethinkdb
  version: v1
  metadata:
  - name: address
    value: <REPLACE-RETHINKDB-ADDRESS> # 必填,例如 127.0.0.1:28015 或 rethinkdb.default.svc.cluster.local:28015。
  - name: database
    value: <REPLACE-RETHINKDB-DB-NAME> # 必填,例如 dapr(仅限字母数字)
  - name: table
    value: # 可选
  - name: username
    value: <USERNAME> # 可选
  - name: password
    value: <PASSWORD> # 可选
  - name: archive
    value: bool # 可选(存储是否应保留所有状态更改的归档表)

如果将可选的 archive 元数据设置为 true,则在每次状态更改时,RethinkDB 状态存储还会在 daprstate_archive 表中记录带有时间戳的状态更改。这允许对由 Dapr 管理的状态进行时间序列分析。

规范元数据字段

字段必填详情示例
addressYRethinkDB 服务器的地址"127.0.0.1:28015", "rethinkdb.default.svc.cluster.local:28015"
databaseY要使用的数据库。仅限字母数字"dapr"
tableN要使用的表名称"table"
usernameN用于连接的用户名"user"
passwordN用于连接的密码"password"
archiveN是否归档表"true", "false"

设置 RethinkDB

您可以使用 Docker 在本地运行 RethinkDB

docker run --name rethinkdb -v "$PWD:/rethinkdb-data" -d rethinkdb:latest

要连接到管理 UI:

open "http://$(docker inspect --format '{{ .NetworkSettings.IPAddress }}' rethinkdb):8080"

相关链接

30 - SQLite

SQLite 状态存储组件的详细信息

该组件允许将 SQLite 3 用作 Dapr 的状态存储。

该组件目前使用 SQLite 版本 3.41.2 编译。

创建 Dapr 组件

创建一个名为 sqlite.yaml 的文件,粘贴以下内容,并将 <CONNECTION STRING> 值替换为你的连接字符串,即磁盘上文件的路径。

如果还想将 SQLite 配置为存储 actor,可以添加 actorStateStore 选项,如下所示。

apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
  name: <NAME>
spec:
  type: state.sqlite
  version: v1
  metadata:
  # 连接字符串
  - name: connectionString
    value: "data.db"
  # 数据库操作的超时时间,单位为秒(可选)
  #- name: timeoutInSeconds
  #  value: 20
  # 用于存储状态的表名(可选)
  #- name: tableName
  #  value: "state"
  # 清理间隔,单位为秒,用于删除过期行(可选)
  #- name: cleanupInterval
  #  value: "1h"
  # 为数据库操作设置 busy timeout
  #- name: busyTimeout
  #  value: "2s"
  # 如果你想将 SQLite 用作 actor 的状态存储,取消此行的注释(可选)
  #- name: actorStateStore
  #  value: "true"

规范元数据字段

字段必填详情示例
connectionStringYSQLite 数据库的连接字符串。更多详情见下文。"path/to/data.db", "file::memory:?cache=shared"
timeoutN数据库操作的超时时间,格式为 Go duration。整数将被解释为秒数。默认为 20s"30s", 30
tableNameN用于存储数据的表名。默认为 state"state"
metadataTableNameNDapr 用于存储组件元数据的表名。默认为 metadata"metadata"
cleanupIntervalN清理具有过期 TTL 的行的间隔,格式为 Go duration。将此值设置为 <=0 会禁用定期清理。默认:0(即禁用)"2h", "30m", -1
busyTimeoutN当 SQLite 数据库正忙于处理另一个请求时,在返回"数据库忙碌"错误之前等待的间隔,格式为 Go duration。默认:2s"100ms", "5s"
disableWALN如果设置为 true,则禁用 SQLite 数据库日志的预写式日志记录。如果数据库存储在网络文件系统上(例如,挂载为 SMB 或 NFS 共享的文件夹),应将其设置为 false。对于只读或内存数据库,此选项将被忽略。"true", "false"
actorStateStoreN将此状态存储用于 actor。默认为 "false""true", "false"

connectionString 参数配置如何打开 SQLite 数据库。

  • 通常,这是磁盘上文件的路径,相对于当前工作目录或绝对路径。例如:"data.db"(相对于工作目录)或 "/mnt/data/mydata.db"
  • 路径由 SQLite 库解释,因此如果路径以 file: 开头,可以使用"URI 选项"向 SQLite 驱动程序传递其他选项。例如:"file:path/to/data.db?mode=ro" 以只读模式打开路径为 path/to/data.db 的数据库。有关所有支持的 URI 选项,请参阅 SQLite 文档
  • 特殊情况 ":memory:" 会启动由内存 SQLite 数据库支持的组件。此数据库不会持久化到磁盘,不会在多个 Dapr 实例之间共享,并且当 Dapr 边车停止时所有数据都会丢失。使用内存数据库时,Dapr 会自动设置 cache=shared URI 选项。

高级

TTL 和清理

此状态存储支持使用 Dapr 存储的记录的生存时间 (TTL)。使用 Dapr 存储数据时,可以设置 ttlInSeconds 元数据属性来指示数据何时应被视为"已过期"。

由于 SQLite 没有内置的 TTL 支持,这是在 Dapr 中通过在状态表中添加一个列来实现的,该列指示数据何时应被视为"已过期"。“已过期"的记录不会返回给调用者,即使它们仍然物理存储在数据库中。后台"垃圾收集器"会定期扫描状态表以查找过期行并删除它们。

cleanupInterval 元数据属性设置过期记录的删除间隔,默认情况下禁用。

  • 较长的间隔需要较少的过期行扫描频率,但可能导致数据库存储过期记录的时间更长,可能需要更多的存储空间。如果你计划在状态表中存储许多记录,且 TTL 较短,可以考虑将 cleanupInterval 设置为较小的值,例如 5m
  • 如果你不打算使用 Dapr 和 SQLite 状态存储的 TTL,应考虑将 cleanupInterval 设置为 <= 0 的值(例如 0-1)以禁用定期清理并减少数据库负载。这是默认行为。

状态表中存储记录过期日期的 expiration_time默认没有索引,因此每次定期清理都必须执行全表扫描。如果你的表有大量记录,并且只有其中一些使用 TTL,你可能会发现在该列上创建索引很有用。假设你的状态表名称是 state(默认值),你可以使用以下查询:

CREATE INDEX idx_expiration_time
  ON state (expiration_time);

Dapr 不会自动 vacuum SQLite 数据库。

共享 SQLite 数据库和使用网络文件系统

虽然你可以有多个 Dapr 实例访问同一个 SQLite 数据库(例如,因为你的应用程序水平扩展或你有多个应用程序访问同一个状态存储),但你应该记住一些注意事项。

当所有客户端访问同一本地安装磁盘上的数据库文件时,SQLite 工作效果最佳。使用从 SAN(存储区域网络)挂载的虚拟磁盘,这是虚拟化或云环境中的常见做法,是可以的。

但是,将 SQLite 数据库存储在网络文件系统(例如通过 NFS 或 SMB,但这些示例并非详尽列表)中应该小心。SQLite 官方文档有一个专门的页面,介绍在网络运行 SQLite 的建议和注意事项

鉴于通过网络文件系统(例如通过 NFS 或 SMB)运行 SQLite 会带来数据损坏的风险,我们不建议在生产环境中对 Dapr 执行此操作。但是,如果你确实想这样做,你应该将 SQLite Dapr 组件配置为将 disableWAL 设置为 true

相关链接

31 - Zookeeper

Zookeeper 状态存储组件的详细信息

组件格式

要设置 Zookeeper 状态存储,请创建一个类型为 state.zookeeper 的组件。请参阅此指南了解如何创建和应用状态存储配置。

apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
  name: <NAME>
spec:
  type: state.zookeeper
  version: v1
  metadata:
  - name: servers
    value: <REPLACE-WITH-COMMA-DELIMITED-SERVERS> # 必填。示例:"zookeeper.default.svc.cluster.local:2181"
  - name: sessionTimeout
    value: <REPLACE-WITH-SESSION-TIMEOUT> # 必填。示例:"5s"
  - name: maxBufferSize
    value: <REPLACE-WITH-MAX-BUFFER-SIZE> # 可选。默认值:"1048576"
  - name: maxConnBufferSize
    value: <REPLACE-WITH-MAX-CONN-BUFFER-SIZE> # 可选。默认值:"1048576"
  - name: keyPrefixPath
    value: <REPLACE-WITH-KEY-PREFIX-PATH> # 可选。

规范元数据字段

字段必填详情示例
serversY服务器列表,以逗号分隔"zookeeper.default.svc.cluster.local:2181"
sessionTimeoutY会话超时值"5s"
maxBufferSizeN缓冲区的最大大小。默认为 "1048576""1048576"
maxConnBufferSizeN连接缓冲区的最大大小。默认为 "1048576""1048576"
keyPrefixPathNZookeeper 中的键前缀路径。无默认值"dapr"

设置 Zookeeper

您可以使用 Docker 在本地运行 Zookeeper:

docker run --name some-zookeeper --restart always -d zookeeper

然后您可以使用 localhost:2181 与服务器交互。

在 Kubernetes 上安装 Zookeeper 最简单的方法是使用 Helm chart

helm repo add incubator http://storage.googleapis.com/kubernetes-charts-incubator
helm install zookeeper incubator/zookeeper

这会将 Zookeeper 安装到 default 命名空间中。 要与 Zookeeper 交互,请使用以下命令查找服务:kubectl get svc zookeeper

例如,如果使用上述示例安装,Zookeeper 主机地址将是:

zookeeper.default.svc.cluster.local:2181

相关链接