降级限流

article/2025/8/28 2:50:05

目录

1、限流和降级

1.1、降级

1.2、限流

2、限流算法

2.1、滑动窗口

2.2、漏桶

2.3、令牌桶

3、限流实践

3.1、单机Guava实现令牌桶和漏桶

3.2、分布式限流器实现

3.2.1、Redis实现

3.2.2、lua脚本实现

3.2.3、Redission的实现

4、小结


前言
对于高可用的服务,除了尽量保证自身的服务的可靠性外, 还的防止不被上游压垮,控制上游的访问一般使用限流策略,避免被下游服务不可用拖垮,一般采取降级策略,只有更好的了解和控制上下游才能使自身的服务的稳定性增强。所以服务降级限流是系统面临挑战的最后一道保护屏障,不可忽视,也是在突发情况下保证系统稳定性和可用性的有效手段。

1、限流和降级

目的: 当流量快速增长的时候,一定要保证核心服务的可用,即便是有损服务。方案包括: 有限重试, 快速失败, 降级限流方案。
对于高并发C端业务系统,一般都会采取相应的手段来保护系统不被意外的请求流量压垮,进行服务的降级处理, 包括熔断和限流:
  • 熔断:类似于电流的保险丝机制,当我们的服务出问题或者影响到核心服务流程的时候需要暂时熔断某些功能+友好的提示,等高峰或者问题解决后再打开;
  • 限流:当流量快速增长、防止脉冲式流量导致服务可能会出现问题(响应超时),或者非核心服务影响到核心流程时, 仍然需要保证服务的可用性, 即便是有损服务
  • 缓存:目的是提升系统访问速度和增大系统处理的容量,可以说是 抗高并发流量的银弹;
所以意味着我们在设计服务的时候,在使用缓存和异步处理的同时,还需要通过一些关键数据进行 自动降级,或者配置 人工降级的开关。

1.1、降级

对于系统的降级,请求的backup,降级一般有几种实现手段:
  • 自动降级:达到某一阈值后自动熔断降级;
    • 例如达到请求QPS阈值,下游服务接口错误率达到一定的阈值;对业务的重要程度可实现服务降级,自动返回预设数据和通知信息,或者延后处理;
    • 中间件服务故障等使用降级掉部分功能服务,例如mq故障使用rpc方式;
    • 多级缓存的使用;
  • 人工降级: 通过配置降级开关,人为实现对流程的控制;
    • 前置化降级开关, 基于配置中心实现附加业务的降级;
    • 业务降级,首先可以进行服务隔离,资源隔离,分渠道分地域分区进行控制,在业务高峰期,我们会优先保证核心业务的流程可用,对附加业务进行降级处理;
降级方案分为:有损降级和无损降级
  • 无损降级例如多级缓存,异步发送mq转rpc调用,全局id转本地生成后备方案;
  • 有损降级:限制资源,降级服务不可用+友好提示等等;

1.2、限流

限流的目的是防止恶意请求流量、恶意攻击、或者防止流量超过系统峰值。通过对并发访问/请求进行限速或者一个时间窗口内的请求进行限速来保护系统。
主要是对资源访问做控制,那么控制这块主要有两个功能:
限流策略
限流策略由 限流算法可调节的参数两部份组成,算法和参数都需要结合具体的业务特点和并发量来选择和设置。
熔断策略
对于服务的 熔断策略,不同的系统有不同的熔断策略诉求,例如:
  • 直接拒绝服务.(友好提示页面告知资源没有了);
  • 排队等待 异步处理(秒杀、抢购下单);
  • 服务降级 (返回兜底数据或默认数据,如商品详情页等等)

2、限流算法

限流算法,对突发流量的整形形成稳定的流量,对系统起到保护作用,将脉冲式流量压力均衡分摊,减少系统瞬时的压力。

2.1、滑动窗口协议

是传输层进行流控的一种措施,接收方通过通告发送方自己的窗口大小,从而控制发送方的发送速度,从而达到防止发送方发送速度过快而导致自己被淹没的目的。
动态限流效果演示: https://media.pearsoncmg.com/aw/ecs_kurose_compnetwork_7/cw/content/interactiveanimations/selective-repeat-protocol/index.html

2.2、漏桶

桶本身具有一个恒定的速率(接口的响应时间)往下漏水,而上方时快时慢的会有水进入桶内。当桶还未满时,上方的水可以加入。一旦水满,上方的水就无法加入。桶满正是算法中的一个关键的触发条件(即流量异常判断成立的条件)。而此条件下如何处理上方流下来的水,有两种方式在桶满水之后,常见的两种处理方式为:
  • 1) 阻塞:暂时拦截住上方水的向下流动,等待桶中的一部分水漏走后,再放行上方水;
  • 2) 抛弃:溢出的上方水直接抛弃,执行拒绝策略;
特点:
  • 1. 漏水的速率是固定的
  • 2. 即使存在注水 burst(突然注水量变大)的情况, 漏水的速率是固定的,不能解决突发流量; 

2.3、令牌桶

令牌桶算法是网络流量整形(Traffic Shaping)和速率限制(Rate Limiting)中最 常使用的一种算法。典型情况下,令牌桶算法用来控制发送到网络上的数据的数目, 能解决突发请求的流量;
令牌桶是一个存放固定容量令牌(token)的桶,按照固定速率往桶里添加令牌; 令牌是按一定的速率来生成;1个令牌/10ms;
令牌桶算法实际上由两部分组成: 
  • 两个流:分别是 令牌流、数据流
  • 一个桶: 令牌桶
令牌桶和漏桶的区别: 令牌桶算法能够在限制数据的平均传输速率的同时还允许某种程度的突发传输。
分析:比如我们的目标现在是每秒钟处理10个请求,使用漏桶法,我们设置桶的大小为10,流出的速率为0.1s流出一个请求,我们可以达成我们的目标;而使用令牌桶的话,我们会设置每1s向桶中放入10个令牌,请求如果是平稳的,每0.1s过来一个请求,来十个,同样能达到我们的目标,这里所说的某种程度的突发传输是指,比如在一秒内前0.5请求是平稳的,每0.1s来一个,但在0.6s的时候突发请求同时来个5个请求,此时令牌算法是可以承受这个突发流量的,并且让5个请求成功立刻同时得到处理,完成了所谓的某种程度的突发传输,而漏桶算法,也可以应对这种突发流量,但不同的是没有让5个请求同时立刻通过,而是缓冲在桶中,然后仍然以固定速率每0.1s处理一个。
这两种算法,都可以实现流速的控制,1s处理10个请求,多于10个的请求都会被拒绝,但由于漏桶算法流出速率是一定的,所以请求可能会被缓冲在桶中,不能马上得到处理,从而徒增了等待时间,而对于令牌桶算法,没有这种等待时间,有令牌则通过,无令牌则抛弃。

3、限流实践

3.1、单机Guava实现令牌桶和漏桶

具体实例如下:
public class GuavaTokenDemo {private int qps;private int countOfReq;private RateLimiter rateLimiter;public GuavaTokenDemo(int qps, int countOfReq) {this.qps = qps;this.countOfReq = countOfReq;}//初始化一个令牌桶public GuavaTokenDemo processWithTokenBucket() {rateLimiter = RateLimiter.create(qps);                          //1min钟的请求量qps;峰值return this;}//初始化一个漏桶public GuavaTokenDemo processWithLeakyBucket() {rateLimiter = RateLimiter.create(qps, 0, TimeUnit.MILLISECONDS); //预热时间 0 return this;}private void processRequest() {System.out.println("RateLimiter:" + rateLimiter.getClass());long start = System.currentTimeMillis();for (int i = 0; i < countOfReq; i++) {rateLimiter.acquire();//获取令牌 acquire()是阻塞的,tryAcquire()是非阻塞的;}long end = System.currentTimeMillis() - start;System.out.println("处理的请求数量:" + countOfReq + "," +"" + "耗时:" + end + ",qps:" + rateLimiter.getRate() + ",实际qps:" +Math.ceil(countOfReq / (end / 1000.00)));}public void doProcessor() throws InterruptedException {for (int i = 0; i < 20; i = i + 5) {TimeUnit.SECONDS.sleep(i);processRequest();}}public static void main(String[] args) throws InterruptedException {new GuavaTokenDemo(50, 100).processWithTokenBucket().doProcessor();new GuavaTokenDemo(50, 100).processWithLeakyBucket().doProcessor();}}

通过运行结果的耗时和处理请求数可以发现,当请求书低于qps的时候,结果是恒定的,对于突发差不多2倍qps的流量请求,令牌桶是可以处理的;但是漏桶的处理速率就是恒定的;

3.2、分布式限流器实现

在分布式环境下,Guava的限流就无法起到作用了,所以必须借助第三方中间件来实现,而redis的高性能使其成了首选。

3.2.1、Redis实现

基于原生Redis的分布式限流器RateLimiter可以用来在分布式环境下进行限流,例如可以用来限制调用接口的次数。
//基于redis实现的限流器
public class RedisLimiter {static String key = "keyWords"; //限流关键字static int limitCount = 10;     //限流访问频次static int limitTimeSecond = 5; //限流单位时间public static void main(String[] args) throws InterruptedException {Jedis j = new Jedis("127.0.0.1", 6379);new Thread(() -> {while (true) {if (!checkKeyLimit(j)) {System.out.println("超过阈值,被限流");return;}incrKey(j);}}).start();}//利用超时时间内的访问频次阈值来实现访问限制;private static void incrKey(Jedis j) {if (j.ttl(key) < 0) {j.incr(key); //访问一次,计数自增一次j.expire(key, limitTimeSecond);} else {j.incr(key);}System.out.println("总访问次数为:" + j.get(key));}//判断时间内是否到达阈值private static boolean checkKeyLimit(Jedis j) {if (null != j.get(key)) {if (Integer.parseInt(j.get(key)) >= limitCount) {return false;}}return true;}
}

3.2.2、lua脚本实现

其实和原生Redis的实现思想一样,只是利用了lua脚本执行的原子性,使用lua脚本实现限流代码如下
    -- ip_limit.lua-- IP 限流,对某个 IP 频率进行限制 ,1 秒钟访问 10 次 local num=redis.call('incr',KEYS[1])if tonumber(num)==1 thenredis.call('expire',KEYS[1],ARGV[1])return 1else if tonumber(num)>tonumber(ARGV[2]) thenreturn 0elsereturn 1end

例如想实现对ip:192.168.8.111,限制1秒内请求超过10次就拒绝,运行命令:

./redis-cli --eval "ip_limit.lua" app:ip:limit:192.168.8.111 , 1 10

3.2.3、Redission的实现

其实使用基于Redis的客户端Redisson提供的api来实现更加方便。主要实现原理是令牌桶机制,需要先获取指定的令牌,限流器每秒会产生n个令牌放入令牌桶,调用接口需要先去令牌桶里面拿令牌,起到限流的作用。
实例如下:
public class SingleTest {public static void main(String[] args) {Config config = new Config();config.setCodec(new org.redisson.client.codec.StringCodec());//指定使用单节点部署方式config.useSingleServer().setAddress("redis://127.0.0.1:6379");RedissonClient redisson = Redisson.create(config);//获取令牌桶限流RRateLimiter rRateLimiter = redisson.getRateLimiter("myRateLimiter");//初始化  最大流速 = 每1秒钟产生100个令牌rRateLimiter.trySetRate(RateType.OVERALL, 100, 1, RateIntervalUnit.SECONDS);//需要1个令牌if(rateLimiter.tryAcquire(1)){//TODO: do something}//批量获取10个令牌if(rateLimiter.acquire(10)){//TODO: do something}//关闭RedissonClientredisson.shutdown();}
}

4、小结

为了保证系统的可用性,系统设计必须考虑到降级限流。
应用按层划分限流:
  • 前置化限流:例如Nginx负载均衡的分流与限流;
  • Server层接口限流方法:令牌桶及漏桶算法,hytrix熔断,请求排队+异步处理,线程池排队+拒绝策略;
  • Dao层数据库资源-池化技术,连接池-数据库资源的合理利用;
单进程的限流:guava中的Ratlimiter.create(10);
分布式下的限流策略:分布式的限流需要借助于第三方才可实现;
  • Mysql: 存储限流策略的参数等元数据
  • 基于 Redis的计数 令牌桶算法,或者lua脚本实现计数限流;
OK---待从头、收拾旧山河,朝天阙。
水滴石穿,积少成多。学习笔记,内容简单,用于复习,梳理巩固。

http://chatgpt.dhexx.cn/article/cm8oNEyf.shtml

相关文章

服务降级设计

实际系统运维中会出现某点的流量高峰&#xff0c;该时间有些可以预计&#xff0c;如双十一&#xff0c;有些不能预计&#xff0c;如某明星大爆料 等等&#xff0c;那么对着此类情况加设备等不能满足要求或者不能立刻满足邀请的时候&#xff0c;就需要对服务进行降级操作。

mysql数据库自动降级_mysql降级caveats

在线QQ客服:1922638 专业的SQL Server、MySQL数据库同步软件 在此博客中,我们将讨论在MySQL降级期间需要注意的事项。 之前,我曾写过博客MySQL升级最佳实践。除了升级MySQL版本外,有时还需要降级。在降级MySQL时,支持两种降级方法: 就地降级:在这种方法中,您使用现有的数…

Dubbo使用之服务降级

什么是服务降级 降级的目的是为了保证核心服务可用。 降级可以有几个层面的分类&#xff1a; 自动降级和人工降级&#xff1b; 按照功能可以分为&#xff1a;读服务降级和写服务降级 对一些非核心服务进行人工降级&#xff0c;在大促之前通过降级开关关闭哪些推荐内容、评价…

伪代码格式和标准

目录 注意算法组成部分算法示例 注意 每一条指令占一行(else if例外)&#xff0c;指令后不跟任何符号&#xff08;Pascal和C中语句要以分号结尾&#xff09;每一行要标号开头描述输入&#xff0c;输出变量名和保留字不区分大小写&#xff0c;Pascal相同&#xff0c;C或C不同数…

LaTeX伪代码写法总结

1. 伪代码所用包 一般会接触到的包有algorithm、algorithmic、algorithmicx、algorithm2e这四种包。 algorithm用于给伪代码提供一个浮动体环境&#xff0c;防止其换页或其他因素导致的内容中断&#xff0c;从而跨页显示。 algorithmic用于编辑伪代码的内容&#xff0c;一些…

伪码-伪代码的定义以及实现

伪代码的写法 伪代码(Pseudocode)是一种算法描述语言。使用伪代码的目的是为了使被描述的算法可以容易地以任何一种编程语言(Pascal&#xff0c;C&#xff0c;Java&#xff0c;etc)实现。因此&#xff0c;伪代码必须结构清晰、代码简单、可读性好&#xff0c;并且类似自然语言…

伪代码教程

伪代码教程 起一篇伪代码基础教程 伪代码(Pseudo code)是一种介于计算机语言和自然语言间的文字和符号&#xff0c;是表达算法的简单而有效的方法。伪代码不需要关注底层是如何实现的&#xff0c;本身就是算法框架的逻辑模型。 一、赋值语句 赋值号 A ← B A\leftarrow B A←…

伪代码怎么编写?

20230522 补充一下&#xff1a; 建议学习PUML的语法&#xff0c;这个和伪代码很相似&#xff0c;也可以看到业务流程图 问 根据IDEA项目代码生成伪代码的工具 答 目前没有根据IDEA项目代码自动生成伪代码的工具。伪代码是一种描述程序算法的语言&#xff0c;通常不是具体的编…

【笔记】伪代码编写

在线LaTeX编写工具overleaf极大的方便了暂时需要为论文编写伪代码的需要&#xff1a;Overleaf, Online LaTeX Editor 该工具只需要简单注册就可以使用。 首先进入overleaf主页&#xff0c;然后完成注册和登录&#xff1a; 接着&#xff0c;需要创建用于储存LaTeX的文件夹&…

伪代码与代码区别

伪码&#xff08;Pseudocode&#xff09;是一种算法描述语言。使用伪码的目的是使被描述的算法可以容易地以任何一种编程语言&#xff08;Pascal&#xff0c;C&#xff0c;Java等&#xff09;实现。因此&#xff0c;伪代码必须结构清晰、代码简单、可读性好&#xff0c;并且类似…

伪代码书写方式

伪代码是描述算法过程的一种语言&#xff0c;它可以直接用中文或者英文等自然语言表示&#xff0c;也可以直接上代码&#xff0c;但常用经典的语法表示(讲的就是这种)。日常生中,别人能通过你的描述明白相应算法就行。 小规范 1、不需要声明变量&#xff0c;变量名可以一定程…

伪代码学习与应用

目录 0. 前言1. 伪代码的基础语法2. 在word中插入伪代码2.1 Aurora和Miktex安装2.2 插入伪代码 参考链接伪代码模板模板一模板二模板三模板四 疑难杂症1. 显示中文&#xff1f;2. 特殊字符&#xff1f;3. 换行&#xff1f; 0. 前言 上一次接触伪代码可能还是在现代数字信号处理…

2D激光slam四种算法建图效果对比

slam算法对照 通过麦克纳姆轮机器人小车构建地图对比Gmapping、Hector、Karto、Cartographer四种算法的优缺点 真实场景图如下图所示&#xff1a; 具体步骤为&#xff1a; 1、打开地图构建命令 roslaunch turn_on_wheeltec_robot mapping.launch2、打开rviz rviz3、打开控制…

SLAM——hector-slam算法原理解析

1、hector-slam代码框架概述 下载源码&#xff1a;git clone https://github.com/tu-darmstadt-ros-pkg/hector_slam.git 原理解读参照&#xff1a;https://blog.csdn.net/weixin_40047925/article/details/80679496 其中包含了许多用于仿真的文件&#xff0c;hector slam算法主…

激光SLAM算法学习(三)——3D激光SLAM

3D激光SLAM 1、3D激光SLAM的介绍 3D激光SLAM的输入: IMU数据 3D激光雷达数据 里程计数据 3D激光SLAM的输出: 3D点云地图 机器人的轨迹 or PoseGraph 2、3D激光SLAM的发展 3D激光SLAM的帧间匹配方法——点云配准算法 Point-to-Plane ICP Feature-based Method 3D激光SLAM的回…

SLAM 算法的一些简单的介绍和理解,有的是从别的地方找到的资料,感觉很有道理。

SLAM&#xff08;Simultaneous localization and mapping&#xff09;,我们要达到的目的就是估计机器人&#xff08;传感器-比如相机&#xff09;的位置轨迹&#xff0c;然后创建地图。locating和map两者互相依赖&#xff0c;密不可分。然而我们 已知的信息一个是 observation&…

2021年开源SLAM算法

1.TANDEM&#xff1a;Tracking and Dense Mapping in Real-time using Deep Multi-view Stereo 慕尼黑工业大学Daniel Cremers团队&#xff0c;实时单目跟踪稠密建图纯视觉SLAM&#xff0c;采用Realsense D455(深度传感器IMU&#xff0c;但只用RGB) 项目地址&#xff1a;https…

激光SLAM技术总结(3)3D激光SLAM算法原理

目录 1. 3D激光SLAM简介 2. 3D激光雷达SLAM 3. 高精度V-LOAM方案 4 发展趋势 1. 3D激光SLAM简介 在 3D 激光 SLAM 领域中&#xff0c; 由 Zhang J 等人提出的LOAM 方案&#xff0c;利用 3D 激光雷达采集数据&#xff0c; 进行基于特征点的扫描匹配&#xff0c; 利用非线性…

实习:slam算法的学习整理

1.odom 2.updata_odom 3.updata_laser updata_landmark 4.resample pf.c 相机的位姿转换是基于世界坐标系的&#xff0c;观察到的路标也会在世界坐标系中不断收敛&#xff0c;若不是计算错误&#xff0c;基本上不会产生漂移。而IMU是自身坐标系标定的&#xff0c;在转换到…

关于slam

什么是SLAM?机器人在未知环境中&#xff0c;要实现智能化需要完成三个任务&#xff0c;第一个是定位(Localization)&#xff0c;第二个是建图(Mapping)&#xff0c;第三个则是随后的路径规划(Navigation)。 之前地平线的高翔博士用这样一句话概括SLAM的释义。不过实际生活中的…