.NET Aspire Azure Service Bus 集成

包括: 托管集成和 Client 集成

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

托管集成

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

若要访问这些类型和 API 来表达它们,需要在 应用主机 项目中添加 📦Aspire.Hosting.Azure.ServiceBus. NuGet 包。

dotnet add package Aspire.Hosting.Azure.ServiceBus

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

添加 Azure Service Bus 资源

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

var builder = DistributedApplication.CreateBuilder(args);

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

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

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

重要

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

生成的预配 Bicep

如果你不熟悉 Bicep,则它是一种特定于域的语言,用于定义 Azure 资源。 使用 .NET.NET 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'

param principalType string

param principalId string

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'
  }
}

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
}

output serviceBusEndpoint string = service_bus.properties.serviceBusEndpoint

前面的 Bicep 是一个模块,它预配具有以下默认值的 Azure Service Bus 命名空间:

  • sku:服务总线命名空间的 SKU。 默认值为 Standard。
  • location:服务总线命名空间的位置。 默认值为资源组的位置。

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

自定义预配基础结构

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

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

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

前面的代码:

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

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

你可能希望连接到一个现有的 Azure Service Bus 命名空间。 您可以向应用程序主机添加连接字符串,而无需创建新的 Azure Service Bus 资源。 若要向现有 Azure Service Bus 命名空间添加连接,请调用 AddConnectionString 方法:

var builder = DistributedApplication.CreateBuilder(args);

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

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

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

注意

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

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

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

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

添加 Azure Service Bus 队列

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

var builder = DistributedApplication.CreateBuilder(args);

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

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

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

添加 Azure Service Bus 主题和订阅

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

var builder = DistributedApplication.CreateBuilder(args);

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

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

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

若要添加主题的订阅,请在 IResourceBuilder<AzureServiceBusTopicResource> 上调用 AddServiceBusSubscription 方法,并使用 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 应用,它是 .NET AspireAzure 托管集成的完美伴侣。 模拟器没有被安装,而是作为容器供 .NET.NET Aspire 访问。 将容器添加到应用主机时,如前面的示例所示,其中包含 mcr.microsoft.com/azure-messaging/servicebus-emulator 映像(以及配套 mcr.microsoft.com/azure-sql-edge 映像),它会在应用主机启动时创建并启动容器。 有关详细信息,请参阅 容器资源生命周期

配置服务总线模拟器容器

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

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

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

端点 图像 集装箱码头 主机端口
emulator mcr.microsoft.com/azure-messaging/servicebus-emulator 5672 动态的
tcp mcr.microsoft.com/azure-sql-edge 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 文件运行。 可以完全替代此文件,也可以使用配置 JsonNode 表示形式更新 JSON 配置。

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

var builder = DistributedApplication.CreateBuilder(args);

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

前面的代码将服务总线模拟器容器配置为使用位于 ./messaging/custom-config.json的自定义 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

托管环境集成运行状况检查

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

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

Client 集成

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

dotnet add package Aspire.Azure.Messaging.ServiceBus

添加服务总线客户端

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

builder.AddAzureServiceBusClient(connectionName: "messaging");

小提示

connectionName 参数必须与在应用主机项目中添加服务总线资源时使用的名称匹配。 换句话说,当你调用 AddAzureServiceBus 并提供 messaging 的名称时,在调用 AddAzureServiceBusClient时应使用相同的名称。 有关详细信息,请参阅 添加 Azure Service Bus 资源

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

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

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

添加键式服务总线客户端

在某些情况下,可能需要使用不同的连接名称注册多个 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 依赖项注入:键式服务

配置

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

使用连接字符串

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

builder.AddAzureServiceBusClient("messaging");

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

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

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

使用配置提供程序

.NET 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

使用内联委托

您还可以传递 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 整合健康检查

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

.NET Aspire Azure Service Bus 集成功能:

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

可观测性和遥测

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

伐木

.NET 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)
                }
            };
        });

追踪

.NET 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:通过服务总线消息传送进行分布式跟踪和关联。

指标

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

另请参阅