0

0

c# Blazor Server 的并发模型和性能问题

畫卷琴夢

畫卷琴夢

发布时间:2026-01-12 10:07:43

|

824人浏览过

|

来源于php中文网

原创

Blazor Server 采用单连接顺序执行模型,同一用户交互复用组件实例并串行处理UI更新,多用户则独立并发;性能瓶颈主因是单次操作耗时过长、内存泄漏、SignalR配置不当及线程池饥饿。

c# blazor server 的并发模型和性能问题

Blazor Server 的连接模型决定了并发行为

Blazor Server 不是每个请求启动新线程或新实例,而是为每个客户端连接维持一个长期 SignalR 连接,并在该连接上下文中复用 ComponentBase 实例。这意味着:同一用户多次交互(如连续点击按钮)通常复用同一个组件实例;不同用户则对应不同连接和独立的组件生命周期。

关键点在于:RenderTreeRenderer 会按连接序列化地处理该连接上的所有 UI 更新(包括事件回调、StateHasChanged() 触发的重渲染),所以单个连接内不存在“并发渲染”——它是严格顺序执行的。

  • 多个用户同时操作 → 多个独立连接 → 各自顺序执行,互不阻塞
  • 同一用户快速连点两次 → 两个事件回调排队进入该连接的消息队列 → 第二个回调必须等第一个完全返回(含异步 await 完成)后才开始
  • async void 在事件处理中是危险的,会导致框架失去等待时机,可能引发状态错乱或重复提交

常见性能瓶颈:UI 渲染卡顿与服务器资源耗尽

卡顿通常不是因为“并发太高”,而是单次操作耗时过长,阻塞了整个连接的消息循环。典型场景包括:同步 I/O(如 File.ReadAllText())、未限制的数据库查询、复杂对象深克隆、或在 OnInitializedAsync() 中执行未分页的全表加载。

更隐蔽的问题是内存泄漏:组件持有大对象(如 byte[]、缓存的 DataTable)且未在 Dispose() 中清理,随着连接数增长,服务器内存持续上涨。

  • 避免在组件中缓存未受控的大型数据结构;改用服务层缓存 + 弱引用或 TTL 控制
  • 所有异步操作必须使用 async Task,禁止 async void
  • 对耗时操作加超时控制,例如:
    await httpClient.GetAsync("api/data", cancellationToken).WaitAsync(TimeSpan.FromSeconds(5));
  • 启用 ServerSideCaching 仅适用于静态资源;Blazor Server 本身不缓存组件渲染结果

SignalR 配置直接影响并发承载能力

默认 SignalR 配置在高连接数下容易成为瓶颈。核心参数不是 CPU 或内存,而是 SignalR 的并发连接数限制和消息缓冲区大小。IIS、Kestrel 和 SignalR 自身都有独立的连接/吞吐限制。

佳蓝在线销售系统(创业版) 佳蓝在线销售
佳蓝在线销售系统(创业版) 佳蓝在线销售

1、对ASP内核代码进行DLL封装,从而大大提高了用户的访问速度和安全性;2、采用后台生成HTML网页的格式,使程序访问速度得到进一步的提升;3、用户可发展下级会员并在下级购买商品时获得差额利润;4、全新模板选择功能;5、后台增加磁盘绑定功能;6、后台增加库存查询功能;7、后台增加财务统计功能;8、后台面值类型批量设定;9、后台财务曲线报表显示;10、完善订单功能;11、对所有传输的字符串进行安全

下载

例如,Kestrel 默认 MaxConcurrentConnections 为 null(无硬限),但 SignalR 的 MaximumReceiveMessageSize 默认仅 32 KB,上传大参数或 Base64 图片时会直接断连并抛出 BadHttpRequestException: Request body too large

  • Program.cs 中显式配置 SignalR 选项:
    builder.Services.AddSignalR(hubOptions =>
    {
        hubOptions.MaximumReceiveMessageSize = 1024 * 1024; // 1 MB
    });
  • Kestrel 需单独配置最大连接数和请求体大小:
    builder.WebHost.ConfigureKestrel(serverOptions =>
    {
        serverOptions.Limits.MaxConcurrentConnections = 10000;
        serverOptions.Limits.MaxRequestBodySize = 10 * 1024 * 1024;
    });
  • IIS 用户需检查 web.config 中的 requestLimitsmaxAllowedContentLength

诊断真实瓶颈:别只看 CPU

CPU 占用低但响应慢?大概率是线程池饥饿或 I/O 等待堆积。Blazor Server 的事件处理依赖 .NET 线程池调度,如果大量请求触发长时间同步阻塞(如 Thread.Sleep()Task.Run(() => { /* CPU-bound */ }).Result),会迅速耗尽线程池,导致新消息无法及时调度。

dotnet-counters 监控关键指标:System.Runtime | ThreadPool Queue Length(持续 > 10 表示调度积压)、Microsoft.AspNetCore.Hosting | Requests In Progress(结合连接数判断是否某连接长期占用)。

  • 不要用 .Result.Wait(),它们会阻塞线程池线程
  • CPU 密集型工作必须用 Task.Run() 显式卸载,但要注意避免频繁创建短任务造成调度开销
  • 生产环境务必启用 Application Insights 或 OpenTelemetry,记录 NavigationManager.NavigateTo() 延迟、组件生命周期耗时、SignalR 消息往返时间

实际部署中,最常被忽略的是 SignalR 心跳超时与反向代理(如 Nginx、Azure Front Door)的空闲连接关闭策略不一致,导致连接静默断开却未触发 OnDisconnectedAsync,用户界面卡死无响应。这个链路层问题比代码逻辑更容易让整个并发模型失效。

相关文章

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

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

下载

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

相关专题

更多
nginx 重启
nginx 重启

nginx重启对于网站的运维来说是非常重要的,根据不同的需求,可以选择简单重启、平滑重启或定时重启等方式。本专题为大家提供nginx重启的相关的文章、下载、课程内容,供大家免费下载体验。

229

2023.07.27

nginx 配置详解
nginx 配置详解

Nginx的配置是指设置和调整Nginx服务器的行为和功能的过程。通过配置文件,可以定义虚拟主机、HTTP请求处理、反向代理、缓存和负载均衡等功能。Nginx的配置语法简洁而强大,允许管理员根据自己的需要进行灵活的调整。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

495

2023.08.04

nginx配置详解
nginx配置详解

NGINX与其他服务类似,因为它具有以特定格式编写的基于文本的配置文件。本专题为大家提供nginx配置相关的文章,大家可以免费学习。

498

2023.08.04

tomcat和nginx有哪些区别
tomcat和nginx有哪些区别

tomcat和nginx的区别:1、应用领域;2、性能;3、功能;4、配置;5、安全性;6、扩展性;7、部署复杂性;8、社区支持;9、成本;10、日志管理。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

227

2024.02.23

nginx报404怎么解决
nginx报404怎么解决

当访问 nginx 网页服务器时遇到 404 错误,表明服务器无法找到请求资源,可以通过以下步骤解决:1. 检查文件是否存在且路径正确;2. 检查文件权限并更改为 644 或 755;3. 检查 nginx 配置,确保根目录设置正确、没有冲突配置等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

332

2024.07.09

Nginx报404错误解决方法
Nginx报404错误解决方法

解决方法:只需要加上这段配置:try_files $uri $uri/ /index.html;即可。想了解更多Nginx的相关内容,可以阅读本专题下面的文章。

3507

2024.08.07

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的相关内容,可以阅读本专题下面的文章。

435

2024.03.01

Java 项目构建与依赖管理(Maven / Gradle)
Java 项目构建与依赖管理(Maven / Gradle)

本专题系统讲解 Java 项目构建与依赖管理的完整体系,重点覆盖 Maven 与 Gradle 的核心概念、项目生命周期、依赖冲突解决、多模块项目管理、构建加速与版本发布规范。通过真实项目结构示例,帮助学习者掌握 从零搭建、维护到发布 Java 工程的标准化流程,提升在实际团队开发中的工程能力与协作效率。

3

2026.01.12

热门下载

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

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
进程与SOCKET
进程与SOCKET

共6课时 | 0.3万人学习

nginx浅谈
nginx浅谈

共15课时 | 0.8万人学习

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

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