Azure SignalR 服务性能指南

使用 Azure SignalR 服务的重要好处之一是易于缩放 SignalR 应用程序。 在大规模方案中,性能是重要的因素。

本文介绍:

  • 影响 SignalR 应用程序性能的因素。
  • 不同用例场景中的典型性能。
  • 可用于生成性能报告的环境和工具。

使用指标进行快速评估

可以在 Azure 门户中轻松监视服务。 在 SignalR 实例的“指标”页中,可以选择“服务器负载”指标来查看服务的“压力”。

Screenshot of the Server Load metric of Azure SignalR on Portal. The metrics shows Server Load is at about 8 percent usage.

该图表显示了 SignalR 服务的计算压力。 你可以测试场景并检查此指标,以决定是否要纵向扩展。 如果服务器负载低于 70%,SignalR 服务内的延迟将保持较低水平。

注意

如果使用单元 50 或更大的 ,并且方案主要发送到小型组(组大小 < 为 20)或单个连接,则需要检查发送到小组发送到连接以供参考。 在这些场景中,存在很高的路由成本,而这并不包括在服务器负载中。

术语定义

入站: 传入 Azure SignalR 服务的消息。

出站: 从 Azure SignalR 服务传出的消息。

带宽: 1 秒内所有消息的总大小。

默认模式:创建 Azure SignalR 服务实例时的默认工作模式。 在接受任何客户端连接之前,Azure SignalR 服务预期应用服务器会与它建立连接。

无服务器模式: 在此模式下,Azure SignalR 服务仅接受客户端连接。 不允许服务器连接。

概述

Azure SignalR 服务为不同的性能容量定义了七个标准层。 本文将解答以下问题:

  • 每个层(单元)的典型 Azure SignalR 服务性能是什么?

  • Azure SignalR 服务是否符合我的消息吞吐量要求(例如,每秒发送 100,000 条消息)?

  • 对于特定方案,如何选择适当的层?

  • 哪种应用服务器(VM 大小)适合我? 应部署其中的多少个应用服务器?

为了解答这些问题,本指南首先提供影响性能的因素的概要说明。 然后,阐释每个层在以下典型用例中的最大入站和出站消息:“回显”、“广播”、“发送到组”以及“发送到连接”(对等聊天)。

本指南无法涵盖所有方案(及不同的用例、消息大小、消息发送模式等)。 但其中提供了一些方法来帮助你:

  • 评估入站或出站消息的大致要求。
  • 通过检查性能表找到适当的层。

性能见解

本部分介绍性能评估方法,然后列出影响性能的所有因素。 最后,提供一些方法来帮助你评估性能要求。

方法

吞吐量和延迟是两个典型的性能检查项目。 对于 Azure SignalR 服务,每个 SKU 层具有自身的吞吐量限制策略。 该策略将允许的最大吞吐量(入站和出站带宽)定义为当 99% 的消息的延迟小于 1 秒时实现的最大吞吐量。

延迟是从连接发送消息,到 Azure SignalR 服务收到响应消息的时间跨度。 以“回显”为例。 每个客户端连接在消息中添加一个时间戳。 应用服务器的中心将原始消息发送回到客户端。 因此,每个客户端连接可以轻松计算传播延迟。 将为“广播”、“发送到组”和“发送到连接”中的每条消息附加时间戳。

若要模拟数千个并发客户端连接,需在 Azure 的虚拟专用网络中创建多个 VM。 所有这些 VM 连接到同一个 Azure SignalR 服务实例。

在 Azure SignalR 服务的默认模式下,应用服务器 VM 将部署在客户端 VM 所在的同一个虚拟专用网络中。 所有客户端 VM 和应用服务器 VM 部署在同一区域的同一网络中,以避免跨区域延迟。

性能因素

以下因素会影响 SignalR 性能。

  • SKU 层(CPU/内存)
  • 连接数
  • 消息大小
  • 消息发送速率
  • 传输类型(WebSocket、Server-Sent-Event 或 Long-Polling)
  • 用例场景(路由开销)
  • 应用服务器和服务连接(服务器模式)

计算机资源

理论上,Azure SignalR 服务容量受计算资源的限制:CPU、内存和网络。 例如,与 Azure SignalR 服务建立更多连接会导致服务使用更多的内存。 对于较大的消息流量(例如,每条消息大于 2,048 字节),Azure SignalR 服务需要消耗更多的 CPU 周期来处理流量。 同时,Azure 网络带宽也对最大流量施加限制。

传输类型

传输类型是影响性能的另一个因素。 这三种类型是:

  • WebSocket:WebSocket 是基于单个 TCP 连接的双向全双工通信协议。
  • Server-Sent-Event:Server-Sent-Event 是将消息从服务器推送到客户端的单向协议。
  • Long-Polling:Long-Polling 要求客户端定期通过 HTTP 请求来从服务器轮询信息。

对于相同条件下的同一 API,WebSocket 的性能最佳,Server-Sent-Event 的速度较慢,而 Long-Polling 是最慢的。 默认情况下,Azure SignalR 服务建议使用 WebSocket。

消息路由成本

消息路由开销也会限制性能。 Azure SignalR 服务充当消息路由器的角色,它将消息从一组客户端或服务器路由到其他客户端或服务器。 不同的方案或 API 需要不同的路由策略。

对于“回显”,客户端会将消息发送到自身,而路由目标也是自身。 此模式的路由开销最低。 但对于“广播”,“发送到组”和“发送到连接”,Azure SignalR 服务需要通过内部分布式数据结构来查找目标连接。 这些额外的处理会占用更多的 CPU、内存和网络带宽。 因此,性能将会降低。

在某些情况下,处于默认模式的应用服务器还可能成为瓶颈。 Azure SignalR SDK 必须调用中心,同时通过检测信号来保持与每个客户端的实时连接。

在无服务器模式下,客户端通过 HTTP POST 发送消息,这不如 WebSocket 那么有效。

协议

另一个因素是协议:JSON 和 MessagePack。 MessagePack 较小,其传送速度比 JSON 要快。 不过,MessagePack 可能无法提高性能。 Azure SignalR 服务的性能对协议不敏感,因为在将消息从客户端转发到服务器或反向转发时,它不会对消息有效负载进行解码。

查找适当的 SKU

如何评估入站/出站容量或确定哪个层适合特定的用例?

假设应用服务器足够强大,不会成为性能瓶颈。 那么,请检查每个层的最大入站和出站带宽。

快速评估

为了快速评估,我们假定采用以下默认设置:

  • 传输类型为 WebSocket。
  • 消息大小为 2,048 字节。
  • 每隔 1 秒发送消息。
  • Azure SignalR 服务处于默认模式。

每个层具有自身的最大入站带宽和出站带宽。 在入站或出站连接超过限制后,不能保证顺畅的用户体验。

“回显”提供最大的入站带宽,因为它的路由开销最低。 “广播”定义最大出站消息带宽。

不要超过以下两个表中突出显示的值。

回显 单元 1 单元 2 单元 10 单元 50 单元 100 单元 200 单元 500 单元 1000
连接 1,000 2,000 10,000 50,000 100,000 200,000 500,000 1,000,000
入站带宽 2 MBps 4 MBps 20 MBps 100 MBps 200 MBps 400 MBps 1,000 MBps 2000 MBps
出站带宽 2 MBps 4 MBps 20 MBps 100 MBps 200 MBps 400 MBps 1,000 MBps 2,000 MBps
广播 单元 1 单元 2 单元 10 单元 50 单元 100 单元 200 单元 500 单元 1000
连接 1,000 2,000 10,000 50,000 100,000 200,000 500,000 1,000,000
入站带宽 4 KBps 4 KBps 4 KBps 4 KBps 4 KBps 4 KBps 4 KBps 4 KBps
出站带宽 4 MBps 8 MBps 40 MBps 200 MBps 400 MBps 800 MBps 2,000 MBps 4,000 MBps

入站带宽和出站带宽是每秒的消息总大小。 它们的计算公式如下:

  inboundBandwidth = inboundConnections * messageSize / sendInterval
  outboundBandwidth = outboundConnections * messageSize / sendInterval
  • inboundConnections:发送消息的连接数。

  • outboundConnections:接收消息的连接数。

  • messageSize:单个消息的大小(平均值)。 小于 1,024 字节的小型消息的性能影响与 1,024 字节消息类似。

  • sendInterval:发送一条消息花费的时间。 通常发送每条消息需要 1 秒,即,每秒发送一条消息。 间隔越短,在一个时间段内发送的消息越多。 例如,每条消息花费 0.5 秒意味着每秒可发送两条消息。

  • 连接:每个层的 Azure SignalR 服务的承诺最大阈值。 如果连接数进一步增加,将遭到连接限制。

注意

需要纵向扩展到 SKU Premium_P2,单位大小大于 100。

复杂用例的评估

较大的消息大小或不同的发送速率

实际用例更复杂。 服务可能会发送大于 2,048 字节的消息,或者消息发送速率不是每秒一条消息。 我们以单元 100 的广播为例来了解如何评估其性能。

下表显示了“广播”的实际用例。 但是,消息大小、连接计数和消息发送速率不同于上一部分假设的条件。 问题在于,如果我们仅知道消息大小、连接计数或消息发送速率中的两项,如何推断剩余的任何一项。

广播 消息大小 并发入站消息 连接 发送间隔
1 20 KB 1 100,000 5 秒
2 256 KB 1 8,000 5 秒

以下公式可根据前一公式轻松推断出:

outboundConnections = outboundBandwidth * sendInterval / messageSize

对于单元 100,上表中的最大出站带宽为 400 MB。 对于 20 KB 消息大小,最大出站连接数应为 400 MB * 5 / 20 KB = 100,000,这与实际值匹配。

混合用例

实际用例通常将四个基本用例混合到一起:“回显”、“广播”、“发送到组”和“发送到连接”。 用于评估容量的方法是:

  1. 将混合用例划分为四个基本用例。
  2. 使用前面的公式分别计算最大入站和出站消息带宽。
  3. 将带宽计算结果相加,得出最大入站/出站总带宽。

然后从最大入站/出站带宽表中选出适当的层。

注意

如果将某条消息发送到数百个甚至数千个小型组,或者数千个客户端相互发送某条消息,则路由开销将很显著。 请考虑到这种影响。

对于向客户端发送消息的用例,请确保应用服务器不会成为瓶颈。 以下“案例研究”部分提供了有关需要多少个应用服务器,以及应配置多少个服务器连接的指导。

案例研究

以下部分探讨 WebSocket 传输的四个典型用例:“回显”、“广播”、“发送到组”和“发送到连接”。 对于每种方案,相应部分列出了 Azure SignalR 服务的当前入站和出站容量。 此外,它还解释了影响性能的主要因素。

在默认模式下,应用服务器将与 Azure SignalR 服务建立 5 个服务器连接。 应用服务器默认使用 Azure SignalR 服务 SDK。 在以下性能测试结果中,服务器连接数已增加至 15 个(或更多,以便将消息广播并发送到大型组)。

不同用例对应用服务器的要求不同。 “广播”需要少量的应用服务器。 “回显”或“发送到连接”需要大量的应用服务器。

在所有用例中,默认消息大小为 2,048 字节,消息发送间隔为 1 秒。

默认模式

客户端、Web 应用服务器和 Azure SignalR 服务参与默认模式。 每个客户端代表一个连接。

回显

首先,Web 应用连接到 Azure SignalR 服务。 其次,许多客户端连接到 Web 应用,后者使用访问令牌和终结点将客户端重定向到 Azure SignalR 服务。 然后,客户端与 Azure SignalR 服务建立 WebSocket 连接。

所有客户端建立连接后,开始每秒向特定的中心发送包含时间戳的消息。 中心将消息回显给消息的原始客户端。 每个客户端在收到回显消息时计算延迟。

在下图中,5 到 8(以红色突出显示的流量)处于循环中。 循环运行默认的持续时间(5 分钟),并获取所有消息延迟的统计信息。

Traffic for the echo use case

“回显”的行为决定了最大入站带宽等于最大出站带宽。 有关详细信息,请参阅下表。

回显 单元 1 单元 2 单元 10 单元 50 单元 100 单元 200 单元 500 单元 1000
连接 1,000 2,000 10,000 50,000 100,000 200,000 500,000 1,000,000
每秒入站/出站消息数 1,000 2,000 10,000 50,000 100,000 200,000 500,000 1,000,000
入站/出站带宽 2 MBps 4 MBps 20 MBps 100 MBps 200 MBps 400 MBps 1,000 MBps 2,000 MBps

在此用例中,每个客户端调用应用服务器中定义的中心。 此中心只调用原始客户端中定义的方法。 此中心是用于“回显”的最轻量中心。

public void Echo(IDictionary<string, object> data)
{
    Clients.Client(Context.ConnectionId).SendAsync("RecordLatency", data);
}

即使是对于这样一个简单的中心,随着“回显”入站消息负载的增大,应用服务器上的流量压力也很大。 此流量压力要求很多应用服务器使用较大的 SKU 层。 下表列出了每个层的应用服务器计数。

回显 单元 1 单元 2 单元 10 单元 50 单元 100 单元 200 单元 500 单元 1000
连接 1,000 2,000 10,000 50,000 100,000 200,000 500,000 1,000,000
应用服务器计数 1 1 1 5 10 20 50 100

注意

应用服务器的客户端连接数、消息大小、消息发送速率、SKU 层和 CPU/内存会影响“回显”的整体性能。

广播

对于“广播”,当 Web 应用收到消息时,会广播到所有客户端。 要广播到的客户端越多,发往所有客户端的消息流量就越大。 请参阅下图。

Traffic for the broadcast use case

少量的客户端正在广播。 入站消息带宽较小,但出站带宽巨大。 出站消息带宽随着客户端连接数或广播速率的增大而增大。

下表汇总了最大客户端连接数、入站/出站消息计数和带宽。

广播 单元 1 单元 2 单元 10 单元 50 单元 100 单元 200 单元 500 单元 1000
连接 1,000 2,000 10,000 50,000 100,000 200,000 500,000 1,000,000
每秒入站消息数 2 2 2 2 2 2 2 2
每秒出站消息数 2,000 4,000 20,000 100,000 200,000 400,000 1,000,000 2,000,000
入站带宽 4 KBps 4 KBps 4 KBps 4 KBps 4 KBps 4 KBps 4 KBps 4 KBps
出站带宽 4 MBps 8 MBps 40 MBps 200 MBps 400 MBps 800 MBps 2,000 MBps 4000 Mbps

发布消息的广播客户端不超过 4 个。 与“回显”相比,广播客户端所需的应用服务器更少,因为入站消息量较小。 两个应用服务器就足以符合 SLA 并解决性能需求。 但是,应增加默认的服务器连接数以避免失衡,尤其是对于大于 50 的单位。

广播 单元 1 单元 2 单元 10 单元 50 单元 100 单元 200 单元 500 单元 1000
连接 1,000 2,000 10,000 50,000 100,000 200,000 500,000 1,000,000
应用服务器计数 1 1 1 2 2 4 10 20

注意

将每个应用服务器上的默认服务器连接数从 5 增加到 40,以避免与 Azure SignalR 服务建立的服务器连接数失衡。

客户端连接数、消息大小、消息发送速率和 SKU 层会影响“广播”的整体性能。

发送到组

“发送到组”用例的流量模式与“广播”类似。 不同之处在于,在客户端与 Azure SignalR 服务建立 WebSocket 连接后,必须先加入组,然后才能将消息发送到特定的组。 下图演示了流量流。

Traffic for the send-to-group use case

组成员和组计数是影响性能的两个因素。 为了简化分析,我们定义了两种类型的组:

  • 小型组:每个组有 10 个连接。 组数 = 最大连接数 / 10。 例如,对于单元 1,如果连接计数为 1,000,则组数为 1000 / 10 = 100。

  • 大型组:组数始终为 10。 组成员计数 = 最大连接计数 / 10。 例如,对于单元 1,如果连接计数为 1,000,则每个组的成员数为 1000 / 10 = 100。

“发送到组”将路由开销计入到 Azure SignalR 服务,因为它必须通过分布式数据结构查找目标连接。 随着发送连接数的增加,开销也会增大。

小型组

将消息发送到大量的小型组时,路由开销很大。 目前,Azure SignalR 服务实施方案已经达到了单元 50 的路由开销限制。 添加更多的 CPU 和内存不起作用,因此单元 100 无法通过设计进一步改善。 如果需要更大的入站带宽,请与客户支持联系。

发送到小型组 单元 1 单元 2 单元 10 单元 50 单元 100 单元 200 单元 500 单元 1000
连接 1,000 2,000 10,000 50,000 100,000 200,000 500,000 1,000,000
组成员计数 10 10 10 10 10 10 10 10
组计数 100 200 1,000 5,000 10,000 20,000 50,000 100,000
每秒入站消息数 200 400 2,000 10,000 10,000 20,000 50,000 100,000
入站带宽 400 KBps 800 KBps 4 MBps 20 MBps 20 MBps 40 MBps 100 MBps 200 MBps
每秒出站消息数 2,000 4,000 20,000 100,000 100,000 200,000 500,000 1,000,000
出站带宽 4 MBps 8 MBps 40 MBps 200 MBps 200 MBps 400 MBps 1,000 MBps 2,000 MBps

许多客户端连接正在调用中心,因此应用服务器数对于性能也很关键。 下表列出了建议的应用服务器计数。

发送到小型组 单元 1 单元 2 单元 10 单元 50 单元 100 单元 200 单元 500 单元 1000
连接 1,000 2,000 10,000 50,000 100,000 200,000 500,000 1,000,000
应用服务器计数 1 1 1 5 10 20 50 100

注意

应用服务器的客户端连接数、消息大小、消息发送速率、路由开销、SKU 层和 CPU/内存会影响“发送到小型组”的整体性能。

表中列出的组计数、组成员计数不是硬限制。 要建立稳定的基准测试方案,请选择这些参数值。 例如,可将每个连接分配到不同的组。 在此配置下,性能接近于发送到连接

大型组

对于“发送到大型组”,出站带宽在达到路由开销限制之前会成为瓶颈。 下表列出了最大出站带宽(与“广播”几乎相同)。

发送到大型组 单元 1 单元 2 单元 10 单元 50 单元 100 单元 200 单元 500 单元 1000
连接 1,000 2,000 10,000 50,000 100,000 200,000 500,000 1,000,000
组成员计数 100 200 500 1,000 2,000 5,000 10,000 20,000
组计数 10 10 10 10 10 10 10 10
每秒入站消息数 20 20 20 20 20 20 20 20
入站带宽 40 KBps 40 KBps 40 KBps 40 KBps 40 KBps 40 KBps 40 KBps 40 KBps
每秒出站消息数 2,000 4,000 20,000 100,000 200,000 400,000 1,000,000 2,000,000
出站带宽 4 MBps 8 MBps 40 MBps 200 MBps 400 MBps 800 MBps 2,000 MBps 4000 Mbps

发送连接计数不超过 40。 应用服务器的负担很小,因此建议的 Web 应用数也很小。

发送到大型组 单元 1 单元 2 单元 10 单元 50 单元 100 单元 200 单元 500 单元 1000
连接 1,000 2,000 10,000 50,000 100,000 200,000 500,000 1,000,000
应用服务器计数 1 1 2 2 2 4 10 20

注意

将每个应用服务器上的默认服务器连接数从 5 增加到 40,以避免与 Azure SignalR 服务建立的服务器连接数失衡。

客户端连接数、消息大小、消息发送速率、路由开销和 SKU 层会影响“发送到大型组”的整体性能。

发送到连接

在“发送到连接”用例中,当客户端与 Azure SignalR 服务建立连接时,每个客户端将调用一个特殊的中心来获取自身的连接 ID。 性能基准测试会收集所有连接 ID,将其随机组合,然后将其重新分配到用作发送目标的所有客户端。 在性能测试完成之前,客户端将不断地向目标连接发送消息。

Traffic for the send-to-client use case

“发送到连接”的路由开销类似于“发送到小型组”的开销。

随着连接数的增加,路由成本成为限制整体性能的关键因素。 值得注意的是,单元 20 标记服务达到路由瓶颈的阈值。 单元计数的进一步增加不会产生性能改进,除非有 Premium_P2(单位 >=100)的转变,这将增强路由功能。

下表列出了运行“发送到连接”基准测试多个轮次后的统计摘要。

发送到连接 单元 1 单元 2 单元 20 单元 50 单元 100 单元 200 单元 500 单元 1000
连接 1,000 2,000 20,000 50,000 100,000 200,000 500,000 1,000,000
每秒入站/出站消息数 1,000 2,000 20,000 20,000 20,000 40,000 100,000 200,000
入站/出站带宽 2 MBps 4 MBps 40 MBps 40 MBps 40 MBps 80 MBps 200 MBps 400 MBps

注意

尽管单元 20 后每秒入站/出站消息停滞,但更多连接的容量仍在增长。 在实际业务方案中,连接计数通常是构成瓶颈的连接计数,而不是其并发消息发送活动。 所有连接都与基准测试一样,以如此高频率主动发送消息并不常见。

此用例要求应用服务器端的负载较高。 请参阅下表中建议的应用服务器计数。

发送到连接 单元 1 单元 2 单元 10 单元 50 单元 100 单元 200 单元 500 单元 1000
连接 1,000 2,000 10,000 50,000 100,000 200,000 500,000 1,000,000
应用服务器计数 1 1 1 5 10 20 50 100

注意

应用服务器的客户端连接数、消息大小、消息发送速率、路由开销、SKU 层和 CPU/内存会影响“发送到连接”的整体性能。

ASP.NET SignalR

Azure SignalR 服务为 ASP.NET SignalR 提供相同的性能容量。

无服务器模式

客户端和 Azure SignalR 服务参与无服务器模式。 每个客户端代表一个连接。 客户端通过 REST API 将消息发送到另一个客户端,或者将消息广播到所有客户端。

通过 REST API 发送高密度消息不如使用 WebSocket 那么有效。 使用 REST API 需要每次都建立新的 HTTP 连接,这是在无服务器模式下产生的额外开销。

通过 REST API 广播

所有客户端与 Azure SignalR 服务建立 WebSocket 连接。 然后,某些客户端通过 REST API 开始广播。 (入站)消息发送全部通过 HTTP POST 进行,这不如 WebSocket 那样有效。

通过 REST API 广播 单元 1 单元 2 单元 10 单元 50 单元 100 单元 200 单元 500 单元 1000
连接 1,000 2,000 10,000 50,000 100,000 200,000 500,000 1,000,000
每秒入站消息数 2 2 2 2 2 2 2 2
每秒出站消息数 2,000 4,000 20,000 100,000 200,000 400,000 1,000,000 2,000,000
入站带宽 4 KBps 4 KBps 4 KBps 4 KBps 4 KBps 4 KBps 4 KBps 4 KBps
出站带宽 4 MBps 8 MBps 40 MBps 200 MBps 400 MBps 800 MBps 2,000 MBps 4,000 MBps

通过 REST API 发送到用户

基准测试将用户名分配到所有客户端,然后开始连接到 Azure SignalR 服务。 客户端与 Azure SignalR 服务建立 WebSocket 连接后,开始通过 HTTP POST 向其他客户端发送消息。

通过 REST API 发送到用户 单元 1 单元 2 单元 10 单元 50 单元 100 单元 200 单元 500 单元 1000
连接 1,000 2,000 10,000 50,000 100,000 200,000 500,000 1,000,000
每秒入站/出站消息数 200 400 2,000 10,000 20,000 40,000 100,000 200,000
入站/出站带宽 400 KBps 800 KBps 4 MBps 20 MBps 40 MBps 80 MBps 200 MBps 400 MBps

性能测试环境

针对上面列出的所有用例,我们已在 Azure 环境中展开了性能测试。 我们最多使用了 200 个客户端 VM 和 100 个应用服务器 VM。 下面是一些详细信息:

  • 客户端 VM 大小:StandardDS2V2(2 个 vCPU,7G 内存)

  • 应用服务器 VM 大小:StandardF4sV2(4 个 vCPU,8G 内存)

  • Azure SignalR SDK 服务器连接:15

性能工具

可以在 GitHub 上找到适用于 Azure SignalR 服务的性能工具。

后续步骤

本文概述了典型用例场景中的 Azure SignalR 服务性能。

若要详细了解该服务的内部组件和缩放,请参阅以下指南: