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:

Header Description Example
Status Component certification status Alpha
Beta
Stable
Component version The version of the component v1
Since runtime version The version of the Dapr runtime when the component status was set or updated 1.11

Generic

Component CRUD Transactional ETag TTL Actors Query Status Component version Since runtime version
Aerospike Transactions: Not supported TTL: Not supported Actors: Not supported Query: Not supported Alpha v1 1.0
Apache Cassandra Transactions: Not supported ETag: Not supported Actors: Not supported Query: Not supported Stable v1 1.9
CockroachDB Stable v1 1.10
Couchbase Transactions: Not supported TTL: Not supported Actors: Not supported Query: Not supported Alpha v1 1.0
etcd Query: Not supported Beta v2 1.12
Hashicorp Consul Transactions: Not supported ETag: Not supported TTL: Not supported Actors: Not supported Query: Not supported Alpha v1 1.0
Hazelcast Transactions: Not supported ETag: Not supported TTL: Not supported Actors: Not supported Query: Not supported Alpha v1 1.0
In-memory Query: Not supported Stable v1 1.9
JetStream KV Transactions: Not supported ETag: Not supported TTL: Not supported Actors: Not supported Query: Not supported Alpha v1 1.7
Memcached Transactions: Not supported ETag: Not supported Actors: Not supported Query: Not supported Stable v1 1.9
MongoDB Stable v1 1.0
MySQL & MariaDB Query: Not supported Stable v1 1.10
Oracle Database Query: Not supported Beta v1 1.7
PostgreSQL v1 Stable v1 1.0
PostgreSQL v2 Query: Not supported Stable v2 1.13
Redis Stable v1 1.0
RethinkDB Transactions: Not supported ETag: Not supported TTL: Not supported Actors: Not supported Query: Not supported Beta v1 1.9
SQLite Query: Not supported Stable v1 1.11
Zookeeper Transactions: Not supported TTL: Not supported Actors: Not supported Query: Not supported Alpha v1 1.0

Amazon Web Services (AWS)

Component CRUD Transactional ETag TTL Actors Query Status Component version Since runtime version
AWS DynamoDB Query: Not supported Stable v1 1.10

Cloudflare

Component CRUD Transactional ETag TTL Actors Query Status Component version Since runtime version
Cloudflare Workers KV Transactions: Not supported ETag: Not supported Actors: Not supported Query: Not supported Beta v1 1.10

Google Cloud Platform (GCP)

Component CRUD Transactional ETag TTL Actors Query Status Component version Since runtime version
GCP Firestore Transactions: Not supported ETag: Not supported TTL: Not supported Actors: Not supported Query: Not supported Stable v1 1.11

Microsoft Azure

Component CRUD Transactional ETag TTL Actors Query Status Component version Since runtime version
Azure Blob Storage Transactions: Not supported TTL: Not supported Actors: Not supported Query: Not supported Stable v2 1.13
Azure Cosmos DB Stable v1 1.0
Azure Table Storage Transactions: Not supported TTL: Not supported Actors: Not supported Query: Not supported Stable v1 1.9
Microsoft SQL Server Query: Not supported Stable v1 1.5

Oracle Cloud

Component CRUD Transactional ETag TTL Actors Query Status Component version Since runtime version
Autonomous Database (ATP and ADW) Query: Not supported Alpha v1 1.7
Coherence Transactions: Not supported ETag: Not supported Actors: Not supported Query: Not supported Alpha v1 1.16
Object Storage Transactions: Not supported Actors: Not supported Query: Not supported Alpha v1 1.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> # 可选

配置元数据字段

字段 必需 详情 示例
hosts Y 数据库服务器的主机名/端口 "localhost:3000", "aerospike:3000,aerospike2:3000"
namespace Y Aerospike 命名空间 "namespace"
set N 数据库中的 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 - 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: partitionKey
    value: "ContractID" # 可选
  # 如果希望将 AWS DynamoDB 用作 actor 的状态存储,请取消注释此行(可选)
  #- name: actorStateStore
  #  value: "true"

主键

要将 DynamoDB 用作 Dapr 状态存储,表必须有一个名为 key 的主键。请参考分区键部分以了解如何更改此设置。

规格元数据字段

字段 必需 详情 示例
table Y 要使用的 DynamoDB 表的名称 "Contracts"
accessKey N 具有适当权限的 AWS 账户的 ID,可使用 secretKeyRef 来引用 secret "AKIAIOSFODNN7EXAMPLE"
secretKey N AWS 用户的 secret,可使用 secretKeyRef 来引用 secret "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"
region N 实例的 AWS 区域。请参阅此页面以获取有效区域:https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Concepts.RegionsAndAvailabilityZones.html。确保 DynamoDB 在该区域可用。 "us-east-1"
endpoint N 组件使用的 AWS 端点。仅用于本地开发。在生产 AWS 上运行时不需要 endpoint "http://localhost:4566"
sessionToken N 使用的 AWS 会话令牌。仅在使用临时安全凭证时需要会话令牌。 "TOKEN"
ttlAttributeName N 应用于 TTL 的表属性名称。 "expiresAt"
partitionKey N 表的主键或分区键属性名称。此字段用于替换默认的主键属性名称 "key"。请参阅分区键部分。 "ContractID"
actorStateStore N 将此状态存储视为 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"
        }
    }
}

相关链接

3 - Azure Blob 存储

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

组件格式

要设置 Azure Blob 存储状态存储,请创建一个类型为 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 提供了两个版本的 Azure Blob 存储状态存储组件:v1v2。建议所有新应用程序使用 v2v1 被视为遗留版本,仅为与现有应用程序的兼容性而保留。

v1 中,存在一个长期的实现问题,即组件错误地忽略了键前缀,导致 keyPrefix 始终被设置为 none
更新后的 v2 组件修复了此问题,使状态存储能够正确地使用 keyPrefix 属性。

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

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

规格元数据字段

字段 必需 详细信息 示例
accountName Y 存储帐户名称 "mystorageaccount"
accountKey Y (除非使用 Microsoft Entra ID) 主存储或辅助存储密钥 "key"
containerName Y 用于 Dapr 状态的容器名称。如果不存在,Blob 存储状态提供者会自动为您创建 "container"
azureEnvironment N 如果使用不同的 Azure 云,则为 Azure 环境的可选名称 "AZUREPUBLICCLOUD" (默认值), "AZURECHINACLOUD", "AZUREUSGOVERNMENTCLOUD"
endpoint N 可选的自定义端点 URL。这在使用 Azurite 模拟器 或使用 Azure 存储的自定义域时很有用(尽管这不是官方支持的)。端点必须是完整的基本 URL,包括协议 (http://https://)、IP 或 FQDN 以及可选端口。 "http://127.0.0.1:10000"
ContentType N Blob 的内容类型 "text/plain"
ContentMD5 N Blob 的 MD5 哈希 "vZGKbMRDAnMs4BIwlXaRvQ=="
ContentEncoding N Blob 的内容编码 "UTF-8"
ContentLanguage N Blob 的内容语言 "en-us"
ContentDisposition N Blob 的内容处置。传达有关如何处理响应负载的附加信息 "attachment"
CacheControl N Blob 的缓存控制 "no-cache"

设置 Azure Blob 存储

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

如果您希望为 Dapr 创建一个容器,可以事先进行。然而,如果不存在,Blob 存储状态提供者会自动为您创建。

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

  • accountName: 存储帐户名称。例如:mystorageaccount
  • accountKey: 主存储或辅助存储帐户密钥。
  • containerName: 用于 Dapr 状态的容器名称。如果不存在,Blob 存储状态提供者会自动为您创建。

使用 Microsoft Entra ID 进行身份验证

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

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

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

  1. 要开始使用 Microsoft Entra ID 进行 Blob 存储状态存储组件的身份验证,请确保您已创建 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,为我们的服务主体分配一个角色,以便它可以访问存储帐户内的数据。
    在这种情况下,您正在分配“存储 Blob 数据贡献者”角色,该角色具有广泛的访问权限;根据您的应用程序,也可以使用其他更具限制性的角色。
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 存储状态存储应用于 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"
        }
      ]'

这将在容器中创建一个以 key 为文件名、value 为文件内容的 Blob 文件。

并发

Azure Blob 存储状态并发是通过使用 ETag 实现的,具体请参见 Azure Blob 存储文档

相关链接

4 - 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"

规格元数据字段

字段 必需 详情 示例
url Y Cosmos DB 的 URL "https://******.documents.azure.com:443/".
masterKey Y* 用于认证 Cosmos DB 帐户的密钥。仅在不使用 Microsoft Entra ID 认证时需要。 "key"
database Y 数据库名称 "db"
collection Y 集合(容器)名称 "collection"
actorStateStore N 将此状态存储用于 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 建立新连接:

  • 确保应用程序的 sidecar 仅在需要时加载 Azure Cosmos DB 组件,以避免不必要的数据库连接。这可以通过将组件限定到特定应用程序来实现。
  • 选择按顺序部署或启动应用程序的部署策略,以最大限度地减少对 Azure Cosmos DB 帐户的新连接突发。
  • 避免为不相关的数据库或系统(即使在 Dapr 之外)重用同一个 Azure Cosmos DB 帐户。不同的 Azure Cosmos DB 帐户具有不同的速率限制。
  • 增加 initTimeout 值,以允许组件在 sidecar 初始化期间重试连接到 Azure Cosmos DB,最长可达 5 分钟。默认值为 5s,应增加。当使用 Kubernetes 时,增加此值可能还需要更新您的就绪性和存活性探针
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 来满足负载。

相关链接

5 - Azure 表存储

详细介绍 Azure 表存储状态组件,该组件可用于连接到 Cosmos DB 表 API 和 Azure 表

组件格式

要配置 Azure 表存储状态组件,请创建一个类型为 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

元数据字段说明

字段 必需 详情 示例
accountName 存储帐户名称 "mystorageaccount"
accountKey 主存储或辅助存储密钥 "key"
tableName 用于 Dapr 状态的表名。如果不存在,将自动创建 "table"
cosmosDbMode 启用后,将连接到 Cosmos DB 表 API 而非 Azure 表。默认为 false "false"
serviceURL 完整的存储服务端点 URL,适用于非公共云的 Azure 环境 "https://mystorageaccount.table.core.windows.net/"
skipCreateTable 跳过检查并在必要时创建指定的存储表,适用于最低权限的活动目录身份验证。默认为 false "true"

Microsoft Entra ID 认证

Azure Cosmos DB 状态组件支持所有 Microsoft Entra ID 认证机制。有关更多信息以及如何选择适合的组件元数据字段,请参阅Azure 认证文档

您可以在下面的部分了解更多关于使用 Microsoft Entra ID 认证设置 Cosmos DB 的信息。

选项 1:设置 Azure 表存储

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

如果您希望为 Dapr 创建一个表,可以提前进行。然而,表存储状态组件会自动为您创建一个表(如果它不存在),除非启用了 skipCreateTable 选项。

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

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

选项 2:设置 Azure Cosmos DB 表 API

按照说明从 Azure 文档中了解如何使用表 API 创建 Cosmos DB 帐户。

如果您希望为 Dapr 创建一个表,可以提前进行。然而,表存储状态组件会自动为您创建一个表(如果它不存在),除非启用了 skipCreateTable 选项。

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

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

分区

Azure 表存储状态组件使用请求中提供的 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"
        }
      ]'

将在表中创建以下记录:

PartitionKey RowKey Value
myservice nihilus darth

并发

Azure 表存储状态的并发通过使用 ETag 实现,具体请参阅官方文档

相关链接

6 - Cassandra

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

组件格式

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

apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
  name: <NAME>
spec:
  type: state.cassandra
  version: v1
  metadata:
  - name: hosts
    value: <用逗号分隔的主机列表> # 必需。示例:cassandra.cassandra.svc.cluster.local
  - name: username
    value: <用户名> # 可选。默认值:""
  - name: password
    value: <密码> # 可选。默认值:""
  - name: consistency
    value: <一致性级别> # 可选。默认值:"All"
  - name: table
    value: <表名> # 可选。默认值:"items"
  - name: keyspace
    value: <键空间> # 可选。默认值:"dapr"
  - name: protoVersion
    value: <协议版本> # 可选。默认值:"4"
  - name: replicationFactor
    value: <复制因子> # 可选。默认值:"1"

规格元数据字段

字段 必需 说明 示例
hosts 用逗号分隔的主机列表 "cassandra.cassandra.svc.cluster.local"
port 通信端口。默认值为 "9042" "9042"
username 数据库用户的用户名。无默认值 "user"
password 用户的密码 "password"
consistency 一致性级别 "All""Quorum"
table 表名。默认值为 "items" "items""tab"
keyspace 要使用的 Cassandra 键空间。默认值为 "dapr" "dapr"
protoVersion 客户端的协议版本。默认值为 "4" "3""4"
replicationFactor 复制因子。默认值为 "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

相关链接

7 - 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(如果 Worker 已在 Dapr 外部预创建,则必需)
    - name: workerUrl
      value: ""

规格元数据字段

字段 必需 详情 示例
kvNamespaceID Y 预创建的 Workers KV 命名空间的 ID "123456789abcdef8b5588f3d134f74ac"
workerName Y 要连接的 Worker 的名称 "mydaprkv"
key Y Ed25519 私钥,PEM 编码 见上面的示例
cfAccountID Y/N Cloudflare 账户 ID。需要 Dapr 管理 Worker。 "456789abcdef8b5588f3d134f74ac"def
cfAPIToken Y/N Cloudflare 的 API 令牌。需要 Dapr 管理 Worker。 "secret-key"
workerUrl Y/N Worker 的 URL。如果 Worker 已在 Dapr 外部预配置,则必需。 "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 仪表板 后在浏览器的 URL 栏中找到此 ID,ID 是 dash.cloudflare.com 之后的十六进制字符串。例如,如果 URL 是 https://dash.cloudflare.com/456789abcdef8b5588f3d134f74acdef,则 cfAccountID 的值为 456789abcdef8b5588f3d134f74acdef
  • cfAPIToken: 具有创建和编辑 Workers 和 Workers KV 命名空间权限的 API 令牌。您可以在 Cloudflare 仪表板的 “我的个人资料” 部分的 “API 令牌” 页面中创建它:
    1. 点击 “创建令牌”
    2. 选择 “编辑 Cloudflare Workers” 模板。
    3. 按照屏幕上的说明生成新的 API 令牌。

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

如果您不希望授予 Dapr 为您部署 Worker 脚本的权限,您可以手动预配置一个 Worker 供 Dapr 使用。请注意,如果您有多个通过 Worker 与 Cloudflare 服务交互的 Dapr 组件,您需要为每个组件创建一个单独的 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.15"
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 命令将向您显示完整的 URL,例如 https://mydaprkv.mydomain.workers.dev

生成 Ed25519 密钥对

所有 Cloudflare Workers 都在公共互联网监听,因此 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,或者从 Homebrew 安装 OpenSSL 3.0,使用 brew install openssl@3,然后在下面的命令中将 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 分钟。

相关链接

8 - 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:
  # 连接字符串
  - name: connectionString
    value: "<CONNECTION STRING>"
  # 数据库操作的超时时间,以秒为单位(可选)
  #- name: timeoutInSeconds
  #  value: 20
  # 存储状态的表名(可选)
  #- name: tableName
  #  value: "state"
  # Dapr 使用的元数据存储表名(可选)
  #- name: metadataTableName
  #  value: "dapr_metadata"
  # 清理过期行的间隔时间,以秒为单位(可选)
  #- name: cleanupIntervalInSeconds
  #  value: 3600
  # 连接关闭前的最大空闲时间(可选)
  #- name: connectionMaxIdleTime
  #  value: 0
  # 如果希望使用 CockroachDB 作为 actor 的状态存储,请取消注释此行(可选)
  #- name: actorStateStore
  #  value: "true"

规格元数据字段

字段 必需 详情 示例
connectionString Y CockroachDB 的连接字符串 "host=localhost user=root port=26257 connect_timeout=10 database=dapr_test"
timeoutInSeconds N 所有数据库操作的超时时间,以秒为单位。默认值为 20 30
tableName N 存储数据的表名。默认值为 state。可以选择性地在前面加上模式名称,如 public.state "state", "public.state"
metadataTableName N Dapr 用于存储一些元数据属性的表名。默认值为 dapr_metadata。可以选择性地在前面加上模式名称,如 public.dapr_metadata "dapr_metadata", "public.dapr_metadata"
cleanupIntervalInSeconds N 清理具有过期 TTL 的行的间隔时间,以秒为单位。默认值:3600(即 1 小时)。将此值设置为 <=0 可禁用定期清理。 1800, -1
connectionMaxIdleTime N 在连接池中未使用的连接自动关闭前的最大空闲时间。默认情况下,没有值,由数据库驱动程序选择。 "5m"
actorStateStore N 将此状态存储视为 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 存储记录的生存时间 (TTL)。使用 Dapr 存储数据时,您可以设置 ttlInSeconds 元数据属性,以指示数据在多少秒后应被视为“过期”。

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

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

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

相关链接

9 - 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> # 必填。

配置元数据字段

字段 必填 详情 示例
couchbaseURL Y Couchbase 服务器的 URL "http://localhost:8091"
username Y 数据库的用户名 "user"
password Y 访问的密码 "password"
bucketName Y 要写入的桶名称 "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

相关链接

10 - Etcd

Etcd 状态存储组件的详细介绍

组件格式

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

apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
  name: <NAME>
spec:
  type: state.etcd
  # 支持 v1 和 v2。建议默认使用 v2。请注意,v1 和 v2 之间没有直接的迁移路径,详情请参见下文的 `版本控制`。
  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 提供了两个版本的 Etcd 状态存储组件:v1v2。建议使用 v2,因为 v1 已被弃用。

虽然 v1v2 使用相同的元数据字段,但在使用 Dapr v1.12 的 actor TTLs 时,v1 可能会导致应用程序中的数据不一致。 v1v2 之间不兼容,且在现有的 Etcd 集群和 keyPrefixPath 上没有从 v1v2 的数据迁移路径。 如果您当前使用的是 v1,建议继续使用,直到您创建一个新的 Etcd 集群或使用不同的 keyPrefixPath

规格元数据字段

字段 必需 详细信息 示例
endpoints Y Etcd 集群的连接字符串 "192.168.0.1:2379,192.168.0.2:2379,192.168.0.3:2379"
keyPrefixPath N Etcd 中的键前缀路径。默认没有前缀。 "dapr"
tlsEnable N 是否启用 TLS 连接到 Etcd。 "false"
ca N 连接到 Etcd 的 CA 证书,PEM 编码。可以是 secretKeyRef 以使用secret 引用 "-----BEGIN CERTIFICATE-----\nMIIC9TCCA..."
cert N 连接到 Etcd 的 TLS 证书,PEM 编码。可以是 secretKeyRef 以使用secret 引用 "-----BEGIN CERTIFICATE-----\nMIIDUTCC..."
key N 连接到 Etcd 的 TLS 密钥,PEM 编码。可以是 secretKeyRef 以使用secret 引用 "-----BEGIN PRIVATE KEY-----\nMIIEpAIB..."
actorStateStore N 将此状态存储视为 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。

相关链接

11 - 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: 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"
  - name: type 
    value: <REPLACE-WITH-CREDENTIALS-TYPE> # 已弃用。

规格元数据字段

字段 必填 说明 示例
project_id Y 使用的 GCP 项目的 ID "project-id"
endpoint N 组件使用的 GCP 端点,仅用于本地开发(例如使用 GCP Datastore Emulator)。在生产环境中不需要设置 endpoint "localhost:8432"
private_key_id N 使用的私钥 ID "private-key-id"
private_key N 如果使用显式凭据,此字段应包含服务账户 JSON 中的 private_key 字段 -----BEGIN PRIVATE KEY-----MIIBVgIBADANBgkqhkiG9w0B
client_email N 客户端的电子邮件地址 "example@example.com"
client_id N 用于身份验证的客户端 ID "client-id"
auth_uri N 使用的身份验证 URI "https://accounts.google.com/o/oauth2/auth"
token_uri N 用于获取 Auth 令牌的 URI "https://oauth2.googleapis.com/token"
auth_provider_x509_cert_url N 身份验证提供者的证书 URL "https://www.googleapis.com/oauth2/v1/certs"
client_x509_cert_url N 客户端证书 URL "https://www.googleapis.com/robot/v1/metadata/x509/x"
entity_kind N Filestore 中的实体名称,默认为 "DaprState" "DaprState"
noindex N 是否禁用状态实体的索引。如果遇到 Firestore 索引大小限制,可以启用此设置。默认为 "false" "true"
type N 已弃用 凭据类型 "serviceaccount"

GCP 凭据

由于 GCP Firestore 组件使用 GCP Go 客户端库,默认情况下会使用 应用程序默认凭据 进行身份验证。详细信息请参阅使用客户端库对 GCP 云服务进行身份验证指南。

设置 GCP Firestore

您可以使用 GCP Datastore 模拟器在本地运行,具体步骤请参阅此处

然后,您可以通过 http://localhost:8432 与服务器交互。

按照此处的说明在 Google Cloud 上设置 Firestore。

相关链接

12 - 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> # 可选。默认: ""

规范元数据字段

字段 必需 详情 示例
datacenter Y 使用的数据中心 "dc1"
httpAddr Y Consul 服务器的地址 "consul.default.svc.cluster.local:8500"
aclToken N 每个请求的 ACL 令牌。默认是 "" "token"
scheme N Consul 服务器的 URI 方案。默认是 "http" "http"
keyPrefixPath N Consul 中的键前缀路径。默认是 "" "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

相关链接

13 - 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> # 必需。服务器地址的逗号分隔字符串。例如:"hazelcast:3000,hazelcast2:3000"
  - name: hazelcastMap
    value: <REPLACE-WITH-MAP> # 必需。Hazelcast map 的配置。

规格元数据字段

字段 必需 详情 示例
hazelcastServers 服务器地址的逗号分隔字符串 "hazelcast:3000,hazelcast2:3000"
hazelcastMap Hazelcast 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

相关链接

14 - 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>"

规格元数据字段说明

字段 必需 详情 示例
natsURL NATS 服务器地址 URL nats://localhost:4222
jwt 用于分布式认证的 NATS JWT eyJhbGciOiJ...6yJV_adQssw5c
seedKey 用于分布式认证的 NATS 种子密钥 SUACS34K232O...5Z3POU7BNIL4Y
bucket JetStream 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>

相关链接

15 - 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"

规格元数据字段

字段 必需 详情 示例
hosts Y 逗号分隔的端点 "memcached.default.svc.cluster.local:11211"
maxIdleConnections N 最大空闲连接数。默认为 "2" "3"
timeout N 调用的超时时间(毫秒)。默认为 "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

相关链接

16 - 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 上均受支持。

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

使用 Microsoft Entra ID 进行身份验证

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

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

其他元数据选项

字段 必需 详情 示例
tableName N 要使用的表名。字母数字加下划线。默认为 "state" "table_name"
metadataTableName N Dapr 用于存储一些元数据属性的表名。默认为 dapr_metadata "dapr_metadata"
keyType N 使用的键类型。支持的值:"string"(默认)、"uuid""integer" "string"
keyLength N 键的最大长度。如果 “keyType” 不是 string,则忽略。默认为 "200" "200"
schema N 要使用的模式。默认为 "dbo" "dapr","dbo"
indexedProperties N 索引属性列表,作为包含 JSON 文档的字符串。 '[{"column": "transactionid", "property": "id", "type": "int"}, {"column": "customerid", "property": "customer", "type": "nvarchar(100)"}]'
actorStateStore N 指示 Dapr 应为 actor 状态存储配置此组件(更多信息)。 "true"
cleanupIntervalInSeconds N 清理具有过期 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 分钟)。
  • 如果您不打算在 Dapr 和 SQL Server 状态存储中使用 TTL,您应该考虑将 cleanupIntervalInSeconds 设置为 <= 0 的值(例如 0-1)以禁用定期清理并减少数据库的负载。

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

CREATE CLUSTERED INDEX expiredate_idx ON state(ExpireDate ASC)

相关链接

17 - 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状态存储和事务支持

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

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

  - name: actorStateStore
    value: "true"

规格元数据字段

字段 必填 详情 示例
server Y1 使用DNS SRV记录时要连接的服务器 "server.example.com"
host Y1 要连接的主机 "mongo-mongodb.default.svc.cluster.local:27017"
username N 要连接的用户的用户名(适用于与host结合使用) "admin"
password N 用户的密码(适用于与host结合使用) "password"
databaseName N 要使用的数据库名称。默认为"daprStore" "daprStore"
collectionName N 要使用的集合名称。默认为"daprCollection" "daprCollection"
writeConcern N 要使用的写关注 "majority"
readConcern N 要使用的读关注 "majority", "local","available", "linearizable", "snapshot"
operationTimeout N 操作的超时时间。默认为"5s" "5s"
params N2 要使用的附加参数 "?authSource=daprStore&ssl=true"
actorStateStore N 将此状态存储考虑为actor。默认为"false" "true", "false"

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

[2] params字段接受一个查询字符串,该字符串指定连接特定选项为<name>=<value>对,以&分隔并以?为前缀。例如,要使用"daprStore"数据库作为身份验证数据库并在连接中启用SSL/TLS,请将参数指定为?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创建3节点副本集,请参阅官方文档

您可以使用Bitnami打包的Helm chart方便地在Kubernetes上安装MongoDB。请参阅Helm chart文档以了解如何部署MongoDB,无论是作为独立服务器还是与副本集(使用事务和actor所需)一起。 这会将MongoDB安装到default命名空间中。 要与MongoDB交互,请使用:kubectl get svc mongo-mongodb查找服务。 例如,如果使用上述Helm默认值安装,MongoDB主机地址将是: mongo-mongodb.default.svc.cluster.local:27017 按照屏幕上的说明获取MongoDB的root密码。 用户名通常默认为admin

TTL和清理

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

相关链接

18 - 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"

规格元数据字段

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

设置 MySQL

Dapr 可以使用任何 MySQL 实例 - 无论是容器化的 MySQL 实例、在本地开发机器上运行的,还是云服务提供的 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 将需要最低 TLS 版本为 1.2。

TTL 和清理

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

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

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

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

相关链接

19 - 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" 或 "false">  # 可选。默认值:"false"
 - name: configFileAuthentication
   value: <"true" 或 "false">  # 可选。默认值:"false"。当 instancePrincipalAuthentication 为 "true" 时不使用
 - name: configFilePath
   value: <配置文件的完整路径>  # 可选。无默认值。仅在 configFileAuthentication 为 "true" 时使用
 - name: configFileProfile
   value: <配置文件中的配置名称>  # 可选。默认值:"DEFAULT"。仅在 configFileAuthentication 为 "true" 时使用
 - name: tenancyOCID
   value: <租户的 OCID>  # 当 configFileAuthentication 为 "true" 或 instancePrincipalAuthentication 为 "true" 时不使用
 - name: userOCID
   value: <用户的 OCID>  # 当 configFileAuthentication 为 "true" 或 instancePrincipalAuthentication 为 "true" 时不使用
 - name: fingerPrint
   value: <公钥的指纹>  # 当 configFileAuthentication 为 "true" 或 instancePrincipalAuthentication 为 "true" 时不使用
 - name: privateKey  # 当 configFileAuthentication 为 "true" 或 instancePrincipalAuthentication 为 "true" 时不使用
   value: |
          -----BEGIN RSA PRIVATE KEY-----
          私钥内容
          -----END RSA PRIVATE KEY-----
 - name: region
   value: <OCI 区域>  # 当 configFileAuthentication 为 "true" 或 instancePrincipalAuthentication 为 "true" 时不使用
 - name: bucketName
   value: <桶的名称>
 - name: compartmentOCID
   value: <隔间的 OCID>

规格元数据字段

字段 必需 详细信息 示例
instancePrincipalAuthentication 布尔值,指示是否使用实例主体认证。默认值:“false” "true""false"
configFileAuthentication 布尔值,指示是否通过配置文件提供身份凭证。默认值:“false”。当 instancePrincipalAuthentication 为 true 时不使用。 "true""false"
configFilePath OCI 配置文件的完整路径。无默认值。当 instancePrincipalAuthentication 为 true 时不使用。请注意:不支持 ~/ 前缀。 "/home/apps/configuration-files/myOCIConfig.txt"
configFileProfile 配置文件中的配置名称。默认值:“DEFAULT”。当 instancePrincipalAuthentication 为 true 时不使用。 "DEFAULT""PRODUCTION"
tenancyOCID OCI 租户标识符。当 instancePrincipalAuthentication 为 true 时不使用。 "ocid1.tenancy.oc1..aaaaaaaag7c7sljhsdjhsdyuwe723"
userOCID OCI 用户的 OCID(需要访问 OCI 对象存储的权限)。当 instancePrincipalAuthentication 为 true 时不使用。 "ocid1.user.oc1..aaaaaaaaby4oyyyuqwy7623yuwe76"
fingerPrint 公钥的指纹。当 instancePrincipalAuthentication 为 true 时不使用。 "02:91:6c:49:e2:94:21:15:a7:6b:0e:a7:34:e1:3d:1b"
privateKey RSA 密钥对的私钥。当 instancePrincipalAuthentication 为 true 时不使用。 "MIIEoyuweHAFGFG2727as+7BTwQRAIW4V"
region OCI 区域。当 instancePrincipalAuthentication 为 true 时不使用。 "us-ashburn-1"
bucketName 用于读写的桶的名称(如果需要则创建) "application-state-store-bucket"
compartmentOCID 包含桶的隔间的 OCID "ocid1.compartment.oc1..aaaaaaaacsssekayyuq7asjh78"

设置 OCI 对象存储

OCI 对象存储状态存储需要与 Oracle 云基础设施交互。状态存储支持两种认证方法:基于身份(用户或服务账户)的认证和实例主体认证。请注意,资源主体认证(用于非实例的资源,如无服务器函数)目前不支持。

在 Oracle 云基础设施上运行的 Dapr 应用程序(无论是在计算实例中还是作为 Kubernetes 上的容器)可以使用实例主体认证。有关更多信息,请参阅 OCI 文档关于从实例调用 OCI 服务。简而言之:实例需要是动态组的成员,并且该动态组需要通过 IAM 策略获得与对象存储服务交互的权限。在这种情况下,设置 instancePrincipalAuthentication 为 "true"。您无需配置 tenancyOCID、userOCID、region、fingerPrint 和 privateKey 属性——如果您为它们定义了值,这些将被忽略。

基于身份的认证通过具有权限的 OCI 账户与 OCI 交互,以在指定的桶中创建、读取和删除对象,并允许在指定的隔间中创建桶(如果桶未事先创建)。OCI 文档描述了如何创建 OCI 账户。状态存储通过使用为 OCI 账户生成的 RSA 密钥对的公钥指纹和私钥进行交互。OCI 文档中提供了生成密钥对和获取所需信息的说明

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

如果您希望为 Dapr 使用创建桶,可以事先进行。然而,如果不存在,对象存储状态提供者将在指定的隔间中自动为您创建一个。

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

  • instancePrincipalAuthentication:指示是否应使用基于实例主体的认证的标志。
  • configFileAuthentication:指示是否通过配置文件提供 OCI 身份凭证的标志。当 instancePrincipalAuthentication 为 true 时不使用。
  • configFilePath:OCI 配置文件的完整路径。当 instancePrincipalAuthentication 为 true 或 configFileAuthentication 不为 true 时不使用。
  • configFileProfile:配置文件中的配置名称。默认值:“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 指定 - (根) nihilus darth category: 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 指定 myApplication nihilus darth category: dapr-state-store

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

生存时间和状态过期

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

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 指定 - nihilus darth category: 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。

相关链接

20 - Oracle 数据库

Oracle 数据库状态存储组件的详细信息

组件格式

创建一个组件属性的 yaml 文件,例如 oracle.yaml(名称可以随意),然后粘贴以下内容,并将 <CONNECTION STRING> 替换为您的连接字符串。连接字符串是标准的 Oracle 数据库连接字符串,格式为:"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 数据库作为 actor 的状态存储,请取消注释此行(可选)
  #- name: actorStateStore
  #  value: "true"

规格元数据字段

字段 必需 详细信息 示例
connectionString Y Oracle 数据库的连接字符串 "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"
oracleWalletLocation N Oracle Wallet 文件内容的位置(连接到 OCI 上的 Autonomous Database 时需要) "/home/app/state/Wallet_daprDB/"
tableName N 此状态存储实例记录数据的数据库表的名称,默认 "STATE" "MY_APP_STATE_STORE"
actorStateStore N 考虑此状态存储用于 actor。默认为 "false" "true", "false"

运行时会发生什么?

当状态存储组件初始化时,它会连接到 Oracle 数据库并检查是否存在指定 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 中创建以下记录:

KEY VALUE CREATION_TIME BINARY_YN ETAG
nihilus darth 2022-02-14T22:11:00 N 79dfb504-5b27-43f6-950f-d55d5ae0894f

Dapr 使用固定的键方案和复合键来跨应用程序分区状态。对于一般状态,键格式为:App-ID||state key。Oracle 数据库状态存储将此键完整映射到 KEY 列。

您可以通过对 tableName 表(例如 STATE 表)进行 SQL 查询轻松检查所有存储的状态。

生存时间和状态过期

Oracle 数据库状态存储组件支持 Dapr 的生存时间逻辑,确保状态在过期后无法检索。有关详细信息,请参阅此处关于设置状态生存时间的指南

Oracle 数据库本身不支持生存时间设置。此组件的实现使用名为 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"}}
        }
      ]'

创建以下对象:

KEY VALUE CREATION_TIME EXPIRATION_TIME BINARY_YN ETAG
temporary ephemeral 2022-03-31T22:11:00 2022-03-31T22:13:00 N 79dfb504-5b27-43f6-950f-d55d5ae0894f

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

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

 delete dapr_state 
 where  expiration_time < SYS_EXTRACT_UTC(SYSTIMESTAMP);

并发

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

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

一致性

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

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

查询

Oracle 数据库状态存储当前不支持查询 API。

创建 Oracle 数据库和用户模式

  1. 运行一个 Oracle 数据库实例。您可以使用以下命令在 Docker CE 中运行一个本地 Oracle 数据库实例 - 或者当然使用现有的 Oracle 数据库:

    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 数据库中创建一个新的用户模式,运行以下 SQL 命令:

    create user dapr identified by DaprPassword4239 default tablespace users quota unlimited on users;
    grant create session, create table to dapr;
    
  3. (可选)创建用于存储状态记录的表。 Oracle 数据库状态存储组件会检查连接到的数据库用户模式中是否已经存在用于存储状态的表,如果不存在,它会创建该表。然而,您也可以在运行时之前创建用于存储状态记录的表。这使您 - 或数据库管理员 - 可以更好地控制表的物理配置。这也意味着您不必授予用户模式 create table 权限。

    运行以下 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 云基础设施上创建一个免费的(或付费的)Autonomous Transaction Processing (ATP) 或 ADW (Autonomous Data Warehouse) 实例,如 OCI 文档中的始终免费自治数据库 所述。

    您需要为用户 ADMIN 提供密码。您使用此帐户(至少最初)进行数据库管理活动。您可以在基于 Web 的 SQL Developer 工具中工作,也可以在其桌面版本或众多数据库开发工具中工作。

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

    要在 Oracle 数据库中创建一个新的用户模式,运行以下 SQL 命令:

    create user dapr identified by DaprPassword4239 default tablespace users quota unlimited on users;
    grant create session, create table to dapr;
    
  3. (可选)创建用于存储状态记录的表。 Oracle 数据库状态存储组件会检查连接到的数据库用户模式中是否已经存在用于存储状态的表,如果不存在,它会创建该表。然而,您也可以在运行时之前创建用于存储状态记录的表。这使您 - 或数据库管理员 - 可以更好地控制表的物理配置。这也意味着您不必授予用户模式 create table 权限。

    运行以下 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
      )
    

相关链接

21 - 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>"
    # 数据库操作的超时时间,作为 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 或 workflow 的状态存储,请取消注释此项(可选)
    #- name: actorStateStore
    #  value: "true"

规格元数据字段

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

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

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

使用 Microsoft Entra ID 进行身份验证

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

字段 必需 详情 示例
useAzureAD Y 必须设置为 true 以使组件能够从 Microsoft Entra ID 检索访问令牌。 "true"
connectionString Y PostgreSQL 数据库的连接字符串。
这必须包含用户,该用户对应于 PostgreSQL 内创建的用户名称,该用户映射到 Microsoft Entra ID 身份。这通常是相应主体的名称(例如,Microsoft Entra ID 应用程序的名称)。此连接字符串不应包含任何密码。
"host=mydb.postgres.database.azure.com user=myapplication port=5432 database=my_db sslmode=require"
azureTenantId N Microsoft Entra ID 租户的 ID "cd4b2887-304c-…"
azureClientId N 客户端 ID(应用程序 ID) "c7dd251f-811f-…"
azureClientSecret N 客户端 secret(应用程序密码) "Ecy3X…"

使用 AWS IAM 进行身份验证

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

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

其他元数据选项

字段 必需 详情 示例
tablePrefix N 存储数据的表的前缀。可以选择性地将模式名称作为前缀,例如 public.prefix_ "prefix_", "public.prefix_"
metadataTableName N Dapr 用于存储一些元数据属性的表名。默认为 dapr_metadata。可以选择性地将模式名称作为前缀,例如 public.dapr_metadata "dapr_metadata", "public.dapr_metadata"
timeout N 数据库操作的超时时间,作为 Go duration。整数被解释为秒数。默认为 20s "30s", 30
cleanupInterval N 间隔时间,作为 Go duration 或秒数,用于清理具有过期 TTL 的行。默认值:1h(1 小时)。将此值设置为 <=0 可禁用定期清理。 "30m", 1800, -1
maxConns N 该组件池化的最大连接数。设置为 0 或更低以使用默认值,默认值为 4 或 CPU 数量中的较大者。 "4"
connectionMaxIdleTime N 在连接池中未使用的连接自动关闭之前的最大空闲时间。默认情况下,没有值,这由数据库驱动程序选择。 "5m"
queryExecMode N 控制执行查询的默认模式。默认情况下,Dapr 使用扩展协议并自动准备和缓存准备好的语句。然而,这可能与代理如 PGBouncer 不兼容。在这种情况下,可能更适合使用 execsimple_protocol "simple_protocol"
actorStateStore N 将此状态存储视为 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 组件中,ETags 现在是随机 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 支持,这在 Dapr 中通过在状态表中添加一列来实现,该列指示数据何时应被视为 “过期”。即使它们仍然物理存储在数据库中,“过期” 的记录也不会返回给调用者。后台 “垃圾收集器” 定期扫描状态表以查找过期的行并删除它们。

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

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

相关链接

22 - 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>"
    # 数据库操作的超时时间,作为 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 或 workflow 的状态存储,请取消注释此项(可选)
    #- name: actorStateStore
    #  value: "true"

规格元数据字段

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

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

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

使用 Microsoft Entra ID 进行身份验证

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

字段 必需 详情 示例
useAzureAD Y 必须设置为 true 以使组件能够从 Microsoft Entra ID 检索访问令牌。 "true"
connectionString Y PostgreSQL 数据库的连接字符串。
这必须包含用户,该用户对应于在 PostgreSQL 内创建的用户的名称,该用户映射到 Microsoft Entra ID 身份;这通常是相应主体的名称(例如,Microsoft Entra ID 应用程序的名称)。此连接字符串不应包含任何密码。
"host=mydb.postgres.database.azure.com user=myapplication port=5432 database=my_db sslmode=require"
azureTenantId N Microsoft Entra ID 租户的 ID "cd4b2887-304c-…"
azureClientId N 客户端 ID(应用程序 ID) "c7dd251f-811f-…"
azureClientSecret N 客户端 secret(应用程序密码) "Ecy3X…"

使用 AWS IAM 进行身份验证

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

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

其他元数据选项

字段 必需 详情 示例
tableName N 存储数据的表名。默认为 state。可以选择性地在前面加上模式名称,例如 public.state "state", "public.state"
metadataTableName N Dapr 用于存储一些元数据属性的表名。默认为 dapr_metadata。可以选择性地在前面加上模式名称,例如 public.dapr_metadata "dapr_metadata", "public.dapr_metadata"
timeout N 数据库操作的超时时间,作为 Go duration。整数被解释为秒数。默认为 20s "30s", 30
cleanupInterval N 间隔时间,作为 Go duration 或秒数,用于清理具有过期 TTL 的行。默认值:1h(1 小时)。将此值设置为 <=0 可禁用定期清理。 "30m", 1800, -1
maxConns N 该组件池化的最大连接数。设置为 0 或更低以使用默认值,该值为 4 或 CPU 数量中的较大者。 "4"
connectionMaxIdleTime N 在连接池中未使用的连接自动关闭之前的最大空闲时间。默认情况下,没有值,这由数据库驱动程序选择。 "5m"
queryExecMode N 控制查询执行的默认模式。默认情况下,Dapr 使用扩展协议并自动准备和缓存准备好的语句。然而,这可能与代理如 PGBouncer 不兼容。在这种情况下,可能更适合使用 execsimple_protocol "simple_protocol"
actorStateStore N 将此状态存储视为 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 存储的记录的 生存时间 (TTL)。在使用 Dapr 存储数据时,您可以设置 ttlInSeconds 元数据属性以指示数据在多少秒后应被视为 “过期”。

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

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

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

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

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

相关链接

23 - 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: 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"

规格元数据字段

字段 必需 详细信息 示例
redisHost Y Redis 主机的连接字符串 localhost:6379, redis-master.default.svc.cluster.local:6379
redisPassword N Redis 主机的密码。无默认值。可以使用 secretKeyRef 来使用 secret 引用 "", "KeFg23!"
redisUsername N Redis 主机的用户名。默认为空。确保您的 Redis 服务器版本为 6 或更高,并正确创建了 ACL 规则。 "", "default"
useEntraID N 实现对 Azure Cache for Redis 的 EntraID 支持。启用此功能之前:
  • 必须以 "server:port" 的形式指定 redisHost 名称
  • 必须启用 TLS
创建 Redis 实例 > Azure Cache for Redis下了解有关此设置的更多信息
"true", "false"
enableTLS N 如果 Redis 实例支持带有公共证书的 TLS,可以配置为启用或禁用。默认为 "false" "true", "false"
clientCert N 客户端证书的内容,用于需要客户端证书的 Redis 实例。必须与 clientKey 一起使用,并且 enableTLS 必须设置为 true。建议使用 secret 存储,如此处所述 "----BEGIN CERTIFICATE-----\nMIIC..."
clientKey N 客户端私钥的内容,与 clientCert 一起用于身份验证。建议使用 secret 存储,如此处所述 "----BEGIN PRIVATE KEY-----\nMIIE..."
maxRetries N 放弃之前的最大重试次数。默认为 3 5, 10
maxRetryBackoff N 每次重试之间的最大退避时间。默认为 2 秒;"-1" 禁用退避。 3000000000
failover N 启用故障转移配置的属性。需要设置 sentinelMasterName。redisHost 应为哨兵主机地址。请参阅 Redis Sentinel 文档。默认为 "false" "true", "false"
sentinelMasterName N 哨兵主名称。请参阅 Redis Sentinel 文档 "", "127.0.0.1:6379"
redeliverInterval N 检查待处理消息以重新传递的间隔。默认为 "60s""0" 禁用重新传递。 "30s"
processingTimeout N 消息必须待处理的时间量,然后才尝试重新传递。默认为 "15s""0" 禁用重新传递。 "30s"
redisType N Redis 的类型。有两个有效值,一个是 "node" 表示单节点模式,另一个是 "cluster" 表示 Redis 集群模式。默认为 "node" "cluster"
redisDB N 连接到 Redis 后选择的数据库。如果 "redisType""cluster",则忽略此选项。默认为 "0" "0"
redisMaxRetries N maxRetries 的别名。如果同时设置了两个值,则忽略 maxRetries "5"
redisMinRetryInterval N 每次重试之间 Redis 命令的最小退避时间。默认为 "8ms""-1" 禁用退避。 "8ms"
redisMaxRetryInterval N maxRetryBackoff 的别名。如果同时设置了两个值,则忽略 maxRetryBackoff "5s"
dialTimeout N 建立新连接的拨号超时时间。默认为 "5s" "5s"
readTimeout N 套接字读取的超时时间。如果达到,Redis 命令将因超时而失败,而不是阻塞。默认为 "3s""-1" 表示无超时。 "3s"
writeTimeout N 套接字写入的超时时间。如果达到,Redis 命令将因超时而失败,而不是阻塞。默认为 readTimeout。 "3s"
poolSize N 最大套接字连接数。默认是每个 CPU 10 个连接,由 runtime.NumCPU 报告。 "20"
poolTimeout N 如果所有连接都忙,客户端等待连接的时间量,然后返回错误。默认是 readTimeout + 1 秒。 "5s"
maxConnAge N 客户端退休(关闭)连接的连接年龄。默认是不关闭老化连接。 "30m"
minIdleConns N 为了避免创建新连接的性能下降,保持打开的最小空闲连接数。默认为 "0" "2"
idleCheckFrequency N 空闲连接清理器进行空闲检查的频率。默认是 "1m""-1" 禁用空闲连接清理器。 "-1"
idleTimeout N 客户端关闭空闲连接的时间量。应小于服务器的超时时间。默认是 "5m""-1" 禁用空闲超时检查。 "10m"
ttlInSeconds N 允许指定一个默认的生存时间(TTL),以秒为单位,将应用于每个状态存储请求,除非通过请求元数据显式定义 TTL。 600
queryIndexes N 用于查询 JSON 对象的索引架构 参见 查询 JSON 对象
actorStateStore N 将此状态存储视为 actor。默认为 "false" "true", "false"

设置 Redis

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

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

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

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

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

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

        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 并复制输出的密码。

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

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

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

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

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

    注意: 在生产级应用程序中,请按照秘密管理说明安全管理您的秘密。

  5. 启用 EntraID 支持:

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

注意:useEntraID 假设您的 UserPrincipal(通过 AzureCLICredential)或 SystemAssigned 托管身份具有 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

按照在 Kubernetes 中部署 Redis的说明进行操作,并添加一个额外的细节。

安装 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

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

接下来是启动一个 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"
    }
  ]
}

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

相关链接

24 - 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 管理的状态进行时间序列分析。

元数据字段说明

字段 必需 详情 示例
address Y RethinkDB 服务器的地址 "127.0.0.1:28015""rethinkdb.default.svc.cluster.local:28015"
database Y 要使用的数据库。仅限字母数字 "dapr"
table N 要使用的表名 "table"
username N 用于连接的用户名 "user"
password N 用于连接的密码 "password"
archive N 是否保留存档表 "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"

相关链接

25 - 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"
  # 设置数据库操作的忙等待时间
  #- name: busyTimeout
  #  value: "2s"
  # 如果希望使用 SQLite 作为 actor 的状态存储,请取消注释此行(可选)
  #- name: actorStateStore
  #  value: "true"

规格元数据字段

字段 必需 详情 示例
connectionString Y SQLite 数据库的连接字符串。详见下文。 "path/to/data.db", "file::memory:?cache=shared"
timeout N 数据库操作的超时时间,格式为 Go duration。整数被解释为秒数。默认值为 20s "30s", 30
tableName N 存储数据的表名。默认值为 state "state"
metadataTableName N Dapr 用于存储组件元数据的表名。默认值为 metadata "metadata"
cleanupInterval N 清理过期 TTL 行的间隔时间,格式为 Go duration。设置为 <=0 的值将禁用定期清理。默认值:0(即禁用) "2h", "30m", -1
busyTimeout N 在 SQLite 数据库当前忙于处理其他请求时等待的时间间隔,格式为 Go duration,然后返回“数据库忙”错误。默认值:2s "100ms", "5s"
disableWAL N 如果设置为 true,则禁用 SQLite 数据库的预写日志记录。若数据库存储在网络文件系统上(例如,作为 SMB 或 NFS 共享挂载的文件夹),应将此设置为 false。此选项在只读或内存数据库中被忽略。 "true", "false"
actorStateStore N 将此状态存储视为 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 下的数据库。请参阅 SQLite 文档以获取所有支持的 URI 选项
  • 特殊情况 ":memory:" 启动由内存 SQLite 数据库支持的组件。此数据库不会持久化到磁盘,不会在多个 Dapr 实例之间共享,并且当 Dapr sidecar 停止时,所有数据都会丢失。使用内存数据库时,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

相关链接

26 - 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> # 可选。

规格元数据字段

字段 必需 详情 示例
servers Y 逗号分隔的服务器列表 "zookeeper.default.svc.cluster.local:2181"
sessionTimeout Y 会话超时时间 "5s"
maxBufferSize N 缓冲区的最大大小,默认值为 "1048576" "1048576"
maxConnBufferSize N 连接缓冲区的最大大小,默认值为 "1048576" "1048576"
keyPrefixPath N Zookeeper 中的键前缀路径,无默认值 "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

相关链接

27 - 内存

关于内存状态组件的详细文档

内存状态存储组件在Dapr sidecar中维护状态,主要用于开发目的。状态不会在多个sidecar之间共享,并且在Dapr sidecar重启时会丢失。

组件格式

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

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

注意:虽然内存组件不需要特定的元数据,但spec.metadata字段仍然是必填的。

相关链接