你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn

使用 Azure SignalR 服务

本文介绍如何在应用服务器中使用 SignalR 时在应用服务器端使用 SDK 连接到 SignalR 服务。

重要

本文中出现的原始连接字符串仅用于演示目的。

连接字符串包括应用程序访问 Azure Web PubSub 服务所需的授权信息。 连接字符串中的访问密钥类似于服务的根密码。 在生产环境中,请始终保护访问密钥。 使用 Azure Key Vault 安全地管理和轮换密钥,使用 Microsoft Entra ID 保护连接字符串,并使用 Microsoft Entra ID 授权访问

避免将访问密钥分发给其他用户、对其进行硬编码或将其以纯文本形式保存在其他人可以访问的任何位置。 如果你认为访问密钥可能已泄露,请轮换密钥。

创建 Azure SignalR 服务实例

按照快速入门:使用 ARM 模板部署 Azure SignalR 以创建 SignalR 服务实例。

对于 ASP.NET Core SignalR

安装 SDK

运行命令,将 SignalR 服务 SDK 安装到你的 ASP.NET Core 项目。

dotnet add package Microsoft.Azure.SignalR

在你的 Startup 类中,使用 SignalR 服务 SDK,如以下代码片段所示。

public void ConfigureServices(IServiceCollection services)
{
    services.AddSignalR()
            .AddAzureSignalR();
}

public void Configure(IApplicationBuilder app)
{
    app.UseEndpoints(routes =>
    {
        routes.MapHub<YourHubClass>("/path_for_your_hub");
    });
}

配置连接字符串

本文中出现的原始连接字符串仅用于演示目的。 在生产环境中,请始终保护访问密钥。 使用 Azure Key Vault 安全地管理和轮换密钥,使用 Microsoft Entra ID 保护连接字符串,并使用 Microsoft Entra ID 授权访问

有两种方法在你的应用程序中配置 SignalR 服务的连接字符串。

  • 使用名称 Azure:SignalR:ConnectionStringAzure__SignalR__ConnectionString 设置环境变量。

    • 在 Azure 应用服务中,将其置于应用程序设置中。
  • 将连接字符串作为 AddAzureSignalR() 的参数传递。

    services.AddSignalR()
            .AddAzureSignalR("<replace with your connection string>");
    

    or

    services.AddSignalR()
            .AddAzureSignalR(options => options.ConnectionString = "<replace with your connection string>");
    

配置选项

使用 Azure SignalR 服务 SDK 时,可以自定义几个选项

ConnectionString

  • 默认值为 web.config 文件中的 Azure:SignalR:ConnectionString connectionStringappSetting
  • 可以重新配置该值,但请确保它硬编码。

InitialHubServerConnectionCount

  • 默认值是 5
  • 此选项控制应用程序服务器与 Azure SignalR 服务之间每个中心的初始连接计数。 通常保留默认值就足够。 在运行时,SDK 可能会启动新的服务器连接,以便进行性能优化或负载均衡。 当你拥有大量客户端时,可以为它提供更大的数量,以提高吞吐量。 例如,如果总共有 100,000 个客户端,则可以将连接计数增加到 1015

MaxHubServerConnectionCount

  • 默认值是 null
  • 此选项控制应用程序服务器与 Azure SignalR 服务之间每个中心允许的最大连接计数。 在运行时,SDK 可能会启动新的服务器连接,以便进行性能优化或负载均衡。 默认情况下,每当需要时,新的服务器连接就会启动。 配置了允许的最大服务器连接计数时,当服务器连接计数达到限制时,SDK 不会启动新连接。

ApplicationName

  • 默认值是 null
  • 如果要为包含相同中心名称的不同应用服务器共享同一 Azure SignalR 实例,此选项很有用。 如果未设置,则所有连接的应用服务器都被视为同一应用程序的实例。

ClaimsProvider

  • 默认值是 null
  • 此选项控制要与客户端连接关联的声明。 服务 SDK 在客户端的协商请求中为客户端生成访问令牌时会使用它。 默认情况下,保留来自协商请求的 HttpContext.User 的所有声明。 可以在 Hub.Context.User 访问它们。
  • 通常,应将此选项留为原样。 在自定义之前,请确保你了解发生的情况。

AccessTokenLifetime

  • 默认值是 1 hour
  • 此选项控制服务 SDK 为每个客户端生成的访问令牌的有效生存期。 访问令牌会在对客户端的协商请求的响应中返回。
  • ServerSentEventLongPolling 用作传输时,由于身份验证失败,客户端连接将在过期后关闭。 可以增加此值以避免客户端断开连接。

AccessTokenAlgorithm

  • 默认值为 HS256
  • 此选项提供在生成访问令牌时 SecurityAlgorithms 的选择。 现在支持的可选值为 HS256HS512。 请注意,HS512 更安全,但生成的令牌比使用 HS256 来说相对较长。

ServerStickyMode

  • 默认值是 Disabled
  • 此选项指定服务器粘滞的模式。 当客户端路由到它第一次协商的服务器时,我们将它称为服务器粘滞
  • 在分布式方案中,可以有多个应用服务器连接到一个 Azure SignalR 实例。 正如客户端连接内部所解释的那样,客户端首先与应用服务器协商,然后重定向到 Azure SignalR 以建立持久连接。 然后,Azure SignalR 会找到一个应用服务器来服务客户端,正如在客户端和服务器之间传输数据所解释的那样。
    • Disabled 时,客户端会路由到一个随机应用服务器。 通常,应用服务器在此模式下具有均衡的客户端连接。 如果你的方案是广播组发送,使用此默认选项就足够了。
    • Preferred 时,Azure SignalR 会尝试查找客户端首先协商的应用服务器,这样就不需要其他成本或全局路由。 当你的方案发送到连接时,这就很有用*。 当发送方和接收方被路由到同一应用服务器时,发送到连接可以有更好的性能和更低的延迟。
    • Required 时,Azure SignalR 会始终尝试查找客户端首先协商的应用服务器。 当从 negotiate 步骤中提取某些客户端上下文并将其存储在内存中,然后在 Hub 中使用它时,此选项很有用。 但是,此选项可能有性能缺点,因为它需要 Azure SignalR 采取其他努力,以全局方式查找此特定应用服务器,并全局保留客户端和服务器之间的路由流量。

GracefulShutdown

GracefulShutdown.Mode
  • 默认值为 Off
  • 此选项指定应用服务器收到 SIGINT (CTRL + C) 后的行为。
  • 如果设置为 WaitForClientsClose,而不是立即停止服务器,我们会将其从 Azure SignalR 服务中移除,以防止将新的客户端连接分配到此服务器。
  • 此外,如果设置为 MigrateClients,则我们会尝试将客户端连接迁移到另一个有效服务器。 只有在传递消息后,才会触发迁移。
    • OnConnectedOnDisconnected 在连接被迁入/迁出时触发。
    • IConnectionMigrationFeature 可以帮助确定连接是否已迁入/迁出。
    • 有关详细用法,请参阅我们的示例代码
GracefulShutdown.Timeout
  • 默认值为 30 seconds
  • 此选项指定等待客户端关闭/迁移的最长时长。

ServiceScaleTimeout

  • 默认值为 5 minutes
  • 此选项指定等待动态缩放服务终结点的最长时长,以最小化对联机客户端的影响。 通常,单个应用服务器和服务终结点之间的动态缩放可以在几秒钟内完成,当考虑你是否有多个应用服务器和具有网络抖动的多个服务终结点,并且希望确保客户端稳定性时,可以相应地配置此值。

MaxPollIntervalInSeconds

  • 默认值为 5
  • 此选项定义 Azure SignalR 服务中 LongPolling 连接允许的最大轮询间隔。 如果下一个轮询请求未在 MaxPollIntervalInSeconds 内传入,则 Azure SignalR 服务将清理客户端连接。
  • 该值限制为 [1, 300]

TransportTypeDetector

  • 默认值:启用所有传输。
  • 此选项定义一个函数,以自定义客户端可用于发送 HTTP 请求的传输。
  • 请使用此选项而非使用 HttpConnectionDispatcherOptions.Transports 来配置传输。

AllowStatefulReconnects

  • 默认值为 null
  • 此选项启用或禁用所有中心的监控状态的重新连接。
  • 如果为 null,SDK 会读取中心设置
  • 如果为 true,Azure SignalR 服务会在所有已声明的中心内启用监控状态的重新连接。 客户端需要在客户端启用监控状态的重新连接
  • 如果为 false,Azure SignalR 服务会在所有已声明的中心内禁用监控状态的重新连接。

示例

可以配置上述选项,如以下示例代码所示。

services.AddSignalR()
        .AddAzureSignalR(options =>
            {
                options.InitialHubServerConnectionCount = 10;
                options.AccessTokenLifetime = TimeSpan.FromDays(1);
                options.ClaimsProvider = context => context.User.Claims;

                options.GracefulShutdown.Mode = GracefulShutdownMode.WaitForClientsClose;
                options.GracefulShutdown.Timeout = TimeSpan.FromSeconds(10);
                options.TransportTypeDetector = httpContext => AspNetCore.Http.Connections.HttpTransportType.WebSockets | AspNetCore.Http.Connections.HttpTransportType.LongPolling;
            });

对于旧版 ASP.NET SignalR

注意

如果这是你第一次尝试 SignalR,我们建议使用 ASP.NET Core SignalR,它更简单、更可靠且更易于使用

安装 SDK

使用包管理器控制台将 SignalR 服务 SDK 安装到你的 ASP.NET 项目:

Install-Package Microsoft.Azure.SignalR.AspNet

在你的 Startup 类中,使用 SignalR 服务 SDK,如以下代码片段所示,将 MapSignalR() 替换为 MapAzureSignalR({your_applicationName})。 将 {YourApplicationName} 替换为你的应用程序的名称,这是将此应用程序与你的其他应用程序区分开来的唯一名称。 可以使用 this.GetType().FullName 作为值。

public void Configuration(IAppBuilder app)
{
    app.MapAzureSignalR(this.GetType().FullName);
}

配置连接字符串

web.config 文件中的连接字符串设置为 connectionStrings 部分:

<configuration>
    <connectionStrings>
        <add name="Azure:SignalR:ConnectionString" connectionString="Endpoint=...;AccessKey=..."/>
    </connectionStrings>
    ...
</configuration>

配置选项

使用 Azure SignalR 服务 SDK 时,可以自定义几个选项

ConnectionString

  • 默认值为 web.config 文件中的 Azure:SignalR:ConnectionString connectionStringappSetting
  • 可以重新配置该值,但请确保它硬编码。

InitialHubServerConnectionCount

  • 默认值是 5
  • 此选项控制应用程序服务器与 Azure SignalR 服务之间每个中心的初始连接计数。 通常保留默认值就足够。 在运行时,SDK 可能会启动新的服务器连接,以便进行性能优化或负载均衡。 当你拥有大量客户端时,可以为它提供更大的数量,以提高吞吐量。 例如,如果总共有 100,000 个客户端,则可以将连接计数增加到 1015

MaxHubServerConnectionCount

  • 默认值是 null
  • 此选项控制应用程序服务器与 Azure SignalR 服务之间每个中心允许的最大连接计数。 在运行时,SDK 可能会启动新的服务器连接,以便进行性能优化或负载均衡。 默认情况下,每当需要时,新的服务器连接就会启动。 配置了允许的最大服务器连接计数时,当服务器连接计数达到限制时,SDK 不会启动新连接。

ApplicationName

  • 默认值是 null
  • 如果要为包含相同中心名称的不同应用服务器共享同一 Azure SignalR 实例,此选项很有用。 如果未设置,则所有连接的应用服务器都被视为同一应用程序的实例。

ClaimProvider

  • 默认值是 null
  • 此选项控制要与客户端连接关联的声明。 服务 SDK 在客户端的协商请求中为客户端生成访问令牌时会使用它。 默认情况下,保留来自协商请求的 IOwinContext.Authentication.User 的所有声明。
  • 通常,应将此选项留为原样。 在自定义之前,请确保你了解发生的情况。

AccessTokenLifetime

  • 默认值是 1 hour
  • 此选项控制服务 SDK 为每个客户端生成的访问令牌的有效生存期。 访问令牌会在对客户端的协商请求的响应中返回。
  • ServerSentEventLongPolling 用作传输时,由于身份验证失败,客户端连接将在过期后关闭。 可以增加此值以避免客户端断开连接。

AccessTokenAlgorithm

  • 默认值为 HS256
  • 此选项提供在生成访问令牌时 SecurityAlgorithms 的选择。 现在支持的可选值为 HS256HS512。 请注意,HS512 更安全,但生成的令牌比使用 HS256 来说相对较长。

ServerStickyMode

  • 默认值是 Disabled
  • 此选项指定服务器粘滞的模式。 当客户端路由到它第一次协商的服务器时,我们将它称为服务器粘滞
  • 在分布式方案中,可以有多个应用服务器连接到一个 Azure SignalR 实例。 正如客户端连接内部所解释的那样,客户端首先与应用服务器协商,然后重定向到 Azure SignalR 以建立持久连接。 然后,Azure SignalR 会找到一个应用服务器来服务客户端,正如在客户端和服务器之间传输数据所解释的那样。
    • Disabled 时,客户端会路由到一个随机应用服务器。 通常,应用服务器在此模式下具有均衡的客户端连接。 如果你的方案是广播组发送,使用此默认选项就足够了。
    • Preferred 时,Azure SignalR 会尝试查找客户端首先协商的应用服务器,这样就不需要其他成本或全局路由。 当你的方案发送到连接时,这就很有用*。 当发送方和接收方被路由到同一应用服务器时,发送到连接可以有更好的性能和更低的延迟。
    • Required 时,Azure SignalR 会始终尝试查找客户端首先协商的应用服务器。 当从 negotiate 步骤中提取某些客户端上下文并将其存储在内存中,然后在 Hub 中使用它时,此选项很有用。 但是,此选项可能有性能缺点,因为它需要 Azure SignalR 采取其他努力,以全局方式查找此特定应用服务器,并全局保留客户端和服务器之间的路由流量。

MaxPollIntervalInSeconds

  • 默认值为 5
  • 此选项定义了 Azure SignalR 服务中非活动连接允许的最大空闲时间。 在 ASP.NET SignalR 中,它适用于长轮询传输类型或重新连接。 如果下一个 /reconnect/poll 请求未在 MaxPollIntervalInSeconds 内传入,Azure SignalR 服务将清理客户端连接。
  • 该值限制为 [1, 300]

示例

可以配置上述选项,如以下示例代码所示。

app.Map("/signalr",subApp => subApp.RunAzureSignalR(this.GetType().FullName, new HubConfiguration(), options =>
{
    options.InitialHubServerConnectionCount = 1;
    options.AccessTokenLifetime = TimeSpan.FromDays(1);
    options.ClaimProvider = context => context.Authentication?.User.Claims;
}));

横向扩展应用程序服务器

使用 Azure SignalR 服务时,持久性连接将从应用程序服务器卸载,以便你可以专注于在中心类中实现业务逻辑。 但是,在处理大规模客户端连接时,你仍需要横向扩展应用程序服务器以提高性能。 下面是横向扩展应用程序服务器的一些提示。

  • 多个应用程序服务器可以连接到同一 Azure SignalR 服务实例。
  • 如果要为包含相同中心名称的不同应用程序共享相同的 Azure SignalR 实例,请使用不同的 ApplicationName 选项设置它们。 如果未设置,则所有连接的应用服务器都被视为同一应用程序的实例。
  • 只要 ApplicationName 选项和中心类的名称相同,来自不同应用程序服务器的连接就会被分组到同一中心。
  • 每个客户端连接只会在其中一个应用程序服务器中创建,来自该客户端的消息只会发送到那个应用程序服务器。 如果要全局访问客户端信息(从所有应用程序服务器),则必须使用一些集中式存储来保存来自所有应用程序服务器的客户端信息。

后续步骤

本文介绍如何在应用程序中使用 SignalR 服务。 查看以下文章以了解有关 SignalR 服务的更多信息。