.NET Aspire Azure Azure SignalR Service 集成

包括:托管集成已包括仅限于—Client集成不包括Client集成不包括

Azure SignalR Service 是一项完全托管的实时消息传送服务,可简化向应用程序添加实时 Web 功能。 通过集成.NET AspireAzureAzure SignalR Service,可以轻松地将应用程序.NETAzure预配、配置和连接到Azure SignalR Service实例。

本文介绍如何将 AzureAzure SignalR Service 集成到您的 .NET Aspire 应用程序中,包括托管和客户端集成。

托管集成

.NET Aspire Azure Azure SignalR Service 托管集成模型将 AzureSignalR 资源建模为以下类型:

  • AzureSignalRResource:表示 AzureAzure SignalR Service 资源,包括与基础 Azure 资源的连接信息。
  • AzureSignalREmulatorResource:表示一个用于AzureAzure SignalR Service的模拟器,允许本地开发和测试,而无需Azure订阅。

若要访问托管类型和 API 以在分布式应用程序生成器中表达这些资源,请安装 。📦AspireHosting.Azure.SignalR应用主机项目中的 NuGet 包:

dotnet add package Aspire.Hosting.Azure.SignalR

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

添加 AzureAzure SignalR Service 资源

若要将 AzureAzure SignalR Service 资源添加到应用主机项目,请调用 AddAzureSignalR 以下方法:

var builder = DistributedApplication.CreateBuilder(args);

var signalR = builder.AddAzureSignalR("signalr");

var api = builder.AddProject<Projects.ApiService>("api")
                 .WithReference(signalR)
                 .WaitFor(signalR);

builder.AddProject<Projects.WebApp>("webapp")
       .WithReference(api)
       .WaitFor(api);

// Continue configuring and run the app...

在上面的示例中:

  • 添加了一个名为AzureAzure SignalR Servicesignalr的资源。
  • 资源 signalrapi 项目引用。
  • api 项目被 webapp 项目引用。

此体系结构允许 webapp 项目与 api 项目通信,而该项目又与 AzureAzure SignalR Service 资源通信。

重要

调用 AddAzureSignalR 隐式启用 Azure 预配支持。 确保应用主机配置了相应的 Azure 订阅与位置。 有关详细信息,请参阅 本地预配:配置

由配置生成的 Bicep

添加 AzureAzure SignalR Service 资源时, .NET Aspire 使用 Bicep 生成预配基础结构。 生成的 Bicep 包括位置、SKU 和角色分配的默认值:

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

resource signalr 'Microsoft.SignalRService/signalR@2024-03-01' = {
  name: take('signalr-${uniqueString(resourceGroup().id)}', 63)
  ___location: ___location
  properties: {
    cors: {
      allowedOrigins: [
        '*'
      ]
    }
    features: [
      {
        flag: 'ServiceMode'
        value: 'Default'
      }
    ]
  }
  kind: 'SignalR'
  sku: {
    name: 'Free_F1'
    capacity: 1
  }
  tags: {
    'aspire-resource-name': 'signalr'
  }
}

output hostName string = signalr.properties.hostName

output name string = signalr.name

生成的 Bicep 文件提供了一个起点,可以在此基础上进一步自定义。

自定义预配基础结构

所有 .NET AspireAzure 资源都是 AzureProvisioningResource 类型的子类。 通过提供 Fluent API 来使用 Azure API 配置 ConfigureInfrastructure<T>(IResourceBuilder<T>, Action<AzureResourceInfrastructure>) 资源,从而能够自定义生成的 Bicep。

builder.AddAzureSignalR("signalr")
    .ConfigureInfrastructure(infra =>
    {
        var signalRService = infra.GetProvisionableResources()
                                  .OfType<SignalRService>()
                                  .Single();

        signalRService.Sku.Name = "Premium_P1";
        signalRService.Sku.Capacity = 10;
        signalRService.PublicNetworkAccess = "Enabled";
        signalRService.Tags.Add("ExampleKey", "Example value");
    });

前面的代码:

连接到现有 AzureAzure SignalR Service

你可能有一个现有的对象AzureAzure SignalR Service需要连接。 可以链式调用以标注 AzureSignalRResource 是现有资源。

var builder = DistributedApplication.CreateBuilder(args);

var existingSignalRName = builder.AddParameter("existingSignalRName");
var existingSignalRResourceGroup = builder.AddParameter("existingSignalRResourceGroup");

var signalr = builder.AddAzureSignalR("signalr")
                     .AsExisting(existingSignalRName, existingSignalRResourceGroup);

builder.AddProject<Projects.ExampleProject>()
       .WithReference(signalr);

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

有关将 AzureSignalR 资源视为现有资源的详细信息,请参阅 使用现有 Azure 资源

或者,您可以向应用主机添加连接字符串来代替表示 AzureSignalR 资源。 这是一种仅依赖于 string 值的弱类型化方法。 若要将连接添加到现有 AzureAzure SignalR Service,请调用 AddConnectionString 方法:

var builder = DistributedApplication.CreateBuilder(args);

var signalr = builder.ExecutionContext.IsPublishMode
    ? builder.AddAzureSignalR("signalr")
    : builder.AddConnectionString("signalr");

builder.AddProject<Projects.ApiService>("apiService")
       .WithReference(signalr);

注释

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

连接字符串在应用主机的配置中配置,通常位于 “用户机密”部分下 ConnectionStrings

{
  "ConnectionStrings": {
    "signalr": "Endpoint=https://your-signalr-instance.service.signalr.net;AccessKey=your-access-key;Version=1.0;"
  }
}

有关详细信息,请参阅 添加带有连接字符串的现有Azure资源

Azure Azure SignalR Service添加模拟器资源

仿真 AzureAzure SignalR Service 器是一种模拟其 AzureAzure SignalR Service行为的本地开发和测试工具。 此模拟器仅支持 无服务器 模式,在使用模拟器时需要特定配置。

若要使用模拟器,请链式调用 RunAsEmulator(IResourceBuilder<AzureSignalRResource>, Action<IResourceBuilder<AzureSignalREmulatorResource>>) 方法:

using Aspire.Hosting.Azure;

var builder = DistributedApplication.CreateBuilder(args);

var signalR = builder.AddAzureSignalR("signalr", AzureSignalRServiceMode.Serverless)
                     .RunAsEmulator();

builder.AddProject<Projects.ApiService>("apiService")
       .WithReference(signalR)
       .WaitFor(signalR);

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

在前面的示例中,该方法 RunAsEmulator 将资源配置为 AzureAzure SignalR Service 作为模拟器运行。 模拟器基于 mcr.microsoft.com/signalr/signalr-emulator:latest 容器映像。 模拟器在运行应用主机时启动,并在应用主机停止时停止。

Azure Azure SignalR Service 模式

Azure Azure SignalR Service虽然模拟器仅支持无服务器模式,AzureAzure SignalR Service但可以将资源配置为使用以下任一模式:

  • AzureSignalRServiceMode.Default
  • AzureSignalRServiceMode.Serverless

默认模式为AzureAzure SignalR Service的默认配置。 每个模式都有自己的一组功能和限制。 有关详细信息,请参阅 AzureAzure SignalR Service 模式

重要

模拟器 AzureAzure SignalR Service 仅适用于 无服务器 模式, AddNamedAzureSignalR 该方法不支持 无服务器 模式。

集线器主机集成

没有官方 .NET AspireAzureSignalR客户端集成。 但是,对类似体验的支持有限。 在这些情况下,AzureAzure SignalR Service 作为代理,位于服务器(托管 HubHub<T>)和客户端(托管 SignalR 客户端)之间。 路由 AzureAzure SignalR Service 服务器和客户端之间的流量,从而允许实时通信。

重要

在区分客户集成和.NET Aspire.NET客户端之间的歧义时,解决这一问题至关重要。 SignalR 公开作为服务器端概念的枢纽,SignalR 客户端连接到这些枢纽。 承载.NET中心的SignalR项目是你与.NET Aspire集成的地方。 客户端 SignalR 是一个单独的库,可连接到其他项目中的这些中心。

可用的两个包分别针对特定场景,例如管理客户端AzureAzure SignalR Service连接,以及连接到AzureAzure SignalR Service资源。 若要开始,请在托管您的 📦 中心的项目中安装 Azure NuGet 包。

dotnet add package Microsoft.Azure.SignalR

在默认模式下配置名称为AzureAzure SignalR Service

默认 模式下,消耗项目需要依赖于命名 AzureAzure SignalR Service 资源。 请考虑下图,说明Azure模式下的Azure SignalR Service体系结构:

AzureAzure SignalR Service:默认模式关系图。

有关 默认 模式的详细信息,请参阅 AzureAzure SignalR Service:默认模式

在您的 SignalR hub 主机项目中,通过将调用链接到Azure来配置 Azure SignalR Service.AddSignalR().AddNamedAzureSignalR("name")

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddSignalR()
                .AddNamedAzureSignalR("signalr");

var app = builder.Build();

app.MapHub<ChatHub>("/chat");

app.Run();

该方法AddNamedAzureSignalR将项目配置为使用名为Azure的资源Azure SignalR Servicesignalr。 连接字符串从配置键 ConnectionStrings:signalr 读取,其他设置从配置节 Azure:SignalR:signalr 加载。

注释

如果使用 AzureSignalR 模拟器,则无法使用该方法 AddNamedAzureSignalR

在无服务器模式下配置AzureAzure SignalR Service

如果你的应用宿主正在使用AzureSignalR模拟器,则还需要安装 📦 Microsoft.AzureSignalR.Management NuGet 包。

dotnet add package Microsoft.Azure.SignalR.Management

Azure SignalR 无服务器 模式不需要中心服务器运行。 Azure Azure SignalR Service 负责维护客户端连接。 此外,在此模式下,不能使用传统 SignalR 中心,例如 HubHub<T>IHubContext<THub>。 而是配置一个上游终结点,这通常是一个Azure函数SignalR触发器。 请考虑下图,说明Azure模式下的Azure SignalR Service体系结构:

AzureAzure SignalR Service:无服务器模式关系图。

有关 无服务器 模式的详细信息,请参阅 AzureAzure SignalR Service:无服务器模式

在旨在与AzureAzure SignalR Service通信的项目中,通过调用AddSignalR注册相应的服务,然后使用ServiceManager连接字符串注册signalr并添加/negotiate终结点。

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddSingleton(sp =>
{
   return new ServiceManagerBuilder()
       .WithOptions(options =>
       {
           options.ConnectionString = builder.Configuration.GetConnectionString("signalr");
       })
       .BuildServiceManager();
});

var app = builder.Build();

app.MapPost("/negotiate", async (string? userId, ServiceManager sm, CancellationToken token) =>
{
    // The creation of the ServiceHubContext is expensive, so it's recommended to 
    // only create it once per named context / per app run if possible.
    var context = await sm.CreateHubContextAsync("messages", token);
    
    var negotiateResponse = await context.NegotiateAsync(new NegotiationOptions
    {
        UserId = userId
    }, token);
    
    // The JSON serializer options need to be set to ignore null values, otherwise the
    // response will contain null values for the properties that are not set.
    // The .NET SignalR client will not be able to parse the response if the null values are present.
    // For more information, see https://github.com/dotnet/aspnetcore/issues/60935.
    return Results.Json(negotiateResponse, new JsonSerializerOptions(JsonSerializerDefaults.Web)
    {
        DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull
    });
});

app.Run();

前面的代码使用 Azure 类配置了 Azure SignalR ServiceServiceManagerBuilder,但没有调用 AddSignalRMapHub无服务器模式不需要这两个扩展。 连接字符串是从配置键 ConnectionStrings:signalr读取的。 使用模拟器时,只有 HTTP 终结点可用。 在应用中,可以使用 ServiceManager 实例创建一个 ServiceHubContextServiceHubContext 用于广播消息和管理与客户端的连接。

为建立连接客户端与/negotiateAzure之间的连接,需要Azure SignalR Service终结点。 使用ServiceHubContext 方法创建ServiceManager.CreateHubContextAsync,该方法以集线器名称作为参数。 调用NegotiateAsync方法来与AzureAzure SignalR Service协商连接,该方法返回连接客户端所需的访问令牌和URL。

有关详细信息,请参阅 “使用 AzureSignalR 管理 SDK”。

另请参阅