return; } else { <">
96SEO 2026-06-05 22:38 14
这次组件并发导致类缓存击穿,如何排查与解决?说实话,一开始我也被这个问题整懵了哈哈。
先kankan代码// 组件部分@{ if { <MudProgressCircular Indeterminate="true" Color="Color.Primary" Size="Size.Large" Class="m-" /> return; } else { <MudNavMenu Color="Color.Primary"> @{ foreach { node.requirePermissionCount += ; <RenderMenuItem Node="node" /> } } </MudNavMenu> }}// 逻辑部分@code{ protected override async Task OnInitializedAsync { ConsoleHelper.WriteLine; var result = await menuRepo.GetAvaliableMenus; if { Snackbar.Add; return; } menuTree = result.Value; isLoaded = true; }}
递归的RenderMenuItem组件核心代码就不贴了害,反正就是一堆逻辑。

虽然有点啰嗦,但我还是想描述下现象和整个问题我的复现链路。
随着菜单数量增多,Zui近明显感觉在切换菜单时系统开始变慢。打开控制台日志一kan,发现了一个比较严重的问题,加载菜单时出现了明显的并发回源。
public async Task<Result<List<ManagePermissionResponseDto>> GetAllPermissionsAsync{ try { string cacheKey = $"{CacheKeys.DecPermissionPrefix}_all"; var cacheValues = await _easyCachingProvider.SMembersAsync<ManagePermissionResponseDto>; if { ConsoleHelper.WriteLine; return Result<List<ManagePermissionResponseDto>.Success; } // 缓存未命中,使用分布式锁防止缓存击穿
// ...略
简单说一下上面这段代码还没有经过整理,缓存策略部分的比重比业务代码要多得多,其核心逻辑如下
问题根源问题的根源就在这两个组件代码里简单来说RenderMenuItem组件是多个实例,而每个实例的生命周期函数是并发执行的,引发了并发竞争,同时回源查库,击穿缓存层。
咱就是说这属于组件生命周期函数利用不当造成的慢性自杀行为,和传统的“缓存击穿”现象还是有点区别,但结果是殊途同归。
解决方案知道了问题的根源,就Ke以对症下药的解决问题了这里其实主要涉及到2个地方,一个是优化我们的组件加载逻辑,这也是主要问题。
分析完问题链路,我这边的处理方法是把权限加载的流程从RenderMenuItem提取到NavMenu中统一执行,确保只加载一次不会随着每个RenderMenuItem的实例化而重新加载。
protected override async Task OnInitializedAsync{ // 先加载菜单 var result = await menuRepo.GetAvaliableMenus; if { Snackbar.Add; return; } menuTree = result.Value; // 统一加载权限数据,防止多个RenderMenuItem并发加载导致缓存击穿 if { ConsoleHelper.WriteLine; var permissionResult = await permissionProvider.GetAllPermissionsAsync; if { StateService.AllPermissions = permissionResult.Value; } } isLoaded = true;}
修改RenderMenuItem,
移除不必要的依赖注入
逻辑变的简单,只负责读取StateService.AllPermissions进行权限检查,不再加载权限数据,
使用OnInitializedAsync替代OnAfterRenderAsync,这里我一开始把实现写在OnAfterRenderAsync里是因为初始版本的组件里涉及到了js交互,而blazor里与js的交互逻辑是要在OnAfterRenderAsync里执行的,不Neng放在预渲染阶段。
@code { public MenuTreeNode Node { get; set; } protected override async Task OnInitializedAsync {
// 权限数据Yi在NavMenu中统一加载到StateService.AllPermissions
// 这里只负责读取并检查当前节点的权限
if
{
var permisstion = StateService.AllPermissions?
.Where)
.FirstOrDefault;
if )
{
Node.hasPermission = true;
}
else
{
Node.hasPermission = false;
}
}
else
{
Node.hasPermission = true;
}
}
}
这样修改后在kan日志,菜单加载的时候,就只回源一次后续在检查权限,就不再回库里查询了从页面执行效果速度也提升了许多
这次的标题我虽然说的是缓存击穿问题,但其本质还是由于组件并发,以及缓存层保护措施不够引起的和“缓存击穿”hen像的一个问题。这也提醒我们,展示层或者说UI层,绝不是简单的完成渲染工作就完事了还是要精心设计,我这里是Blazor,在其他前端场景也是一样的,组件一多,Ru果涉及不当,明明一次请求就Ke以完成的事情,hen可Neng会被放大N倍,造成严重的并发失控问题。
拜拜,下次见。
另外全局数据还是要Zuo好入口统一,像权限这种数据,不应该在子组件里单独加载,而是应该提取到入口,统一处理。而加载权限的后端方法,仅仅用上缓存也是不够的,还应该考虑并发访问,以及失效瞬间的回源保护等。毕竟后端服务是兜底的,高可用设计是首要条件。
作为专业的SEO优化服务提供商,我们致力于通过科学、系统的搜索引擎优化策略,帮助企业在百度、Google等搜索引擎中获得更高的排名和流量。我们的服务涵盖网站结构优化、内容优化、技术SEO和链接建设等多个维度。
| 服务项目 | 基础套餐 | 标准套餐 | 高级定制 |
|---|---|---|---|
| 关键词优化数量 | 10-20个核心词 | 30-50个核心词+长尾词 | 80-150个全方位覆盖 |
| 内容优化 | 基础页面优化 | 全站内容优化+每月5篇原创 | 个性化内容策略+每月15篇原创 |
| 技术SEO | 基本技术检查 | 全面技术优化+移动适配 | 深度技术重构+性能优化 |
| 外链建设 | 每月5-10条 | 每月20-30条高质量外链 | 每月50+条多渠道外链 |
| 数据报告 | 月度基础报告 | 双周详细报告+分析 | 每周深度报告+策略调整 |
| 效果保障 | 3-6个月见效 | 2-4个月见效 | 1-3个月快速见效 |
我们的SEO优化服务遵循科学严谨的流程,确保每一步都基于数据分析和行业最佳实践:
全面检测网站技术问题、内容质量、竞争对手情况,制定个性化优化方案。
基于用户搜索意图和商业目标,制定全面的关键词矩阵和布局策略。
解决网站技术问题,优化网站结构,提升页面速度和移动端体验。
创作高质量原创内容,优化现有页面,建立内容更新机制。
获取高质量外部链接,建立品牌在线影响力,提升网站权威度。
持续监控排名、流量和转化数据,根据效果调整优化策略。
基于我们服务的客户数据统计,平均优化效果如下:
我们坚信,真正的SEO优化不仅仅是追求排名,而是通过提供优质内容、优化用户体验、建立网站权威,最终实现可持续的业务增长。我们的目标是与客户建立长期合作关系,共同成长。
Demand feedback