SignalR 性能

作者 :Patrick Fletcher

警告

本文档不适用于最新版本的 SignalR。 查看 ASP.NET Core SignalR

本主题介绍如何在 SignalR 应用程序中设计、度量和改进性能。

本主题中使用的软件版本

本主题的早期版本

有关 SignalR 早期版本的信息,请参阅 SignalR 旧版本

问题和评论

请留下反馈,说明你如何喜欢本教程,以及我们可以在页面底部的评论中改进的内容。 如果你有与本教程不直接相关的问题,可以将其发布到 ASP.NET SignalR 论坛StackOverflow.com

有关 SignalR 性能和缩放的最新演示文稿,请参阅 使用 ASP.NET SignalR 缩放实时 Web

本主题包含以下各节:

设计注意事项

本部分介绍可在 SignalR 应用程序设计期间实现的模式,以确保性能不会因生成不必要的网络流量而受阻。

限制消息频率

即使在以高频率 (发送消息的应用程序(如实时游戏应用程序) )中,大多数应用程序也不需要每秒发送多条消息。 为了减少每个客户端生成的流量,可以实现消息循环,使队列和发送消息的频率不超过固定速率 (也就是说,如果在该时间间隔内有消息要发送) ,则每秒将发送一定数量的消息。 有关将消息限制为特定速率的示例应用程序, (来自客户端和服务器) ,请参阅 使用 SignalR 的高速实时

减小消息大小

可以通过减少序列化对象的大小来减小 SignalR 消息的大小。 在服务器代码中,如果要发送包含不需要传输的属性的对象,请使用 特性阻止这些属性进行序列化 JsonIgnore 。 属性的名称也存储在消息中;可以使用 特性缩短 JsonProperty 属性的名称。 以下代码示例演示如何排除发送到客户端的属性,以及如何缩短属性名称:

.NET 服务器代码,用于演示 JsonIgnore 属性以排除发送到客户端的数据,以及用于减小消息大小的 JsonProperty 属性

using Newtonsoft.Json; 
using System; 
public class ShapeModel
{
    [JsonProperty("l")]
    public double Left { get; set; }
    [JsonProperty("t")]
    public double Top { get; set; }
    // We don't want the client to get the "LastUpdatedBy" property
    [JsonIgnore]
    public string LastUpdatedBy { get; set; }
}

为了在客户端代码中保持可读性/可维护性,可以在收到消息后将缩写的属性名称重新映射到人类友好名称。 以下代码示例演示了一种将缩短的名称重新映射到较长名称的可能方法,方法是定义消息协定 (映射) ,并使用 reMap 函数将协定应用于优化的消息类:

将缩短的属性名称重新映射到人类可读名称的客户端 JavaScript 代码

function reMap(smallObject, contract) {
    var largeObject = {};
    for (var smallProperty in contract) {
        largeObject[contract[smallProperty]] = smallObject[smallProperty];
    }
    return largeObject;
}
var shapeModelContract = {
    l: "left",
    t: "top"
};
myHub.client.setShape = function (shapeModelSmall) {
    var shapeModel = reMap(shapeModelSmall, shapeModelContract);
    // shapeModelSmall has "l" and "t" properties  but after remapping
    // shapeModel now has "left" and "top" properties
};

还可以使用同一方法在从客户端到服务器的消息中缩短名称。

减少内存占用 (也就是说,用于消息对象的消息) 的内存量也可以提高性能。 例如,如果不需要 的全范围 intshort 则可以改用 或 byte

由于消息存储在消息总线中的服务器内存中,因此减小消息的大小也可以解决服务器内存问题。

优化 SignalR 服务器以提升性能

以下配置设置可用于优化服务器,以提高 SignalR 应用程序中的性能。 有关如何在 ASP.NET 应用程序中提高性能的一般信息,请参阅 提高 ASP.NET 性能

SignalR 配置设置

  • DefaultMessageBufferSize:默认情况下,SignalR 为每个连接在每个中心保留 1000 条消息。 如果使用大型消息,则可能会导致内存问题,可以通过减少此值来缓解这些问题。 可以在 ASP.NET 应用程序的事件处理程序中或在Configuration自承载应用程序中 OWIN 启动类的 方法中设置Application_Start此设置。 以下示例演示了如何减少此值以减少应用程序的内存占用量,以减少使用的服务器内存量:

    Startup.cs 中的 .NET 服务器代码,用于减小默认消息缓冲区大小

    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            // Any connection or hub wire up and configuration should go here
            GlobalHost.Configuration.DefaultMessageBufferSize = 500;
            app.MapSignalR();
        }
    }
    

IIS 配置设置

  • 每个应用程序的最大并发请求数:增加并发 IIS 请求数将增加可用于处理请求的服务器资源。 默认值为 5000;若要增加此设置,请在提升的命令提示符下执行以下命令:

    cd %windir%\System32\inetsrv\
    appcmd.exe set config /section:system.webserver/serverRuntime 
            /appConcurrentRequestLimit:10000
    
  • ApplicationPool QueueLength:这是应用程序池Http.sys队列的最大请求数。 当队列已满时,新请求会收到 503“服务不可用”响应。 默认值为 1000。

    缩短托管应用程序的应用程序池中辅助角色进程的队列长度将节省内存资源。 有关详细信息,请参阅 管理、优化和配置应用程序池

ASP.NET 配置设置

本部分包括可在 文件中设置的配置 aspnet.config 设置。 此文件位于以下两个位置之一,具体取决于平台:

  • %windir%\Microsoft.NET\Framework\v4.0.30319\aspnet.config
  • %windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet.config

可提高 SignalR 性能 ASP.NET 设置包括:

  • 每个 CPU 的最大并发请求数:增加此设置可以缓解性能瓶颈。 若要增加此设置,请将以下配置设置添加到 aspnet.config 文件:

    <?xml version="1.0" encoding="UTF-8" ?>
    <configuration>
        <system.web>
            <applicationPool maxConcurrentRequestsPerCPU="20000" />
        </system.web>
    </configuration>
    
  • 请求队列限制:当连接总数超过设置 maxConcurrentRequestsPerCPU 时,ASP.NET 将使用队列开始限制请求。 若要增加队列的大小,可以增加 requestQueueLimit 设置。 为此,请将以下配置设置添加到 processModel (中的 config/machine.config 节点,而不是 aspnet.config) :

    <processModel autoConfig="false" requestQueueLimit="250000" />
    

性能问题故障排除

本部分介绍在应用程序中查找性能瓶颈的方法。

验证是否正在使用 WebSocket

虽然 SignalR 可以使用各种传输在客户端和服务器之间进行通信,但 WebSocket 具有显著的性能优势,在客户端和服务器支持时应使用。 若要确定客户端和服务器是否满足 WebSocket 的要求,请参阅 传输和回退。 若要确定应用程序中使用的传输,可以使用浏览器开发人员工具,并检查日志以查看用于连接的传输。 有关在 Internet Explorer 和 Chrome 中使用浏览器开发工具的信息,请参阅 传输和回退

使用 SignalR 性能计数器

本部分介绍如何启用和使用包中的 Microsoft.AspNet.SignalR.Utils SignalR 性能计数器。

安装signalr.exe

可以使用名为 SignalR.exe 的实用工具将性能计数器添加到服务器。 若要安装此实用工具,请执行以下步骤:

  1. 在 Visual Studio 中,选择“工具>”“NuGet 包管理器>”“管理解决方案的 NuGet 包

  2. 搜索 signalr.utils,然后选择“安装”。

    显示已选择“Microsoft A S P 点 NET Signal R Utilities”的屏幕截图。

  3. 接受用于安装包的许可协议。

  4. SignalR.exe将安装到 <project folder>/packages/Microsoft.AspNet.SignalR.Utils.<version>/tools

使用 SignalR.exe 安装性能计数器

若要安装 SignalR 性能计数器,请使用以下参数在提升的命令提示符中运行SignalR.exe:

SignalR.exe ipc

若要删除 SignalR 性能计数器,请使用以下参数在提升的命令提示符中运行SignalR.exe:

SignalR.exe upc

SignalR 性能计数器

实用工具包安装以下性能计数器。 “总计”计数器测量自上次应用程序池或服务器重启以来的事件数。

连接指标

以下指标衡量发生的连接生存期事件。 有关详细信息,请参阅 了解和处理连接生存期事件

  • 连接连接
  • 连接已重新连接
  • 连接已断开连接
  • 当前连接数

消息指标

以下指标衡量 SignalR 生成的消息流量。

  • 已接收的连接消息总数
  • 已发送的连接消息总数
  • 接收的连接消息数/秒
  • 已发送的连接消息数/秒

消息总线指标

以下指标测量通过内部 SignalR 消息总线(所有传入和传出 SignalR 消息放置的队列)的流量。 发送或广播时,消息为 “已发布 ”。 此上下文中的 订阅服务器 是消息总线上的订阅;这应等于客户端数加上服务器本身。 分配的辅助角色是一个组件,用于将数据发送到活动连接;忙碌的辅助角色是主动发送消息的辅助角色。

  • 消息总线消息已接收总数
  • 收到的消息总线消息数/秒
  • 消息总线消息已发布总数
  • 已发布的消息总线消息数/秒
  • 消息总线订阅服务器当前
  • 消息总线订阅者总数
  • 消息总线订阅服务器数/秒
  • 消息总线分配的辅助角色
  • 消息总线忙碌辅助角色
  • 消息总线当前主题

错误指标

以下指标衡量 SignalR 消息流量生成的错误。 无法解决中心或中心方法时,会发生中心解析错误。 中心调用 错误是在调用中心方法时引发的异常。 传输 错误是在 HTTP 请求或响应期间引发的连接错误。

  • 错误:全部总计
  • 错误:全部/秒
  • 错误:中心解析总数
  • 错误:中心解析/秒
  • 错误:中心调用总数
  • 错误:中心调用/秒
  • 错误:传输总计
  • 错误:传输/秒

横向扩展指标

以下指标衡量扩展提供程序生成的流量和错误。 此上下文中的是扩展提供程序使用的缩放单元;如果使用SQL Server,则为表;如果使用服务总线,则为主题;如果使用 Redis,则为订阅。 每个流确保有序的读取和写入操作;单个流是潜在的规模瓶颈,因此可以增加流的数量以帮助减少该瓶颈。 如果使用多个流,SignalR 将自动跨这些流分配 (分片) 消息,确保从任何给定连接发送的消息按顺序发送。

MaxQueueLength 设置控制 SignalR 维护的扩展发送队列的长度。 将其设置为大于 0 的值会将发送队列中的所有消息一次一个发送到配置的消息背板。 如果队列的大小超过配置的长度,则对 send 的后续调用将立即失败,并显示 InvalidOperationException ,直到队列中的消息数再次小于该设置。 默认禁用排队,因为实现的背板通常具有自己的队列或流控制。 在SQL Server的情况下,连接池可有效限制任何时间正在进行的发送数。

默认情况下,只有一个流用于 SQL Server 和 Redis,五个流用于服务总线,队列已禁用,但可以通过SQL Server和服务总线上的配置更改这些设置:

用于为SQL Server背板配置表计数和队列长度的 .NET 服务器代码

var connectionString = "(your connection string)";
var config = new SqlScaleoutConfiguration(connectionString) { 
TableCount = 3,
MaxQueueLength = 50 };
GlobalHost.DependencyResolver.UseSqlServer(config);

用于为服务总线背板配置主题计数和队列长度的 .NET 服务器代码

string connectionString = "(your connection string)";
var config = new ServiceBusScaleoutConfiguration(connectionString, "YourAppName") { 
TopicCount = 3,
MaxQueueLength = 50 };
GlobalHost.DependencyResolver.UseServiceBus(config);

缓冲流是已进入错误状态的流;当流处于故障状态时,发送到底板的所有消息将立即失败,直到流不再出错。 发送队列长度是已发布但尚未发送的消息数。

  • 已接收的横向扩展消息总线消息数/秒
  • 横向扩展流总数
  • 横向扩展流打开
  • 横向扩展流缓冲
  • 横向扩展错误总数
  • Scaleout Errors/Sec
  • 扩展发送队列长度

有关这些计数器测量的内容的详细信息,请参阅带有Azure 服务总线的 SignalR Scaleout

使用其他性能计数器

以下性能计数器还可用于监视应用程序的性能。

内存

  • w3wp) 的所有堆 (中的 .NET CLR 内存\# 字节数

ASP.NET

  • ASP.NET\Requests Current
  • ASP.NET\Queued
  • ASP.NET\Rejected

CPU

  • 处理器信息\处理器时间

TCP/IP

  • TCPv6/已建立的连接
  • TCPv4/已建立连接

Web 服务

  • Web 服务\当前连接
  • Web 服务\最大连接数

线程处理

  • 当前逻辑线程的 .NET CLR 锁和线程\#
  • 当前物理线程的 .NET CLR 锁和线程数\#

其他资源

有关 ASP.NET 性能监视和优化的详细信息,请参阅以下主题: