当前位置: 首页 > news >正文

C# --- 本地缓存失效形成缓存击穿触发限流

C# --- 本地缓存失效形成缓存击穿触发限流

  • 问题描述
  • 解决方案
    • 缓存Request Task
    • 加入信号量限制请求数量

问题描述

  • 某一接口前端会偶发返回400.
  • 通过检查日志发现是后端服务调用外部Api时,因为缓存失效导致并发请求数量过多 (QPS接近300), 外部Api返回429导致的.
  • 代码大致如下

private readonly MemoryCache _timeZoneCache = new(new MemoryCacheOptions())private MemeoryCacheEntryOptions EntryOption => new MemeoryCacheEntryOption().SetAbsoluteExpiraton(DataTimeOffset.Utc.Now.AddMinutes(1))public async Task Process()
{var elements = await GetAllElementsAsync();//如果elements数量过多,这里会并发发送大量请求var tasks = elements.Select(element -> GetTimeZoneAsync(element)).ToList();if (tasks.Any()){await Task.WhenAll(tasks)}}private async Task<string> GetTimeZoneAsync(Element element){if (_timeZoneCache.TryGetValue(element.QueryParameter, out string timeZone){return timeZone}//send reuqets to external Apivar reponse = await SendTimeZoneRequestAsync(element)//parse http responsevar result = ParseHttpResponse(response)//set cache_timeZoneCache.Add(element.QueryParameter, result)}
  • 当缓存失效时,如果elements的数量过多(比如300个),那么上面的代码会并发发送300个请求. 导致触发外部服务的限流,返回429

解决方案

缓存Request Task

  • 经过调查发现,被发送出去的大量请求其实很多是重复的请求
  • 那么可以利用C#的Task机制,加入一个新的缓存,这个缓存用来缓存发送出去的Request Task,避免重复发送请求

private readonly MemoryCache _timeZoneCache = new(new MemoryCacheOptions())private MemeoryCacheEntryOptions EntryOption => new MemeoryCacheEntryOption().SetAbsoluteExpiraton(DataTimeOffset.Utc.Now.AddMinutes(1))public async Task Process()
{var elements = await GetAllElementsAsync();//如果elements数量过多,这里会并发发送大量请求var tasks = elements.Select(element -> GetTimeZoneAsync(element)).ToList();if (tasks.Any()){await Task.WhenAll(tasks)}}private async Task<string> GetTimeZoneAsync(Element element){if (_timeZoneCache.TryGetValue(element.QueryParameter, out string timeZone){return timeZone}var response = await GetTimeZoneRequestTaskAsync(element);//parse http responsevar result = ParseHttpResponse(response)//set cache_timeZoneCache.Add(element.QueryParameter, result)}private async Task<HttpResponse> GetTimeZoneRequestTaskAsync(Element element){if (_timeZoneRequestCache.TryGetValue(element.QueryParameter, out string timeZoneRequest){return timeZoneRequest}//do not await herevar request = SendTimeZoneRequestAsync(element)//cache the request_timeZoneRequestCache(element.QueryParameter, request);return request;}

加入信号量限制请求数量

  • 如果都是不同的请求,那么可以使用信号量控制并发发送请求的数量
    参见 https://blog.csdn.net/weixin_38803409/article/details/135353000
http://www.dtcms.com/a/315737.html

相关文章:

  • 【面向对象】面向对象七大原则
  • 【乐企板式文件生成工程】关于乐企板式文件(PDF/OFD/XML)生成工程介绍
  • [2401MT-B] 面积比较
  • 翻译的本质:人工翻译vs机器翻译的核心差异与互补性
  • Starrocks中的 Query Profile以及explain analyze及trace命令中的区别
  • MySQL 中 VARCHAR 和 TEXT 的区别
  • 智慧酒店:科技赋能下的未来住宿新体验
  • Spring-rabbit使用实战六
  • 国产三防平板电脑是什么?三防平板推荐
  • Spark内核调度
  • RTC实时时钟RX8900SA国产替代FRTC8900S
  • 使用maven-shade-plugin解决es跨版本冲突
  • 微信小程序功能实现:页面导航与跳转
  • jenkins插件Active Choices的使用通过参数动态控制多选参数的选项
  • LHA6958D是一款代替AD7606的芯片
  • 【前端】网站favicon图标制作
  • MyBatisPlus查询数据库中所有表的数据(AI)
  • 使标签垂直水平居中的多种方法
  • 自动驾驶控制算法——MPC控制算法
  • 数据结构 实现单链表
  • Vue3核心语法进阶(Props)
  • C语言:选择排序算法深度剖析!
  • nodejs 编码初体验
  • JAVA无人共享球杆柜系统球杆柜租赁系统源码支持微信小程序
  • 嵌入式硬件中运放的基本控制原理
  • 基于k8s环境下的pulsar常用命令(上)
  • 达梦分布式集群DPC_分布式任务执行拆分流程_yxy
  • 安全测绘之敏感网络资产排查指南
  • 在Linux上部署RabbitMQ、Redis、ElasticSearch
  • Taro Hooks 完整分类详解