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

限流、熔断、降级、线程池隔离

文章目录

  • 一、限流
      • 1.1 常见限流方式
          • 1.1.1 固定窗口、滑动窗口、漏斗、令牌桶
          • 1.1.2 令牌桶限流原理-公式
      • 1.2Guava令牌桶使用方式
      • 1.3 其他限流
          • 流控规则配置
          • 阻塞类型
          • 突发流量
          • 限流并且拒绝流量请求,友好提示限流了
  • 二、 熔断
      • 1.1 Thfirt熔断器
  • 三、 线程池隔离
      • 3.1 背景
      • 3.2 使用

一、限流

1.1 常见限流方式

1.1.1 固定窗口、滑动窗口、漏斗、令牌桶

四种常见限流方式

1.1.2 令牌桶限流原理-公式

令牌桶

1.2Guava令牌桶使用方式

Guava-RateLimiter

1.3 其他限流

流控规则配置

集群非精确 + 720次/s (限流周期1s、限流次数720)、阻塞类型:不限时阻塞 + 突发流量1s(缓存一定时间的阈值,应对流量蜂刺)、返回码429、返回信息:导出查询接口被限流

补充详解策略

序号策略类型含义备注极端场景
1集群非精确限流限流策略:5s/一个请求。5台机器平均每个机器0.2个请求/s令牌是会先通过当前的,再阻塞未来的,所以限流不准用户A和B,同一时刻或者5s之内,两次访问请求都可以打进去接口
2集群精确限流1.0限流策略:5s/一个请求 ,即整个集群,5s内只允许通过一个请求5s内,整个集群只会通过1次请求
阻塞类型
序号策略类型使用场景极端场景备注
1限时阻塞集群非精确限流
2不限时阻塞会阻塞线程100qps,5台机器。每台处理20QPS300请求打过来,极端场景全部打到同一个机器A。A,1s只能处理20请求,300请求需要15s,也就是,最后一个线程可能等待15s才能获得令牌执行线程因为限流线程等待了近10s
突发流量

1、定义:

在突发模式中,Guava限流器的桶中令牌是有一个有效期的,有效期的作用是让限流器具有一定的“弹性”,可以根据空闲情况临时超额放行一些请求用于平滑处理突发流量。

2、设置值:1

即保留上1s内,剩下的所有令牌。给下一秒用。

eg:1s生产100令牌。12:00:00没有请求进来,12:00:01的时候,现有可用令牌数量 = 本秒的100 + 上一秒的100 = 200。所以,即时限制了100QPS,在12:00:01的时候,也可能有200个请求打进来

踩坑1: 使用限流器后实际流量总是超过配置阈值

**解释:**这种情况只可能发生下突发模式下,是由2.3小节中介绍的突发流量处理机制导致的。突发模式限流器在向请求发放令牌包括存量令牌与新令牌,新令牌的生成速度等于限流速度,而超额部分的请求来自于存量令牌。在实际流量超过阈值不多的情况下,令牌桶中的令牌需要很长时间才能被耗尽。

踩坑2:在客户端匀速调用的场景中,服务端使用了限流器后发现实际流量无法达到阈值上限【很少见】

**解释:**这种情况是非常偶然的,实际是由于限流配置不当导致的。假设某个客户端以50QPS的速度发出请求,即每20ms一个,服务端的限流器配置为30QPS,且不支持突发流量(突发模式下设置突发时间为0,或者使用了预热模式)。这种情况下服务端会严格按照每30+ms一个的速度接收请求,因此,客户端在20ms之后发出第二个请求时,服务端尚未满足30ms的间隔时间,就出现了每两个请求就有一个被拒绝的现象。读者可参考下图理解这一现象。

**建议:**在遇到这种问题时首先考虑限流阈值是否合理。其次,如果在服务端使用突发模式限流,尽量不要把突发时间(maxBrustSeconds)设置为0。如果使用预热模式限流,应该参考服务容量,配置一个足够大的限流阈值。

限流并且拒绝流量请求,友好提示限流了

自定义blockHandle处理方法

方法的入参和出参 和 限流方法的一致

    public ExportDataTResponse blockHandler(SkuPreSellTRequest request, Operator operator) {LOGGER.info("限流导出request:{}, operator:{}", GsonUtil.toJsonString(request), GsonUtil.toJsonString(operator));ExportDataTResponse response = new ExportDataTResponse();response.setCode(429);response.setMsg(String.format("当前有用户正在操作导出,请 3 s后重试");response.setData("");return response;}

二、 熔断

1.1 Thfirt熔断器

1、默认配置

  • 请求试探窗口:5s(心跳机制)
  • 恢复策略:正常(立即、限时)
  • 降级方法:自定义降级方法(返回常量、抛出异常、脚本)
    @Degrade(key = "自定义key", fallBackMethod = "fallBack")public int getPrice(int param) {//方法内部不要捕获异常,熔断器通过异常判断调用结果int n = random.nextInt(10000);int m = 1;if (n > 9900) {m = 1 / 0;}return m;}// 降级方法,参数和主方法保持一致,注意降级方法必须是public,否则无法被cglib代理增强public int fallBack(int param) {return 0;}
  • 统计窗口:10s
  • 请求总数20
  • 失败率:50%
  • 失败数:2

三、 线程池隔离

3.1 背景

  • 如果某个接口的QPS过高,可能会影响服务提供其他功能接口。
  • 因为thrift单机默认256个工作线程,如果某接口的性能不好,QPS又高,则某个时间点,工作线程可能都被这个接口占用了,导致其他接口不可用。这时候我们就可以使用线程池隔离,动态!!!的给这个接口分配线程池。当超过一定的工作线程,则采用拒绝策略或直接抛出异常,再结合熔断降级方法,10s内20次调用超过50%的失败率,则这个接口会被降级,调用降级方法fallbackMethod。
  • 然后5s之后,心跳机制会去验证这个接口是否恢复正常,如果恢复正常,则接口限时|正常 节奏恢复可用,否则再等5s

3.2 使用

  • 线程池隔离 + 降级熔断方法
  • 同理,限流也可以接口熔断降级方法一起使用
@ThreadPoolExecute(key = "method.querySkuStock", coreSize = 15, maxSize = 30, maxQueueSize = 500, rejectHandler =ThreadPoolExecutor.CallerRunsPolicy.class)
@Degrade(rhinoKey = "asyncMethod", fallBackMethod = "fallbackMethod")
public Future<String> asyncMethod() {return new AsyncResult<String>() {@Overridepublic String invoke() throws Exception {TimeUnit.MILLISECONDS.sleep(500);return "asyncMethod";}};
}public String fallbackMethod(Throwable e) {//do fallback businessreturn "fallback";
}

相关文章:

  • 【数电笔记】11-最小项(逻辑函数的表示方法及其转换)
  • [Electron] 将应用打包成供Ubuntu、Debian平台下安装的deb包
  • 一篇文章带你详细了解C++智能指针
  • 2023年第十二届数学建模国际赛小美赛C题雪崩防范求解分析
  • Mysql安全之基础合规配置
  • 服务器数据恢复—服务器重装系统导致逻辑卷发生改变的数据恢复案例
  • 二:C语言-数据类型和变量
  • 深入了解UUID:生成、应用与优势
  • 【译】DispatcherServlet
  • 钉钉提交审批意见,并上传附件接口集成
  • 前端入门(四)Ajax、Promise异步、Axios通信、vue-router路由、组件库
  • 【Openstack Train安装】四、MariaDB/RabbitMQ 安装
  • 利用python编写后端程序 通用代码详解 项目实现
  • ReadWriteLock 和 StampedLock 的比较与解析
  • 人体姿态估计算法
  • JS 中的深拷贝与浅拷贝
  • C语言笔记(第一章:C语言编程)
  • JavaScript 事件——“事件类型”中“HTML5事件”的注意要点
  • k个最大的数及变种小结
  • MySQL QA
  • nginx 负载服务器优化
  • react 代码优化(一) ——事件处理
  • Sublime Text 2/3 绑定Eclipse快捷键
  • 开发了一款写作软件(OSX,Windows),附带Electron开发指南
  • 爬虫模拟登陆 SegmentFault
  • 深入浅出Node.js
  • 实现菜单下拉伸展折叠效果demo
  • 使用Maven插件构建SpringBoot项目,生成Docker镜像push到DockerHub上
  • 世界编程语言排行榜2008年06月(ActionScript 挺进20强)
  • 白色的风信子
  • 微龛半导体获数千万Pre-A轮融资,投资方为国中创投 ...
  • ​LeetCode解法汇总2696. 删除子串后的字符串最小长度
  • ​人工智能书单(数学基础篇)
  • # Java NIO(一)FileChannel
  • (16)Reactor的测试——响应式Spring的道法术器
  • (1综述)从零开始的嵌入式图像图像处理(PI+QT+OpenCV)实战演练
  • (2021|NIPS,扩散,无条件分数估计,条件分数估计)无分类器引导扩散
  • (PWM呼吸灯)合泰开发板HT66F2390-----点灯大师
  • (react踩过的坑)Antd Select(设置了labelInValue)在FormItem中initialValue的问题
  • (Spark3.2.0)Spark SQL 初探: 使用大数据分析2000万KF数据
  • (安全基本功)磁盘MBR,分区表,活动分区,引导扇区。。。详解与区别
  • (待修改)PyG安装步骤
  • (二)fiber的基本认识
  • (二)PySpark3:SparkSQL编程
  • (二)斐波那契Fabonacci函数
  • (附源码)springboot社区居家养老互助服务管理平台 毕业设计 062027
  • (黑客游戏)HackTheGame1.21 过关攻略
  • (介绍与使用)物联网NodeMCUESP8266(ESP-12F)连接新版onenet mqtt协议实现上传数据(温湿度)和下发指令(控制LED灯)
  • (转)AS3正则:元子符,元序列,标志,数量表达符
  • (转)Java socket中关闭IO流后,发生什么事?(以关闭输出流为例) .
  • (转载)CentOS查看系统信息|CentOS查看命令
  • (转载)Google Chrome调试JS
  • .bat批处理(三):变量声明、设置、拼接、截取
  • .mysql secret在哪_MySQL如何使用索引
  • .NET 中选择合适的文件打开模式(CreateNew, Create, Open, OpenOrCreate, Truncate, Append)