Aspire Azure Service Bus 集成

包含:已包含托管集成 托管集成 —&— 已包含 Client 集成Client 集成

Azure Service Bus 是一个完全托管的企业消息中转站,其中包含消息队列和发布-订阅主题。 通过 AspireAzure Service Bus 集成,可以从 Azure Service Bus 应用程序连接到 .NET 实例。

托管集成

托管 AspireAzure Service Bus 集成将各种服务总线资源建模为以下类型:

若要访问这些类型和 API 来表达它们,请添加 .📦AspireHosting.Azure.AppHost 项目中的 ServiceBus NuGet 包。

dotnet add package Aspire.Hosting.Azure.ServiceBus

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

添加 Azure Service Bus 资源

在 AppHost 项目中,调用 AddAzureServiceBus 添加并返回 Azure Service Bus 资源生成器。

var builder = DistributedApplication.CreateBuilder(args);

var serviceBus = builder.AddAzureServiceBus("messaging");

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

将 a AzureServiceBusResource 添加到 AppHost 时,它会公开其他有用的 API 来添加队列和主题。 换句话说,在添加任何其他服务总线资源之前,必须先添加AzureServiceBusResource

重要

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

连接到现有 Azure Service Bus 命名空间

你可能希望连接到一个现有的 Azure Service Bus 命名空间。 链接调用以标注你的 AzureServiceBusResource 是现有资源:

var builder = DistributedApplication.CreateBuilder(args);

var existingServiceBusName = builder.AddParameter("existingServiceBusName");
var existingServiceBusResourceGroup = builder.AddParameter("existingServiceBusResourceGroup");

var serviceBus = builder.AddAzureServiceBus("messaging")
                        .AsExisting(existingServiceBusName, existingServiceBusResourceGroup);

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

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

重要

调用RunAsExistingPublishAsExistingAsExisting处理订阅中Azure已存在的资源的方法时,必须将某些配置值添加到 AppHost,以确保Aspire找到它们。 必要的配置值包括 SubscriptionIdAllowResourceGroupCreationResourceGroupLocation。 如果您不设置它们,仪表板中就会出现“缺少配置”错误 Aspire。 有关如何设置它们的详细信息,请参阅 “配置”。

有关将 Azure Service Bus 资源视为现有资源的详细信息,请参阅 “使用现有 Azure 资源”。

或者,可以向 AppHost 添加连接字符串,而不是表示 Azure Service Bus 资源。 此方法属于弱类型,不适用于角色分配或基础结构自定义。 有关详细信息,请参阅 添加包含连接字符串的现有 Azure 资源

添加 Azure Service Bus 队列

若要添加 Azure Service Bus 队列,请在 AddServiceBusQueue上调用 IResourceBuilder<AzureServiceBusResource> 方法:

var builder = DistributedApplication.CreateBuilder(args);

var serviceBus = builder.AddAzureServiceBus("messaging");
var queue = serviceBus.AddServiceBusQueue("queue");

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

调用 AddServiceBusQueue(IResourceBuilder<AzureServiceBusResource>, String, String)时,它将服务总线资源配置为具有名为 queue的队列。 表达了 messaging 服务总线资源与其子 queue 之间的明确父子关系。 队列是在服务总线命名空间中创建的,该命名空间由前面添加的 AzureServiceBusResource 表示。 有关详细信息,请参阅队列、主题和订阅。Azure Service Bus

添加 Azure Service Bus 主题和订阅

若要添加 Azure Service Bus 主题,请在 AddServiceBusTopic上调用 IResourceBuilder<AzureServiceBusResource> 方法:

var builder = DistributedApplication.CreateBuilder(args);

var serviceBus = builder.AddAzureServiceBus("messaging");
var topic = serviceBus.AddServiceBusTopic("topic");

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

调用 AddServiceBusTopic(IResourceBuilder<AzureServiceBusResource>, String, String)时,它将服务总线资源配置为具有名为 topic的主题。 主题是在你之前添加的 AzureServiceBusResource 所表示的服务总线命名空间中创建的。

若要添加主题的订阅,请在 AddServiceBusSubscription 上调用 IResourceBuilder<AzureServiceBusTopicResource> 方法,并使用 WithProperties 方法对其进行配置:

using Aspire.Hosting.Azure;

var builder = DistributedApplication.CreateBuilder(args);

var serviceBus = builder.AddAzureServiceBus("messaging");
var topic = serviceBus.AddServiceBusTopic("topic");
topic.AddServiceBusSubscription("sub1")
     .WithProperties(subscription =>
     {
         subscription.MaxDeliveryCount = 10;
         subscription.Rules.Add(
             new AzureServiceBusRule("app-prop-filter-1")
             {
                 CorrelationFilter = new()
                 {
                     ContentType = "application/text",
                     CorrelationId = "id1",
                     Subject = "subject1",
                     MessageId = "msgid1",
                     ReplyTo = "someQueue",
                     ReplyToSessionId = "sessionId",
                     SessionId = "session1",
                     SendTo = "xyz"
                 }
             });
     });

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

上述代码不仅添加了一个主题,还为该主题创建并配置了一个名为 sub1 的订阅。 订阅的最大传递计数是 10,还有一个名为 app-prop-filter-1的规则。 规则是一个关联筛选器,它基于 ContentTypeCorrelationIdSubjectMessageIdReplyToReplyToSessionIdSessionIdSendTo 属性筛选消息。

有关详细信息,请参阅队列、主题和订阅。Azure Service Bus

添加 Azure Service Bus 模拟器资源

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

var builder = DistributedApplication.CreateBuilder(args);

var serviceBus = builder.AddAzureServiceBus("messaging")
                        .RunAsEmulator();

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

调用 RunAsEmulator时,它会将服务总线资源配置为使用模拟器在本地运行。 在本例中,Azure Service Bus模拟器是一个仿真器。 Azure Service Bus 模拟器提供了一个免费的本地环境来测试 Azure Service Bus 应用,它是 AspireAzure 托管集成的完美伴侣。 模拟器并未安装,而是以容器的形式通过 Aspire 访问。 将容器添加到 AppHost 时,如前面的示例 mcr.microsoft.com/azure-messaging/servicebus-emulator 所示,其中包含映像(以及配套 mcr.microsoft.com/azure-sql-edge 映像),它会在 AppHost 启动时创建并启动容器。 有关详细信息,请参阅 容器资源生命周期

配置服务总线模拟器容器

有各种配置可用于容器资源,例如,可以配置容器的端口,或者提供一个整体性配置 JSON,覆盖所有内容。

配置服务总线模拟器容器主机端口

默认情况下,服务总线模拟器容器在配置 Aspire时公开以下终结点:

端点 图像 集装箱码头 主机端口
emulator mcr.microsoft.com/azure-messaging/servicebus-emulator 5672 动态的
tcp mcr.microsoft.com/mssql/server 1433 动态的

默认情况下,侦听的端口是动态的。 容器启动时,端口将映射到主机上的随机端口。 若要配置终结点端口,请对 RunAsEmulator 方法提供的容器资源生成器进行链式调用,然后对 WithHostPort(IResourceBuilder<AzureServiceBusEmulatorResource>, Nullable<Int32>) 进行链式调用,如以下示例所示:

var builder = DistributedApplication.CreateBuilder(args);

var serviceBus = builder.AddAzureServiceBus("messaging").RunAsEmulator(
                         emulator =>
                         {
                             emulator.WithHostPort(7777);
                         });

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

前面的代码将服务总线模拟器容器的现有 emulator 终结点配置为侦听端口 7777。 服务总线模拟器容器的端口映射到主机端口,如下表所示:

终结点名称 端口映射 (container:host)
emulator 5672:7777
配置服务总线模拟器容器 JSON 配置

服务总线模拟器自动生成与配置资源中的此 config.json 文件类似的配置。 你可以完全替代此生成的文件,也可以使用配置的 JSON 表示形式更新 JsonNode 配置。

若要提供自定义 JSON 配置文件,请调用 WithConfigurationFile(IResourceBuilder<AzureServiceBusEmulatorResource>, String) 方法:

var builder = DistributedApplication.CreateBuilder(args);

var serviceBus = builder.AddAzureServiceBus("messaging").RunAsEmulator(
                         emulator =>
                         {
                             emulator.WithConfigurationFile(
                                 path: "./messaging/custom-config.json");
                         });

前面的代码将服务总线模拟器容器配置为使用位于 JSON的自定义 ./messaging/custom-config.json 配置文件。 若要替代默认配置中的特定属性,请调用 WithConfiguration(IResourceBuilder<AzureServiceBusEmulatorResource>, Action<JsonNode>) 方法:

var builder = DistributedApplication.CreateBuilder(args);

var serviceBus = builder.AddAzureServiceBus("messaging").RunAsEmulator(
                         emulator =>
                         {
                             emulator.WithConfiguration(
                                 (JsonNode configuration) =>
                                 {
                                     var userConfig = configuration["UserConfig"];
                                     var ns = userConfig["Namespaces"][0];
                                     var firstQueue = ns["Queues"][0];
                                     var properties = firstQueue["Properties"];
                                     
                                     properties["MaxDeliveryCount"] = 5;
                                     properties["RequiresDuplicateDetection"] = true;
                                     properties["DefaultMessageTimeToLive"] = "PT2H";
                                 });
                         });

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

前面的代码从默认配置中检索 UserConfig 节点。 然后,它会更新第一个队列的属性,将 MaxDeliveryCount 设置为 5,将 RequiresDuplicateDetection 设置为 true,并将 DefaultMessageTimeToLive 设置为 2 hours

预配生成的 Bicep

如果你是 Bicep 的新手,Bicep 是一种特定于域的语言,用于定义 Azure 资源。 使用 Aspire时,无需手动编写 Bicep,而是预配 API 会为你生成 Bicep。 发布应用时,生成的 Bicep 文件将与清单文件一同输出。 添加 Azure Service Bus 资源时,会生成以下 Bicep:

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

param sku string = 'Standard'

resource service_bus 'Microsoft.ServiceBus/namespaces@2024-01-01' = {
  name: take('servicebus-${uniqueString(resourceGroup().id)}', 50)
  location: location
  properties: {
    disableLocalAuth: true
  }
  sku: {
    name: sku
  }
  tags: {
    'aspire-resource-name': 'service-bus'
  }
}

output serviceBusEndpoint string = service_bus.properties.serviceBusEndpoint

output name string = service_bus.name

前面的 Bicep 是预配 Azure Service Bus 命名空间资源的模块。 此外,在单独的模块中为 Azure 资源创建角色分配:

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

param service_bus_outputs_name string

param principalType string

param principalId string

resource service_bus 'Microsoft.ServiceBus/namespaces@2024-01-01' existing = {
  name: service_bus_outputs_name
}

resource service_bus_AzureServiceBusDataOwner 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
  name: guid(service_bus.id, principalId, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '090c5cfd-751d-490a-894a-3ce6f1109419'))
  properties: {
    principalId: principalId
    roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '090c5cfd-751d-490a-894a-3ce6f1109419')
    principalType: principalType
  }
  scope: service_bus
}

除了服务总线命名空间外,它还预配 Azure 数据所有者的 Azure 基于角色的访问控制 (Azure Service Bus RBAC) 内置角色。 该角色被分配给服务总线命名空间所属的资源组。 有关详细信息,请参阅 Azure Service Bus 数据所有者

自定义预配基础结构

所有 AspireAzure 资源都是 AzureProvisioningResource 类型的子类。 这类型通过提供用于配置 Azure 资源的流畅 API 来允许自定义生成的 Bicep - ConfigureInfrastructure<T>(IResourceBuilder<T>, Action<AzureResourceInfrastructure>) API。 例如,你可以配置 SKU、位置等。 以下示例演示如何自定义 Azure Service Bus 资源:

builder.AddAzureServiceBus("service-bus")
    .ConfigureInfrastructure(infra =>
    {
        var serviceBusNamespace = infra.GetProvisionableResources()
                                       .OfType<ServiceBusNamespace>()
                                       .Single();

        serviceBusNamespace.Sku = new ServiceBusSku
        {
            Name = ServiceBusSkuName.Premium
        };
        serviceBusNamespace.Tags.Add("ExampleKey", "Example value");
    });

前面的代码:

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

托管集成运行状况检查

托管集成 Azure Service Bus 会自动为服务总线资源添加运行状况检查。 运行状况检查会验证服务总线是否正在运行,以及是否可以与其建立连接。

托管集成依赖于 📦 AspNetCore.HealthChecks.AzureServiceBus NuGet 包。

Client 集成

若要开始进行 AspireAzure Service Bus 客户端集成,请在使用客户端的项目(即,使用服务总线客户端的应用程序的项目)中安装 📦Aspire.Azure.Messaging.ServiceBus NuGet 包。 服务总线客户端集成会注册一个 ServiceBusClient 实例,该实例可用于与服务总线交互。

dotnet add package Aspire.Azure.Messaging.ServiceBus

添加 Service Bus 客户端

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

builder.AddAzureServiceBusClient(connectionName: "messaging");

然后,可以使用依赖项注入检索 ServiceBusClient 实例。 例如,若要从示例服务检索连接,

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

有关依赖项注入的详细信息,请参阅 .NET 依赖项注入

选择正确的连接名称

调用 AddAzureServiceBusClient()时,正确的值取决于在 AppHost 中传递给客户端的对象。

例如,如果在 AppHost 中使用此代码:

var serviceBus = builder.AddAzureServiceBus("messaging");

var apiService = builder.AddProject<Projects.Example_ApiService>("apiservice")
    .WithReference(serviceBus);

然后,在客户端使用程序中添加服务总线的正确代码为:

builder.AddAzureServiceBusClient(connectionName: "messaging");

但是,如果您在 AppHost 中创建并传递了 Service Bus 主题:

var serviceBus = builder.AddAzureServiceBus("messaging");
var topic = serviceBus.AddServiceBusTopic("myTopic");

var apiService = builder.AddProject<Projects.Example_ApiService>("apiservice")
    .WithReference(topic);

然后,在客户端使用程序中添加服务总线主题的正确代码为:

builder.AddAzureServiceBusClient(connectionName: "myTopic");

有关详细信息,请参阅“添加资源”和“添加Azure Service BusAzure Service Bus主题”和“订阅”。

添加键控服务总线客户端

在某些情况下,可能需要使用不同的连接名称注册多个 ServiceBusClient 实例。 若要注册密钥服务总线客户端,请调用 AddKeyedAzureServiceBusClient 方法:

builder.AddKeyedAzureServiceBusClient(name: "mainBus");
builder.AddKeyedAzureServiceBusClient(name: "loggingBus");

重要

使用密钥服务时,预计您的服务总线资源需配置两个命名总线,一个用于mainBus,一个用于loggingBus

然后,可以使用依赖项注入检索 ServiceBusClient 实例。 例如,若要从示例服务检索连接,

public class ExampleService(
    [FromKeyedServices("mainBus")] ServiceBusClient mainBusClient,
    [FromKeyedServices("loggingBus")] ServiceBusClient loggingBusClient)
{
    // Use clients...
}

有关密钥服务的详细信息,请参阅 .NET 依赖关系注入:密钥服务

配置

Aspire Azure Service Bus 集成提供了多个选项,用于根据项目的要求和约定配置连接。

使用连接字符串

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

builder.AddAzureServiceBusClient("messaging");

然后,从 ConnectionStrings 配置部分检索连接字符串:

{
  "ConnectionStrings": {
    "messaging": "Endpoint=sb://{namespace}.servicebus.windows.net/;SharedAccessKeyName={keyName};SharedAccessKey={key};"
  }
}

有关如何设置此连接字符串格式的详细信息,请参阅 ConnectionString 文档。

使用配置提供程序

Aspire Azure Service Bus 集成支持 Microsoft.Extensions.Configuration。 它使用 AzureMessagingServiceBusSettings 键从配置中加载 Aspire:Azure:Messaging:ServiceBus。 以下代码片段是一个 appsettings.json 文件的示例,该文件配置了一些选项:

{
  "Aspire": {
    "Azure": {
      "Messaging": {
        "ServiceBus": {
          "ConnectionString": "Endpoint=sb://{namespace}.servicebus.windows.net/;SharedAccessKeyName={keyName};SharedAccessKey={key};",
          "DisableTracing": false
        }
      }
    }
  }
}

有关完整的服务总线客户端集成 JSON 架构,请参阅 Aspire.Azure.Messaging.ServiceBus/ConfigurationSchema.json.

使用命名配置

集成 AspireAzure Service Bus 支持命名配置,通过该配置,可以使用不同的设置来配置同一资源类型的多个实例。 命名配置使用连接名称作为主配置部分下的密钥。

{
  "Aspire": {
    "Azure": {
      "Messaging": {
        "ServiceBus": {
          "bus1": {
            "ConnectionString": "Endpoint=sb://namespace1.servicebus.windows.net/;SharedAccessKeyName=keyName;SharedAccessKey=key;",
            "DisableTracing": false
          },
          "bus2": {
            "ConnectionString": "Endpoint=sb://namespace2.servicebus.windows.net/;SharedAccessKeyName=keyName;SharedAccessKey=key;",
            "DisableTracing": true
          }
        }
      }
    }
  }
}

在此示例中,当调用bus1时,可以使用bus2AddAzureServiceBusClient作为连接名称。

builder.AddAzureServiceBusClient("bus1");
builder.AddAzureServiceBusClient("bus2");

命名配置优先于顶级配置。 如果同时提供这两种设置,则命名配置中的设置将替代顶级设置。

使用内联委托

您还可以传递 Action<AzureMessagingServiceBusSettings> configureSettings 委托以在代码中直接设置某些或所有选项,例如禁用跟踪功能。

builder.AddAzureServiceBusClient(
    "messaging",
    static settings => settings.DisableTracing = true);

还可以使用 Azure.Messaging.ServiceBus.ServiceBusClientOptions 方法的可选 Action<ServiceBusClientOptions> configureClientOptions 参数来设置 AddAzureServiceBusClient。 例如,为此客户端发出的所有请求设置 ServiceBusClientOptions.Identifier 用户代理标头后缀:

builder.AddAzureServiceBusClient(
    "messaging",
    configureClientOptions:
        clientOptions => clientOptions.Identifier = "myapp");

Client 集成运行状况检查

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

Aspire Azure Service Bus 集成:

  • AzureMessagingServiceBusSettings.DisableTracingfalse 时添加运行状况检查,该检查会尝试连接到服务总线。
  • /health HTTP 端点集成,该端点规定所有注册的健康检查必须通过,应用才能被视为已准备好接收流量。

可观测性和遥测

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

日志记录

Aspire Azure Service Bus 集成使用以下日志类别:

  • Azure.Core
  • Azure.Identity
  • Azure-Messaging-ServiceBus

除了为失败的请求获取 Azure Service Bus 请求诊断之外,还可以配置延迟阈值来确定将记录哪些成功的 Azure Service Bus 请求诊断。 对于点操作,默认值为 100 毫秒,非点操作的默认值为 500 毫秒。

builder.AddAzureServiceBusClient(
    "messaging",
    configureClientOptions:
        clientOptions => {
            clientOptions.ServiceBusClientTelemetryOptions = new()
            {
                ServiceBusThresholdOptions = new()
                {
                    PointOperationLatencyThreshold = TimeSpan.FromMilliseconds(50),
                    NonPointOperationLatencyThreshold = TimeSpan.FromMilliseconds(300)
                }
            };
        });

跟踪

Aspire Azure Service Bus 集成将通过 OpenTelemetry 生成以下跟踪活动:

  • Message
  • ServiceBusSender.Send
  • ServiceBusSender.Schedule
  • ServiceBusSender.Cancel
  • ServiceBusReceiver.Receive
  • ServiceBusReceiver.ReceiveDeferred
  • ServiceBusReceiver.Peek
  • ServiceBusReceiver.Abandon
  • ServiceBusReceiver.Complete
  • ServiceBusReceiver.DeadLetter
  • ServiceBusReceiver.Defer
  • ServiceBusReceiver.RenewMessageLock
  • ServiceBusSessionReceiver.RenewSessionLock
  • ServiceBusSessionReceiver.GetSessionState
  • ServiceBusSessionReceiver.SetSessionState
  • ServiceBusProcessor.ProcessMessage
  • ServiceBusSessionProcessor.ProcessSessionMessage
  • ServiceBusRuleManager.CreateRule
  • ServiceBusRuleManager.DeleteRule
  • ServiceBusRuleManager.GetRules

Azure Service Bus 跟踪目前处于预览版阶段,因此,你必须设置试验开关以确保发出跟踪。

AppContext.SetSwitch("Azure.Experimental.EnableActivitySource", true);

有关详细信息,请参阅 Azure Service Bus:通过服务总线消息传送进行分布式跟踪和关联

指标

由于 Aspire SDK 的限制,Azure Service BusAzure 集成目前默认不支持度量指标。

另请参阅