.NET Aspire Azure Blob Storage 集成

包括:托管集成 以及 Client 集成

Azure Blob Storage 是用于存储大量非结构化数据的服务。 通过 .NET AspireAzure Blob Storage 集成,可以连接到现有 Azure Blob Storage 实例,或从 .NET 应用程序创建新实例。

托管集成

存储托管整合将 .NET.NET AspireAzure 存储 的各种存储资源建模为以下几种类型:

若要访问这些类型和 API 来表达它们,请在 📦 项目中添加 AspireAzure.Hosting..Storage. NuGet 包。

dotnet add package Aspire.Hosting.Azure.Storage

有关详细信息,请参阅 dotnet add package在 .NET 应用程序中管理包依赖性

添加 Azure 存储资源

在应用主机项目中,调用 AddAzureStorage 添加并返回 Azure 存储资源生成器。

var builder = DistributedApplication.CreateBuilder(args);

var storage = builder.AddAzureStorage("storage");

// An Azure Storage resource is required to add any of the following:
//
// - Azure Blob storage resource.
// - Azure Queue storage resource.
// - Azure Table storage resource.

// After adding all resources, run the app...

AzureStorageResource 添加到应用主机时,它会公开其他有用的 API 来添加 Azure Blob、队列和表存储资源。 换句话说,在添加任何其他存储资源之前,必须添加 AzureStorageResource

重要

调用 AddAzureStorage时,它会隐式调用 AddAzureProvisioning,这增加了在应用启动期间动态生成 Azure 资源的支持。 应用必须配置相应的订阅和位置。 有关详细信息,请参阅 本地预配:配置

生成的预配 Bicep

如果你不熟悉 Bicep,它是一种领域特定的语言,用于定义 Azure 资源。 使用 .NET.NET Aspire,无需手动编写 Bicep,而是预配 API 会为你生成 Bicep。 发布应用时,生成的 Bicep 会与清单文件一起输出。 添加 Azure 存储资源时,将生成如下所示的 Bicep:


切换 Azure 存储 Bicep。

@description('The location for the resource(s) to be deployed.')
param location string = resourceGroup().location

param principalId string

param principalType string

resource storage 'Microsoft.Storage/storageAccounts@2024-01-01' = {
  name: take('storage${uniqueString(resourceGroup().id)}', 24)
  kind: 'StorageV2'
  location: location
  sku: {
    name: 'Standard_GRS'
  }
  properties: {
    accessTier: 'Hot'
    allowSharedKeyAccess: false
    minimumTlsVersion: 'TLS1_2'
    networkAcls: {
      defaultAction: 'Allow'
    }
  }
  tags: {
    'aspire-resource-name': 'storage'
  }
}

resource blobs 'Microsoft.Storage/storageAccounts/blobServices@2024-01-01' = {
  name: 'default'
  parent: storage
}

resource storage_StorageBlobDataContributor 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
  name: guid(storage.id, principalId, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ba92f5b4-2d11-453d-a403-e96b0029c9fe'))
  properties: {
    principalId: principalId
    roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ba92f5b4-2d11-453d-a403-e96b0029c9fe')
    principalType: principalType
  }
  scope: storage
}

resource storage_StorageTableDataContributor 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
  name: guid(storage.id, principalId, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0a9a7e1f-b9d0-4cc4-a60d-0319b160aaa3'))
  properties: {
    principalId: principalId
    roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0a9a7e1f-b9d0-4cc4-a60d-0319b160aaa3')
    principalType: principalType
  }
  scope: storage
}

resource storage_StorageQueueDataContributor 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
  name: guid(storage.id, principalId, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '974c5e8b-45b9-4653-ba55-5f855dd0fb88'))
  properties: {
    principalId: principalId
    roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '974c5e8b-45b9-4653-ba55-5f855dd0fb88')
    principalType: principalType
  }
  scope: storage
}

output blobEndpoint string = storage.properties.primaryEndpoints.blob

output queueEndpoint string = storage.properties.primaryEndpoints.queue

output tableEndpoint string = storage.properties.primaryEndpoints.table

前面的 Bicep 是一个模块,它预配了具有以下默认值的 Azure 存储帐户:

  • kind:存储帐户的类型。 默认值为 StorageV2
  • sku:存储帐户的 SKU。 默认值为 Standard_GRS
  • properties:存储帐户的属性:
    • accessTier:存储帐户的访问层。 默认值为 Hot
    • allowSharedKeyAccess:一个布尔值,该值指示存储帐户是否允许使用帐户访问密钥授权请求。 默认值为 false
    • minimumTlsVersion:存储帐户支持的最低 TLS 版本。 默认值为 TLS1_2
    • networkAcls:存储账户的网络 ACL。 默认值为 { defaultAction: 'Allow' }

除了存储帐户,它还预配 Blob 容器。

以下角色分配将添加到存储帐户,以授予应用程序访问权限。 要了解更多信息,请查看 内置 Azure 基于角色的访问控制(Azure RBAC)角色

角色/ID 描述
存储 Blob 数据贡献者
ba92f5b4-2d11-453d-a403-e96b0029c9fe
读取、写入和删除 Azure 存储容器和 Blob。
存储表格数据贡献者
0a9a7e1f-b9d0-4cc4-a60d-0319b160aaa3
读取、写入和删除 Azure 存储表和实体。
存储队列数据贡献者
974c5e8b-45b9-4653-ba55-5f855dd0fb88
读取、写入和删除 Azure 存储队列和队列消息。

生成的 Bicep 是一个起点,可以自定义以满足特定要求。

自定义预配基础结构

所有 .NET AspireAzure 资源都是 AzureProvisioningResource 类型的子类。 此类型允许通过使用 Azure API 所提供的 fluent API 来配置 ConfigureInfrastructure<T>(IResourceBuilder<T>, Action<AzureResourceInfrastructure>) 资源,从而自定义生成的 Bicep。 例如,可以配置 kindskuproperties等。 以下示例演示如何自定义 Azure 存储资源:

builder.AddAzureStorage("storage")
    .ConfigureInfrastructure(infra =>
    {
        var storageAccount = infra.GetProvisionableResources()
                                  .OfType<StorageAccount>()
                                  .Single();

        storageAccount.AccessTier = StorageAccountAccessTier.Cool;
        storageAccount.Sku = new StorageSku { Name = StorageSkuName.PremiumZrs };
        storageAccount.Tags.Add("ExampleKey", "Example value");
    });

前面的代码:

还有更多配置选项可用于自定义 Azure 存储资源。 有关详细信息,请参阅 Azure.Provisioning.Storage

连接到现有 Azure 存储帐户

您可能已有一个现有的 Azure 存储帐户需要连接。 与其表示新的 Azure 存储资源,不如向应用主机添加连接字符串。 若要将连接添加到现有 Azure 存储帐户,请调用 AddConnectionString 方法:

var builder = DistributedApplication.CreateBuilder(args);

var blobs = builder.AddConnectionString("blobs");

builder.AddProject<Projects.WebApplication>("web")
       .WithReference(blobs);

// After adding all resources, run the app...

注意

连接字符串用于表示各种连接信息,包括数据库连接、消息代理、终结点 URI 和其他服务。 在 .NET.NET Aspire 名词中,术语“连接字符串”用于表示任何类型的连接信息。

连接字符串是在应用主机的配置中配置的,通常在 部分下的 ConnectionStrings下。 应用主机将此连接字符串作为环境变量注入到所有依赖资源中,例如:

{
    "ConnectionStrings": {
        "blobs": "https://{account_name}.blob.core.windows.net/"
    }
}

依赖资源可以通过调用 GetConnectionString 方法并传递连接名称作为参数来访问注入的连接字符串,在本例中为 "blobs"GetConnectionString API 是 IConfiguration.GetSection("ConnectionStrings")[name]的简写。

添加 Azure 存储模拟器资源

若要添加 Azure 存储模拟器资源,请将对 IResourceBuilder<AzureStorageResource> 的调用链接到 RunAsEmulator API:

var builder = DistributedApplication.CreateBuilder(args);

var storage = builder.AddAzureStorage("storage")
                     .RunAsEmulator();

// After adding all resources, run the app...

调用 RunAsEmulator时,它将存储资源配置为使用模拟器在本地运行。 在这个例子中,Azurite是模拟器。 Azurite 开源模拟器为测试你的 Azure Blob、队列存储和表存储应用提供了一个免费的本地环境,是 .NET AspireAzure 托管集成的理想选择。 Azurite 未安装,而是作为容器可通过 .NET.NET Aspire 访问。 将容器添加到应用主机时,如前面的示例所示,其中包含 mcr.microsoft.com/azure-storage/azurite 映像,它会在应用主机启动时创建并启动容器。 有关详细信息,请参阅 容器资源生命周期

配置 Azurite 容器

容器资源可以使用各种配置,例如,可以配置容器的端口、环境变量、生存期等。

配置 Azurite 容器端口

默认情况下,.NET.NET Aspire配置 Azurite 容器时,会公开以下终结点:

端点 集装箱码头 主机端口
blob 一万 动态
queue 10001 动态
table 10002 动态

默认情况下,他们正在侦听的端口是动态的。 容器启动时,端口将映射到主机上的随机端口。 若要配置终结点端口,请对 RunAsEmulator 方法提供的容器资源生成器进行链式调用,如以下示例所示:

var builder = DistributedApplication.CreateBuilder(args);

var storage = builder.AddAzureStorage("storage").RunAsEmulator(
                     azurite =>
                     {
                         azurite.WithBlobPort("blob", 27000)
                                .WithQueuePort("queue", 27001)
                                .WithTablePort("table", 27002);
                     });

// After adding all resources, run the app...

前面的代码将 Azurite 容器的现有 blobqueuetable 终结点分别配置为侦听端口 270002700127002。 Azurite 容器的端口映射到主机端口,如下表所示:

终结点名称 端口映射(container:host
blob 10000:27000
queue 10001:27001
table 10002:27002
配置持久生存期的 Azurite 容器

若要使用持久性生存期配置 Azurite 容器,请在 Azurite 容器资源上调用 WithLifetime 方法,并传递 ContainerLifetime.Persistent

var builder = DistributedApplication.CreateBuilder(args);

var storage = builder.AddAzureStorage("storage").RunAsEmulator(
                     azurite =>
                     {
                         azurite.WithLifetime(ContainerLifetime.Persistent);
                     });

// After adding all resources, run the app...

有关详细信息,请参阅 容器资源生存期

使用数据卷配置 Azurite 容器

若要将数据卷添加到 Azure 存储模拟器资源,请在 WithDataVolume 存储模拟器资源上调用 Azure 方法:

var builder = DistributedApplication.CreateBuilder(args);

var storage = builder.AddAzureStorage("storage").RunAsEmulator(
                     azurite =>
                     {
                         azurite.WithDataVolume();
                     });

// After adding all resources, run the app...

数据卷用于在容器生命周期之外保留 Azurite 数据。 数据卷装载在 Azurite 容器中的 /data 路径,如果未提供 name 参数,则名称的格式为 .azurite/{resource name}。 有关为何数据卷优先于 绑定挂载的详细信息,请参阅 Docker 文档:卷

配置 Azurite 容器,使用数据绑定挂载

若要将数据绑定挂载添加到 Azure 存储仿真器资源,请调用 WithDataBindMount 方法:

var builder = DistributedApplication.CreateBuilder(args);

var storage = builder.AddAzureStorage("storage").RunAsEmulator(
                     azurite =>
                     {
                         azurite.WithDataBindMount("../Azurite/Data");
                     });

// After adding all resources, run the app...

重要

相比,绑定 装载的数据 功能有限,从而提供更好的性能、可移植性和安全性,使它们更适用于生产环境。 但是,绑定装载允许直接访问和修改主机系统上的文件,非常适合在需要实时更改的情况下进行开发和测试。

数据绑定装载依赖于主机的文件系统在容器重启时保留 Azurite 数据。 数据绑定装载安装在主机上相对于 Azurite 容器中的应用主机目录(../Azurite/Data)的 IDistributedApplicationBuilder.AppHostDirectory 路径上。 有关数据绑定装载的详细信息,请参阅 Docker 文档:绑定装载

连接到存储资源

.NET .NET Aspire 应用主机运行时,可以通过外部工具(例如 Azure 存储资源管理器)访问存储资源。 如果存储资源使用 Azurite 在本地运行,Azure 存储资源管理器会自动选取它。

注意

Azure 存储资源管理器在假设使用默认端口的情况下,能够发现 Azurite 存储资源。 如果已 将 Azurite 容器配置为使用不同的端口,则需要配置 Azure 存储资源管理器以连接到正确的端口。

若要从 Azure 存储资源管理器连接到存储资源,请执行以下步骤:

  1. 运行 .NET.NET Aspire 应用主机。

  2. 打开 Azure 存储资源管理器。

  3. 查看 资源管理器 窗格。

  4. 选择“刷新所有” 链接以刷新存储帐户列表。

  5. 展开 模拟器 & 附加 节点。

  6. 展开 存储帐户 节点。

  7. 您应该看到一个以您的资源名称为前缀的存储帐户。

    Azure 存储资源管理器:发现 Azurite 存储资源。

可以使用 Azure 存储资源管理器免费浏览存储帐户及其内容。 有关使用 Azure 存储资源管理器的详细信息,请参阅 存储资源管理器入门。

添加 Azure Blob Storage 资源

在应用主机项目中,通过在 Azure Blob Storage返回的 AddBlobs 实例上依次调用 IResourceBuilder<IAzureStorageResource> 来注册 AddAzureStorage 集成。 以下示例演示如何添加名为 Azure Blob Storage 的 storage 资源,以及名为 blobs的 blob 容器:

var builder = DistributedApplication.CreateBuilder(args);

var blobs = builder.AddAzureStorage("storage")
                   .RunAsEmulator();
                   .AddBlobs("blobs");

builder.AddProject<Projects.ExampleProject>()
       .WithReference(blobs)
       .WaitFor(blobs);

// After adding all resources, run the app...

前面的代码:

  • 添加名为 Azure的 storage 存储资源。
  • 将调用链接到 RunAsEmulator,将存储资源配置为使用模拟器在本地运行。 在这个例子中,Azurite是模拟器。
  • 将名为 blobs 的 blob 容器添加到存储资源。
  • blobs 资源添加到 ExampleProject,并在启动项目之前等待它准备就绪。

托管集成运行状况检查

Azure 存储托管集成会自动为存储资源添加运行状况检查。 仅当以模拟器模式运行时才会添加此功能,并会验证 Azurite 容器正在运行以及与其的连接可以建立。 托管集成依赖于 📦 AspNetCore.HealthChecksAzure.Storage.Blobs NuGet 包。

Client 集成

若要开始 .NET AspireAzure Blob Storage 客户端集成,请在使用 Azure Blob Storage 客户端的项目中安装 📦Aspire.Azure.Storage.Blobs 的 NuGet 包,即用于该应用程序的项目。 Azure Blob Storage 客户端集成会注册一个 BlobServiceClient 实例,该实例可用于与 Azure Blob Storage交互。

dotnet add package Aspire.Azure.Storage.Blobs

添加 Azure Blob Storage 客户端

在客户端使用项目的 Program.cs 文件中,对任何 IHostApplicationBuilder 调用 AddAzureBlobClient 扩展方法,以注册 BlobServiceClient,以便通过依赖项注入容器使用。 该方法采用连接名称参数。

builder.AddAzureBlobClient("blobs");

然后,可以使用依赖项注入检索 BlobServiceClient 实例。 例如,若要从服务检索客户端:

public class ExampleService(BlobServiceClient client)
{
    // Use client...
}

配置

.NET Aspire Azure Blob Storage 集成提供了多个选项,用于根据项目的要求和约定配置 BlobServiceClient

使用连接字符串

使用 ConnectionStrings 配置部分中的连接字符串时,可以在调用 AddAzureBlobClient时提供连接字符串的名称:

builder.AddAzureBlobClient("blobs");

然后,从 ConnectionStrings 配置部分检索连接字符串,支持两种连接格式:

服务统一资源标识符 (URI)

建议的方法是使用 ServiceUri,它与 AzureStorageBlobsSettings.Credential 属性配合以建立连接。 如果未配置凭据,则使用 Azure.Identity.DefaultAzureCredential

{
  "ConnectionStrings": {
    "blobs": "https://{account_name}.blob.core.windows.net/"
  }
}
连接字符串

或者,可以使用 Azure 存储连接字符串

{
  "ConnectionStrings": {
    "blobs": "AccountName=myaccount;AccountKey=myaccountkey"
  }
}

有关详细信息,请参阅 配置 Azure 存储连接字符串

使用配置提供程序

.NET Aspire Azure Blob Storage 集成支持 Microsoft.Extensions.Configuration。 它使用 AzureStorageBlobsSettings 密钥从配置加载 BlobClientOptionsAspire:Azure:Storage:Blobs。 以下代码片段是一个配置某些选项的 appsettings.json 文件示例:

{
  "Aspire": {
    "Azure": {
      "Storage": {
        "Blobs": {
          "DisableHealthChecks": true,
          "DisableTracing": false,
          "ClientOptions": {
            "Diagnostics": {
              "ApplicationId": "myapp"
            }
          }
        }
      }
    }
  }
}

有关完整的 Azure Blob Storage 客户端集成 JSON 架构,请参阅 Aspire/Azure/Storage.Blobs/ConfigurationSchema.json

使用内联委托

还可以传递 Action<AzureStorageBlobsSettings> configureSettings 委托来设置一些或所有内联选项,例如配置运行状况检查:

builder.AddAzureBlobClient(
    "blobs",
    settings => settings.DisableHealthChecks = true);

您还可以通过使用 BlobClientOptions 委托(作为 Action<IAzureClientBuilder<BlobServiceClient, BlobClientOptions>> configureClientBuilder 方法的第二个参数)来设置 AddAzureBlobClient。 例如,若要为此客户端的所有请求问题设置用户代理标头的第一部分:

builder.AddAzureBlobClient(
    "blobs",
    configureClientBuilder: clientBuilder =>
        clientBuilder.ConfigureOptions(
            options => options.Diagnostics.ApplicationId = "myapp"));

Client 集成健康检查

默认情况下,.NET.NET Aspire 集成为所有服务启用 健康检查。 有关详细信息,请参阅 .NET.NET Aspire 集成概述

.NET Aspire Azure Blob Storage 集成:

  • AzureStorageBlobsSettings.DisableHealthChecksfalse时,添加运行状况检查,尝试连接到 Azure Blob Storage。
  • /health HTTP 终结点集成,该终结点规定所有已注册的健康检查必须通过,应用才被视为可接受流量。

可观测性和遥测

.NET .NET Aspire 集成会自动设置日志记录、跟踪和指标配置,这些配置有时称为 可观测性的支柱。 有关集成可观测性和遥测的详细信息,请参阅 .NET.NET Aspire 集成概述。 根据支持服务,某些集成可能仅支持其中一些功能。 例如,某些集成支持日志记录和跟踪,但不支持指标。 也可以使用 配置 部分中介绍的技术禁用遥测功能。

伐木

.NET Aspire Azure Blob Storage 集成使用以下日志类别:

  • Azure.Core
  • Azure.Identity

描图

.NET Aspire Azure Blob Storage 集成使用 OpenTelemetry发出以下跟踪活动:

  • Azure.Storage.Blobs.BlobContainerClient

指标

由于 .NET Aspire SDK 的限制,Azure Blob StorageAzure 集成目前目前不支持指标。

另请参阅