.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 Storageclient 集成,请安装 📦Aspire。Azure。storage.Blobs 使用 client项目中的 NuGet 包,即使用 Azure Blob Storageclient的应用程序的项目。 Azure Blob Storage client 集成注册一个您可以用于与 BlobServiceClient进行交互的 Azure Blob Storage 实例。

dotnet add package Aspire.Azure.Storage.Blobs

添加 Azure Blob Storageclient

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

builder.AddAzureBlobClient("blobs");

然后,可以使用依赖项注入检索 BlobServiceClient 实例。 例如,要从服务中获取 client,可以按照以下步骤:

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 Storageclient 集成 JSON 架构,请参阅 Aspire。Azure。Storage.Blobs/ConfigurationSchema。json

使用内联委托

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

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

您还可以通过使用 BlobClientOptions 委托(作为 Action<IAzureClientBuilder<BlobServiceClient, BlobClientOptions>> configureClientBuilder 方法的第二个参数)来设置 AddAzureBlobClient。 例如,若要为此 client发出的所有请求设置 User-Agent 标头的首部分:

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 集成目前目前不支持指标。

另请参阅