0

0

c# SignalR 高并发连接数优化 SignalR 性能瓶颈

畫卷琴夢

畫卷琴夢

发布时间:2026-01-18 12:50:37

|

444人浏览过

|

来源于php中文网

原创

SignalR 默认连接数上不去是因服务器配置和底层限制所致,需调优Kestrel连接数、HTTP/2、TLS及Hub广播机制,并优化客户端重连策略。

c# signalr 高并发连接数优化 signalr 性能瓶颈

SignalR 默认连接数为什么上不去?

SignalR 在 IIS 或 Kestrel 上默认受限于服务器配置和 ASP.NET Core 的底层限制,不是代码写得“高级”就能突破的。常见现象是:压测时连接数卡在几百就报 ConnectionRefusedTimeoutException 或客户端反复重连失败——这往往不是 SignalR 自身问题,而是 Windows 句柄、线程池、HTTP/2 流控或 TLS 握手堆积导致的。

  • IIS 默认 maxConcurrentRequestsPerCPU 是 5000,但实际受 applicationPool → queueLength(默认1000)和系统 MaxUserPort(默认5000)拖累
  • Kestrel 默认不启用 HTTP/2,而大量短连接 + 频繁重连会快速耗尽端口和 TLS session cache
  • HubLifetimeManager 默认用内存实现,高并发下广播操作易成瓶颈,尤其 Clients.All.SendAsync 会同步阻塞整个 Hub 线程

必须改的 Kestrel 和 ASP.NET Core 配置项

别只盯着 Hub 类写法,真正起效的是宿主层调优。以下配置需在 Program.cs 中显式设置:

var builder = WebApplication.CreateBuilder(args);

// 关键:Kestrel 连接与缓冲调优
builder.WebHost.ConfigureKestrel(serverOptions =>
{
    serverOptions.Limits.MaxConcurrentConnections = 100_000; // 显式放开
    serverOptions.Limits.MaxConcurrentUpgradedConnections = 100_000;
    serverOptions.Limits.MaxRequestBodySize = null; // 若不用上传
    serverOptions.Limits.MinRequestBodyDataRate = null; // 防止慢速攻击误杀
    serverOptions.Limits.KeepAliveTimeout = TimeSpan.FromMinutes(5);
});

// 关键:ASP.NET Core 主机级并发控制
builder.Services.Configure(options =>
{
    options.AutomaticAuthentication = false;
    options.AuthenticationDisplayName = "Windows Authentication";
});
builder.Services.Configure(options =>
{
    options.MaxConnections = 100_000;
    options.MaxRequestBodySize = null;
});

var app = builder.Build();

注意:MaxConcurrentConnections 必须设为 null 或足够大数值,否则 Kestrel 内部连接队列会直接拒绝新连接;MaxConcurrentUpgradedConnections 是 WebSocket 升级专用阈值,SignalR 默认走 WebSocket,此项常被忽略。

Hub 层避免广播阻塞的实操方式

高频消息场景下,Clients.All.SendAsync 是性能杀手——它会把所有连接序列化一次、再逐个 await 发送,中间任意一个慢连接都会拖垮整批。替代方案不是“优化序列化”,而是绕过同步广播模型:

Replit Agent
Replit Agent

Replit最新推出的AI编程工具,可以帮助用户从零开始自动构建应用程序。

下载
  • Clients.AllExcept(...).SendAsync 减少目标集,但本质未解耦
  • 改用 ITransportHeartbeat + 自定义 IHubLifetimeManager 实现异步批量投递(推荐)
  • 更轻量做法:在 Hub 外启动独立后台服务(BackgroundService),将消息入队(如 Channel),由消费者线程池分片推送
  • 禁用自动 JSON 序列化缓存:AddJsonProtocol(opt => opt.PayloadSerializerOptions.WriteIndented = false),减小 GC 压力

示例:用 Channel 实现非阻塞广播

public class BroadcastService : BackgroundService
{
    private readonly ChannelReader _reader;
    private readonly IHubContext _hubContext;

    public BroadcastService(Channel channel, IHubContext hubContext)
    {
        _reader = channel.Reader;
        _hubContext = hubContext;
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        await foreach (var msg in _reader.ReadAllAsync(stoppingToken))
        {
            // 不 await SendAsync,用 Fire-and-forget 避免阻塞
            _ = _hubContext.Clients.All.SendAsync("ReceiveMessage", msg, CancellationToken.None);
        }
    }
}

客户端连接复用与重连策略关键点

服务端再强,客户端乱建连也会拖垮整体。SignalR JS 客户端默认重试逻辑极易引发雪崩:

  • 禁用默认自动重连:new HubConnectionBuilder().withUrl(...).configureLogging(LogLevel.None).build(),手动控制重连间隔
  • 连接前检查 navigator.onLine,避免离线时疯狂重试
  • 服务端返回 429 时,客户端应退避重连(如指数退避),而非立即重试
  • Web Worker 中运行 SignalR 连接,防止 UI 线程阻塞影响心跳上报
  • .NET 客户端务必设置 HubConnectionBuilder.WithAutomaticReconnect() 并传入自定义策略,避免 RetryExponential 默认最大间隔仅 30 秒

最容易被忽略的是:WebSocket 连接本身不感知网络闪断,依赖心跳超时(默认 30 秒)才发现断连。生产环境建议将 KeepAliveInterval 设为 10–15 秒,ClientTimeoutInterval 设为 30–45 秒,并在 OnCloseAsync 中清理资源。

相关文章

数码产品性能查询
数码产品性能查询

该软件包括了市面上所有手机CPU,手机跑分情况,电脑CPU,电脑产品信息等等,方便需要大家查阅数码产品最新情况,了解产品特性,能够进行对比选择最具性价比的商品。

下载

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
json数据格式
json数据格式

JSON是一种轻量级的数据交换格式。本专题为大家带来json数据格式相关文章,帮助大家解决问题。

412

2023.08.07

json是什么
json是什么

JSON是一种轻量级的数据交换格式,具有简洁、易读、跨平台和语言的特点,JSON数据是通过键值对的方式进行组织,其中键是字符串,值可以是字符串、数值、布尔值、数组、对象或者null,在Web开发、数据交换和配置文件等方面得到广泛应用。本专题为大家提供json相关的文章、下载、课程内容,供大家免费下载体验。

533

2023.08.23

jquery怎么操作json
jquery怎么操作json

操作的方法有:1、“$.parseJSON(jsonString)”2、“$.getJSON(url, data, success)”;3、“$.each(obj, callback)”;4、“$.ajax()”。更多jquery怎么操作json的详细内容,可以访问本专题下面的文章。

309

2023.10.13

go语言处理json数据方法
go语言处理json数据方法

本专题整合了go语言中处理json数据方法,阅读专题下面的文章了解更多详细内容。

74

2025.09.10

c语言中null和NULL的区别
c语言中null和NULL的区别

c语言中null和NULL的区别是:null是C语言中的一个宏定义,通常用来表示一个空指针,可以用于初始化指针变量,或者在条件语句中判断指针是否为空;NULL是C语言中的一个预定义常量,通常用来表示一个空值,用于表示一个空的指针、空的指针数组或者空的结构体指针。

231

2023.09.22

java中null的用法
java中null的用法

在Java中,null表示一个引用类型的变量不指向任何对象。可以将null赋值给任何引用类型的变量,包括类、接口、数组、字符串等。想了解更多null的相关内容,可以阅读本专题下面的文章。

436

2024.03.01

session失效的原因
session失效的原因

session失效的原因有会话超时、会话数量限制、会话完整性检查、服务器重启、浏览器或设备问题等等。详细介绍:1、会话超时:服务器为Session设置了一个默认的超时时间,当用户在一段时间内没有与服务器交互时,Session将自动失效;2、会话数量限制:服务器为每个用户的Session数量设置了一个限制,当用户创建的Session数量超过这个限制时,最新的会覆盖最早的等等。

308

2023.10.17

session失效解决方法
session失效解决方法

session失效通常是由于 session 的生存时间过期或者服务器关闭导致的。其解决办法:1、延长session的生存时间;2、使用持久化存储;3、使用cookie;4、异步更新session;5、使用会话管理中间件。

740

2023.10.18

高德地图升级方法汇总
高德地图升级方法汇总

本专题整合了高德地图升级相关教程,阅读专题下面的文章了解更多详细内容。

43

2026.01.16

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
WEB前端教程【HTML5+CSS3+JS】
WEB前端教程【HTML5+CSS3+JS】

共101课时 | 8.3万人学习

JS进阶与BootStrap学习
JS进阶与BootStrap学习

共39课时 | 3.2万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号