架构之高并发:限流(高并发限流降级)

  本篇文章为你整理了架构之高并发:限流(高并发限流降级)的详细内容,包含有高并发限流方案 高并发限流降级 限流技术 限流算法以及实现 架构之高并发:限流,希望能帮助你了解 架构之高并发:限流。

   Java 全栈知识体系 ❁导航 ♥面试 ✿导读 JavaJavaJava 面向对象和基础 Java 面向对象基础 Java 基础知识体系 Java进阶 - 集合框架 Java 集合框架详解 Java进阶 - 并发框架 Java 并发知识体系 Java 并发理论基础 Java 并发线程基础 J.U.C 知识体系与详解 Java进阶 - IO框架 Java IO/NIO/AIO详解 Java进阶 - 新版本特性 Java 8 特性详解 Java 8 以上版本特性体系 Java 8 升Java 11特性必读 Java 11 升Java 17特性必读 Java进阶 - JVM相关 Java 类加载机制 Java 字节码和增强技术 JVM 内存结构详解 JVM 垃圾回收机制 Java 调试排错相关 算法算法算法基础和思想 数据结构基础 常见排序算法 算法思想 一些领域算法 安全算法 字符串匹配算法 分布式系统算法 海量数据处理 负载均衡算法 推荐算法 数据挖掘算法 ID生成算法 其它算法相关 头脑风暴 数据库数据库数据库基础和原理 数据库原理 SQL语言 SQL 数据库 MySQL 详解 NoSQL 数据库 Redis 详解 MongoDB 详解 ElasticSearch 详解 开发开发开发 - 常用开发基础 常用类库详解 正则表达式详解 CRON表达式详解 网络协议和工具详解 安全相关详解 开发 - 质量保障 单元测试详解 统一风格详解 质量管理详解 开发 - 代码重构 代码重构相关 SpringSpringSpring Framework(v5.3) Spring框架知识体系 Spring框架组成 控制反转(IOC) 面向切面编程(AOP) SpringMVC SpringBoot系列(v2.5) SpringBoot知识体系 SpringBoot入门 SpringBoot接口设计和实现 SpringBoot集成MySQL SpringBoot集成ShardingJDBC SpringBoot集成Redis SpringBoot集成Postgre SpringBoot集成ElasticSearch SpringBoot集成Socket SpringBoot定时任务 SpringBoot后端视图 SpringBoot监控 SpringBoot进阶 框架中间件框架中间件Web 容器 Tomcat 源码详解 ORM 框架 MyBatis 源码详解 分表分库框架 ShardingSphere 详解 架构架构架构基础和技术点 架构知识体系 从角色视角看架构 从分层视角看架构 从演化视角看架构 从模式视角看架构 高并发之缓存 高并发之限流 高并发之降级和熔断 高可用之负载均衡 高可用之容灾备份 分布式系统 分布式理论和一致性算法 全局唯一ID实现方案 分布式锁及实现方案 分布式事务及实现方案 分布式任务及实现方案 分布式会话及实现方案 微服务系统 微服务系统和设计 系统设计之商业业务平台 秒杀抽奖相关设计 电商交易相关设计 仓储物流相关设计 拉新投放相关设计 其它综合相关设计 系统设计之数据仓库平台 数据库架构相关设计 数据同步相关设计 数据仓库相关设计 数据治理相关设计 工具部署工具部署 开发工具 Git详解 Linux Docker 项目 方法论方法论开发理论 开发原则(SOLID) 分布式理论(CAP) 分布式理论(BASE) 事务理论(ACID) 微服务理论(康威定律) 开源协议 常见开源协议详解 知识共享许可协议 国产开源木兰协议 代码规范 阿里巴巴 Java开发手册 Google Java 编程风格指南 Twitter Java代码规范 开发流程 软件生命周期与传统模型 结合测试演化的过程模型 敏捷开发项目管理理论 敏捷之极限编程(XP) 敏捷之Scrum Kanban 敏捷实践之测试驱动开发 设计模式 设计模式详解 系统认证 CMMI 认证 等级保护认证 ISO27001认证 产品团队产品团队技术之外 技术之外应该思考什么 个人相关 个人成长和认知 产品相关 产品设计和思考 团队相关 管对管理和成长 其它相关 其它软实力等 关于 ❁导航 ♥面试 ✿导读 JavaJavaJava 面向对象和基础 Java 面向对象基础 Java 基础知识体系 Java进阶 - 集合框架 Java 集合框架详解 Java进阶 - 并发框架 Java 并发知识体系 Java 并发理论基础 Java 并发线程基础 J.U.C 知识体系与详解 Java进阶 - IO框架 Java IO/NIO/AIO详解 Java进阶 - 新版本特性 Java 8 特性详解 Java 8 以上版本特性体系 Java 8 升Java 11特性必读 Java 11 升Java 17特性必读 Java进阶 - JVM相关 Java 类加载机制 Java 字节码和增强技术 JVM 内存结构详解 JVM 垃圾回收机制 Java 调试排错相关 算法算法算法基础和思想 数据结构基础 常见排序算法 算法思想 一些领域算法 安全算法 字符串匹配算法 分布式系统算法 海量数据处理 负载均衡算法 推荐算法 数据挖掘算法 ID生成算法 其它算法相关 头脑风暴 数据库数据库数据库基础和原理 数据库原理 SQL语言 SQL 数据库 MySQL 详解 NoSQL 数据库 Redis 详解 MongoDB 详解 ElasticSearch 详解 开发开发开发 - 常用开发基础 常用类库详解 正则表达式详解 CRON表达式详解 网络协议和工具详解 安全相关详解 开发 - 质量保障 单元测试详解 统一风格详解 质量管理详解 开发 - 代码重构 代码重构相关 SpringSpringSpring Framework(v5.3) Spring框架知识体系 Spring框架组成 控制反转(IOC) 面向切面编程(AOP) SpringMVC SpringBoot系列(v2.5) SpringBoot知识体系 SpringBoot入门 SpringBoot接口设计和实现 SpringBoot集成MySQL SpringBoot集成ShardingJDBC SpringBoot集成Redis SpringBoot集成Postgre SpringBoot集成ElasticSearch SpringBoot集成Socket SpringBoot定时任务 SpringBoot后端视图 SpringBoot监控 SpringBoot进阶 框架中间件框架中间件Web 容器 Tomcat 源码详解 ORM 框架 MyBatis 源码详解 分表分库框架 ShardingSphere 详解 架构架构架构基础和技术点 架构知识体系 从角色视角看架构 从分层视角看架构 从演化视角看架构 从模式视角看架构 高并发之缓存 高并发之限流 高并发之降级和熔断 高可用之负载均衡 高可用之容灾备份 分布式系统 分布式理论和一致性算法 全局唯一ID实现方案 分布式锁及实现方案 分布式事务及实现方案 分布式任务及实现方案 分布式会话及实现方案 微服务系统 微服务系统和设计 系统设计之商业业务平台 秒杀抽奖相关设计 电商交易相关设计 仓储物流相关设计 拉新投放相关设计 其它综合相关设计 系统设计之数据仓库平台 数据库架构相关设计 数据同步相关设计 数据仓库相关设计 数据治理相关设计 工具部署工具部署 开发工具 Git详解 Linux Docker 项目 方法论方法论开发理论 开发原则(SOLID) 分布式理论(CAP) 分布式理论(BASE) 事务理论(ACID) 微服务理论(康威定律) 开源协议 常见开源协议详解 知识共享许可协议 国产开源木兰协议 代码规范 阿里巴巴 Java开发手册 Google Java 编程风格指南 Twitter Java代码规范 开发流程 软件生命周期与传统模型 结合测试演化的过程模型 敏捷开发项目管理理论 敏捷之极限编程(XP) 敏捷之Scrum Kanban 敏捷实践之测试驱动开发 设计模式 设计模式详解 系统认证 CMMI 认证 等级保护认证 ISO27001认证 产品团队产品团队技术之外 技术之外应该思考什么 个人相关 个人成长和认知 产品相关 产品设计和思考 团队相关 管对管理和成长 其它相关 其它软实力等 关于 架构基础

   ♥架构 - 知识体系详解♥ 架构 - 架构基础: 特点,本质... 架构 - 理解构架的视角 架构 - 理解构架的分层 架构 - 理解架构的演进 架构 - 理解架构的服务演化 架构 - 理解架构的模式1 架构 - 理解架构的模式2 架构 - 理解架构的核心要素 架构之高并发:缓存 架构之高并发:限流 架构之高并发:降级和熔断 架构之高可用:负载均衡 架构之高可用:容灾备份,故障转移 架构 - 保障架构安全 架构 - 学习资料 分布式系统

   ♥分布式系统 - 知识体系详解♥ 分布式系统 - 理论基础,理论及一致性算法 分布式系统 - 全局唯一ID实现方案 分布式系统 - 分布式锁及实现方案 分布式系统 - 分布式事务及实现方案 分布式系统 - 分布式缓存及方案实现 分布式系统 - 分布式任务及实现方案 分布式系统 - 分布式会话及实现方案 分布式系统 - 分布式服务链路追踪 分布式系统 - 分布式文件系统 分布式系统 - 分布式存储系统 分布式系统 - 分布式计算详解 分布式系统 - 分布式系统的8个谬误 微服务系统与设计

   走出微服务误区:避免从单体到分布式单体 系统设计之商业业务平台

   ♥系统设计之商业业务平台设计♥ 【秒杀抽奖】秒杀系统设计 【电商交易】京东-亿级商品详情页设计 【电商交易】闲鱼-亿级商品结构化背后的思考和演进 【电商交易】闲鱼-多状态多操作的交易链路架构演进 【拉新投放】闲鱼-拉新投放系统如何设计 【综合/其它】闲鱼-复杂搜索系统的可靠性优化之路 【仓储物流】美团-配送系统架构演进实践 【仓储物流】美团-即时物流的分布式系统架构设计 【综合/其它】美团-外卖客户端高可用建设体系 系统设计之日志系统平台

   美团: 高性能终端实时日志系统建设实践 vivo: 大数据日志采集Agent设计实践 美团: 可视化全链路日志追踪 美团: 日志导致线程Block的这些坑,你不得不防 京东: 秒级百G日志传输存储架构设计与实战 美团: 如何优雅地记录操作日志? 携程: 日均TB级数据,携程支付统一日志框架 腾讯: 企业微信万亿级日志检索系统 系统设计之网关设计

   美团: 百亿规模API网关服务Shepherd的设计与实现 vivo: 微服务 API 网关架构实践 唯品会: 高吞吐消息网关的探索与思考 # 架构之高并发:限流每个系统都有服务的上线,所以当流量超过服务极限能力时,系统可能会出现卡死、崩溃的情况,所以就有了降级和限流。限流其实就是:当高并发或者瞬时高并发时,为了保证系统的稳定性、可用性,系统以牺牲部分请求为代价或者延迟处理请求为代价,保证系统整体服务可用。@pdai

  限流简介算法分类方案一:令牌桶方式(Token Bucket)举例:Guava RateLimiter - 平滑突发限流(SmoothBursty)举例:Guava RateLimiter - SmoothWarmingUp方案二:漏桶方式令牌桶和漏桶对比方案三:计数器方式采用AtomicInteger采用令牌Semaphore采用ThreadPoolExecutor java线程池压力测试参考文章# 限流简介每个系统都有服务的上线,所以当流量超过服务极限能力时,系统可能会出现卡死、崩溃的情况,所以就有了降级和限流。限流其实就是:当高并发或者瞬时高并发时,为了保证系统的稳定性、可用性,系统以牺牲部分请求为代价或者延迟处理请求为代价,保证系统整体服务可用。

  # 算法令牌桶(Token Bucket)、漏桶(leaky bucket)和计数器算法是最常用的三种限流的算法。

  # 分类# 应用级 - 单机应用级限流方式只是单应用内的请求限流,不能进行全局限流。

  限流总资源数限流总并发/连接/请求数限流某个接口的总并发/请求数限流某个接口的时间窗请求数平滑限流某个接口的请求数Guava RateLimiter# 分布式我们需要分布式限流和接入层限流来进行全局限流。

  redis+lua实现中的lua脚本使用Nginx+Lua实现的Lua脚本使用 OpenResty 开源的限流方案限流框架,比如Sentinel实现降级限流熔断# 方案一:令牌桶方式(Token Bucket)令牌桶算法是网络流量整形(Traffic Shaping)和速率限制(Rate Limiting)中最常使用的一种算法。先有一个木桶,系统按照固定速度,往桶里加入Token,如果桶已经满了就不再添加。当有请求到来时,会各自拿走一个Token,取到Token 才能继续进行请求处理,没有Token 就拒绝服务。

  这里如果一段时间没有请求时,桶内就会积累一些Token,下次一旦有突发流量,只要Token足够,也能一次处理,所以令牌桶算法的特点是允许突发流量。

  # 举例:Guava RateLimiter - 平滑突发限流(SmoothBursty)Guava RateLimiter提供了令牌桶算法实现:平滑突发限流(SmoothBursty)和平滑预热限流(SmoothWarmingUp)实现。

  Case 1

RateLimiter limiter = RateLimiter.create(5);

 

  System.out.println(limiter.acquire());

  System.out.println(limiter.acquire());

  System.out.println(limiter.acquire());

  System.out.println(limiter.acquire());

  System.out.println(limiter.acquire());

  System.out.println(limiter.acquire());

  // 将得到类似如下的输出:

  0.198239

  0.196083

  0.200609

  0.199599

  0.19961

  

1、RateLimiter.create(5)表示桶容量为5且每秒新增5个令牌,即每隔200毫秒新增一个令牌;

 

  2、limiter.acquire()表示消费一个令牌,如果当前桶中有足够令牌则成功(返回值为0),如果桶中没有令牌则暂停一段时间,比如发令牌间隔是200毫秒,则等待200毫秒后再去消费令牌(如上测试用例返回的为0.198239,差不多等待了200毫秒桶中才有令牌可用),这种实现将突发请求速率平均为了固定请求速率。如果结构不想等待可以采用tryAcquire立刻返回!

  Case 2 - RateLimiter的突发情况处理:

RateLimiter limiter = RateLimiter.create(5);

 

  System.out.println(limiter.acquire(5));

  System.out.println(limiter.acquire(1));

  System.out.println(limiter.acquire(1))

  // 将得到类似如下的输出:

  0.98745

  0.183553

  0.199909

  

limiter.acquire(5)表示桶的容量为5且每秒新增5个令牌,令牌桶算法允许一定程度的突发,所以可以一次性消费5个令牌,但接下来的limiter.acquire(1)将等待差不多1秒桶中才能有令牌,且接下来的请求也整形为固定速率了。

 

  Case 3 - RateLimiter的突发情况处理:

RateLimiter limiter = RateLimiter.create(5);

 

  System.out.println(limiter.acquire(10));

  System.out.println(limiter.acquire(1));

  System.out.println(limiter.acquire(1));

  // 将得到类似如下的输出:

  1.997428

  0.192273

  0.200616

  

同上边的例子类似,第一秒突发了10个请求,令牌桶算法也允许了这种突发(允许消费未来的令牌),但接下来的limiter.acquire(1)将等待差不多2秒桶中才能有令牌,且接下来的请求也整形为固定速率了。

 

  Case 4

RateLimiter limiter = RateLimiter.create(2);

 

  System.out.println(limiter.acquire());

  Thread.sleep(2000L);

  System.out.println(limiter.acquire());

  System.out.println(limiter.acquire());

  System.out.println(limiter.acquire());

  System.out.println(limiter.acquire());

  System.out.println(limiter.acquire());

  // 将得到类似如下的输出:

  0.499876

  0.495799

  

1、创建了一个桶容量为2且每秒新增2个令牌; 2、首先调用limiter.acquire()消费一个令牌,此时令牌桶可以满足(返回值为0); 3、然后线程暂停2秒,接下来的两个limiter.acquire()都能消费到令牌,第三个limiter.acquire()也同样消费到了令牌,到第四个时就需要等待500毫秒了。

 

  此处可以看到我们设置的桶容量为2(即允许的突发量),这是因为SmoothBursty中有一个参数:最大突发秒数(maxBurstSeconds)默认值是1s,突发量/桶容量=速率*maxBurstSeconds,所以本示例桶容量/突发量为2,例子中前两个是消费了之前积攒的突发量,而第三个开始就是正常计算的了。令牌桶算法允许将一段时间内没有消费的令牌暂存到令牌桶中,留待未来使用,并允许未来请求的这种突发.

  SmoothBursty通过平均速率和最后一次新增令牌的时间计算出下次新增令牌的时间的,另外需要一个桶暂存一段时间内没有使用的令牌(即可以突发的令牌数)。另外RateLimiter还提供了tryAcquire方法来进行无阻塞或可超时的令牌消费。

  因为SmoothBursty允许一定程度的突发,会有人担心如果允许这种突发,假设突然间来了很大的流量,那么系统很可能扛不住这种突发。因此需要一种平滑速率的限流工具,从而系统冷启动后慢慢的趋于平均固定速率(即刚开始速率小一些,然后慢慢趋于我们设置的固定速率)。Guava也提供了SmoothWarmingUp来实现这种需求类似漏桶算法;

  # 举例:Guava RateLimiter - SmoothWarmingUpSmoothWarmingUp创建方式:RateLimiter.create(doublepermitsPerSecond, long warmupPeriod, TimeUnit unit)

  permitsPerSecond表示每秒新增的令牌数,warmupPeriod表示在从冷启动速率过渡到平均速率的时间间隔。

  

RateLimiter limiter = RateLimiter.create(5,1000, TimeUnit.MILLISECONDS);

 

  for(inti =1; i 5;i++) {

   System.out.println(limiter.acquire());

  Thread.sleep(1000L);

  for(inti =1; i 5;i++) {

   System.out.println(limiter.acquire());

  // 将得到类似如下的输出:

  0.51767

  0.357814

  0.219992

  0.199984

  0.360826

  0.220166

  0.199723

  0.199555

  

速率是梯形上升速率的,也就是说冷启动时会以一个比较大的速率慢慢到平均速率;然后趋于平均速率(梯形下降到平均速率)。可以通过调节warmupPeriod参数实现一开始就是平滑固定速率。

 

  # 方案二:漏桶方式水(请求)先进入到漏桶里,漏桶以一定的速度出水(接口有响应速率),当水流入速度过大会直接溢出(访问频率超过接口响应速率),然后就拒绝请求,可以看出漏桶算法能强行限制数据的传输速率。

  可见这里有两个变量,一个是桶的大小,支持流量突发增多时可以存多少的水(burst),另一个是水桶漏洞的大小(rate)。

  因为漏桶的漏出速率是固定的参数,所以,即使网络中不存在资源冲突(没有发生拥塞),漏桶算法也不能使流突发(burst)到端口速率.因此,漏桶算法对于存在突发特性的流量来说缺乏效率.

  # 令牌桶和漏桶对比令牌桶是按照固定速率往桶中添加令牌,请求是否被处理需要看桶中令牌是否足够,当令牌数减为零时则拒绝新的请求;漏桶则是按照常量固定速率流出请求,流入请求速率任意,当流入的请求数累积到漏桶容量时,则新流入的请求被拒绝;令牌桶限制的是平均流入速率(允许突发请求,只要有令牌就可以处理,支持一次拿3个令牌,4个令牌),并允许一定程度突发流量;漏桶限制的是常量流出速率(即流出速率是一个固定常量值,比如都是1的速率流出,而不能一次是1,下次又是2),从而平滑突发流入速率;令牌桶允许一定程度的突发,而漏桶主要目的是平滑流入速率;两个算法实现可以一样,但是方向是相反的,对于相同的参数得到的限流效果是一样的。# 方案三:计数器方式计数器限流算法也是比较常用的,主要用来限制总并发数,比如数据库连接池大小、线程池大小、程序访问并发数等都是使用计数器算法。也是最简单粗暴的算法。

  # 采用AtomicInteger使用AomicInteger来进行统计当前正在并发执行的次数,如果超过域值就简单粗暴的直接响应给用户,说明系统繁忙,请稍后再试或其它跟业务相关的信息。

  弊端:使用 AomicInteger 简单粗暴超过域值就拒绝请求,可能只是瞬时的请求量高,也会拒绝请求。

  # 采用令牌Semaphore使用Semaphore信号量来控制并发执行的次数,如果超过域值信号量,则进入阻塞队列中排队等待获取信号量进行执行。如果阻塞队列中排队的请求过多超出系统处理能力,则可以在拒绝请求。

  相对Atomic优点:如果是瞬时的高并发,可以使请求在阻塞队列中排队,而不是马上拒绝请求,从而达到一个流量削峰的目的。

  # 采用ThreadPoolExecutor java线程池固定线程池大小,超出固定先线程池和最大的线程数,拒绝线程请求;

  # 压力测试给个思路

  Linux AB可以参考Linux - ab压力测试

  写代码比如:

  

@SneakyThrows

 

  public static void test(int clientSize) {

   CountDownLatch downLatch = new CountDownLatch(clientSize);

   ExecutorService fixedThreadPool = Executors.newFixedThreadPool(clientSize);

   IntStream.range(0, clientSize).forEach(i -

   fixedThreadPool.submit(() - {

   RestTemplate restTemplate = new RestTemplate();

   restTemplate.getForObject( http://localhost:8080/limit1 , ResponseResult.class);

   downLatch.countDown();

   downLatch.await();

   fixedThreadPool.shutdown();

  

其它测试工具,LoadRunner,Jmeter...# 参考文章聊聊互联网限流方案 http://www.dczou.com/viemall/852.html

 

  https:///cmfwm/p/8032994.html

   我要纠错 架构之高并发:缓存 架构之高并发:降级和熔断

  苏ICP备19053722号 pdai copyright © 2017-present 架构之高并发:限流 限流简介 算法 分类 方案一:令牌桶方式(Token Bucket) 举例:Guava RateLimiter - 平滑突发限流(SmoothBursty) 举例:Guava RateLimiter - SmoothWarmingUp 方案二:漏桶方式 令牌桶和漏桶对比 方案三:计数器方式 采用AtomicInteger 采用令牌Semaphore 采用ThreadPoolExecutor java线程池 压力测试 参考文章 【双11】腾讯云服务器Java全栈读者专享
2核2G,4M,40GB, 50元/1年 查看2核4G,6M,60GB, 100元/1年 查看4核8G,10M,100GB, 300元/1年 查看目录架构之高并发:限流 限流简介 算法 分类 方案一:令牌桶方式(Token Bucket) 举例:Guava RateLimiter - 平滑突发限流(SmoothBursty) 举例:Guava RateLimiter - SmoothWarmingUp 方案二:漏桶方式 令牌桶和漏桶对比 方案三:计数器方式 采用AtomicInteger 采用令牌Semaphore 采用ThreadPoolExecutor java线程池 压力测试 参考文章 手机看微信扫一扫
可以手机看或分享至朋友圈
全屏看左栏交流圈添加pdai微信进《Java全栈知识体系》学习交流圈「无任何套路」 PS:添加时请备注Java全栈,谢谢! 下资料扫描公众号,回复“资料”下载10GB+书籍资料「无任何套路」公众号: Java全栈知识体系
支持我鼓励/支持/赞赏我
1. 不靠它生存但仍希望得到你的鼓励;
2. 时刻警醒自己保持技术人的初心,恒心,简单,利他;
(点击右侧❤️可以查看赞赏榜单和用途)
面试
上一篇
下一篇站点图 关于我 关于站点 最近更新记录问题反馈常用搜索百度 Google Bing Github 搜代码 技术社区CSDN OSChina 知否 掘金 Linux公社 IBM 开发者 StackOverflow Java相关面向对象基础语法基础集合框架并发基础并发关键字JUC并发框架IO框架Java8 特性JVM基础调试排错更多资源算法相关数组与线性表树详解图详解内部排序算法思想安全算法大数据处理分布式算法负载均衡算法推荐算法头脑风暴数据库相关数据库原理SQL语言MySQL相关MongoDBElasticSearch开发基础相关常用类库单元测试正则表达式网络协议安全相关常见重构技巧架构相关架构基础架构视角架构演进架构模式和要素高并发之缓存高并发之限流高并发之降级负载均衡容灾备份架构安全秒杀系统设计架构案例工具和部署工具集合IDE相关GitMavenLinuxDocker方法论SOLIDCAPBASE开源协议代码规范设计模式产品和团队产品相关团队相关其它分享

  以上就是架构之高并发:限流(高并发限流降级)的详细内容,想要了解更多 架构之高并发:限流的内容,请持续关注盛行IT软件开发工作室。

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: