文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

SpringBoot项目中接口限流实现方案

2024-12-03 07:57

关注

计数器

用计数器实现限流有点简单粗暴,一般我们会限 制一秒钟的能够通过的请求数,比如限流QPS为100,算法的实现思路就是从第一个请求进来开始计时,在接下去的1s内,每来一个请求,就把计数加1,如果累加的数字达到了100,那么后续的请求就会被全部拒绝。等到1s结束后,把计数恢复成0,重新开始计数。

具体的实现可以是这样的:对于每次服务调用,可以通过 AtomicLong#incrementAndGet()方法来给计数器加1并返回最新值,通过这个最新值和阈值进行比较。

这种实现方式,有一个弊端:如果我在单位时间1s内的前10ms,已经通过了100个请求,那后面的990ms,只能眼巴巴的把请求拒绝,我们把这种现象称为“突刺现象”。

漏桶算法

漏桶算法主要是控制数据注入到网络的速率,平滑网络上的突发流量。漏桶算法提供了一种机制,通过它,突发流量可以被整形以便为网络提供一个稳定的流量。

漏桶可以看作是一个带有常量服务时间的单服务器队列,如果漏桶(包缓存)溢出,那么数据包会被丢弃。 在网络中,漏桶算法可以控制端口的流量输出速率,平滑网络上的突发流量,实现流量整形,从而为网络提供一个稳定的流量。

如图所示,把请求比作是水,水来了都先放进桶里,并以限定的速度出水,当水来得过猛而出水不够快时就会导致水直接溢出,即拒绝服务。

image

可以看出,漏桶算法可以很好地控制流量的访问速度,一旦超过该速度就拒绝服务。

令牌桶算法

令牌桶算法的原理是系统会以一个恒定的速度往桶里放入令牌,而如果请求需要被处理,则需要先从桶里获取一个令牌,当桶里没有令牌可取时,则拒绝服务。从原理上看,令牌桶算法和漏桶算法是相反的,一个“进水”,一个是“漏水”。

image

了解完后3种限流算法后,接下来我们看看在项目中如何应用。

RateLimiter使用的是一种叫令牌桶的流控算法,RateLimiter会按照一定的频率往桶里扔令牌,线程拿到令牌才能执行;且RateLimiter不支持集群环境,集群环境需要借助Redis等第三方工具实现。

依赖

  1.  
  2.     org.springframework.boot 
  3.     spring-boot-starter-web 
  4.  
  5.  
  6.     com.google.guava 
  7.     guava 
  8.     30.1.1-jre 
  9.  

 实现目标:每秒只允许3个请求通过。

  1. @RestController 
  2. @RequestMapping("/products"
  3. public class ProductController { 
  4.      
  5.     private final RateLimiter rateLimiter = RateLimiter.create(5.0) ; 
  6.      
  7.     @GetMapping("/{id}"
  8.     public ResponseEntity queryProducts(@PathVariable("id")  String id) throws Exception { 
  9.         if (rateLimiter.tryAcquire(1)) { 
  10.             TimeUnit.MILLISECONDS.sleep(200) ; 
  11.             return new ResponseEntity(R.success("查询商品【" + id + "】成功"), HttpStatus.OK) ; 
  12.         } 
  13.         return new ResponseEntity(R.failure("你访问的太快了"), HttpStatus.INTERNAL_SERVER_ERROR) ; 
  14.     } 

 通过Jmeter测试,版本5.4.1

线程配置,100个并发循环2次

接口配置

测试结果

RateLimiter相关方法说明: 

参考https://ifeve!com/guava-ratelimiter

ratelimiter-spring-boot-starter为服务端限流的SDK,提供单节点维度的限流功能,通过限流算法,在流量过大时保证服务端按照一定速率平滑处理请求。

基于Spring Boot框架开发,目的是为Spring Cloud项目增加限流功能,同样在Spring Boot项目中也能正常使用。 本Starter的目前的应用场景为在Spring Cloud/Spring Boot的Web项目中引入该限流Starter,配置限流规则开启限流功能。 非Spring Web项目的特性正在规划中。

限流维度为:节点级、方法维度、服务维度限流。

目前方法级只提供http方法的规则配置与生效,后续有计划支持Rpc方法的限流。

依赖

  1.  
  2.         com.baidubce.formula 
  3.         ratelimiter-spring-boot-starter 
  4.         2.1.1.1 
  5.  

 应用配置

  1. spring: 
  2.   application: 
  3.     name: ratelimiter 
  4. --- 
  5. formula: 
  6.   ratelimiter: 
  7.     enabled: true 
  8.     ratelimiters: 
  9.     # 限流生效的位置,配置具体的uri 
  10.     - effectiveLocation: /products/q/** 
  11.       # 限流类型:1表示http,2表示rpc(暂未支持) 
  12.       effectiveType: 1 
  13.       # 该规则是否生效 
  14.       enabled: true 
  15.       httpMethod: GET 
  16.       # 限流器类型,1表示令牌桶 
  17.       limiterType: 1 
  18.       # 请求来源,当前版本不区分请求来源,区分请求来源的需求正在开发 
  19.       # source: 
  20.       # 限流的QPS值 
  21.       threshold: 5 

 注意:这里的spring.application.name必须配置,不然启动报错;

formula.ratelimiter.ratelimiters.source这个没有搞懂怎么配置的,官方文档没找到。

接口

  1. @GetMapping("/q/{id}"
  2. public ResponseEntity queryProduct(@PathVariable("id")  String id) throws Exception { 
  3.         TimeUnit.MILLISECONDS.sleep(200) ; 
  4.         return new ResponseEntity(R.success("查询商品【" + id + "】成功"), HttpStatus.OK) ; 

 测试

 

对于失败的请求,返回状态码429(Too Many Request)

baidu的这个限流工具,核心过滤器:

RateLimiterEffectiveFilter.java

waitForPermit方法

waitForPermission方法

HttpUtil#isBlockException方法

看到这里你想修改返回信息只能是重写它的代码了。

重写该类:

在我们项目src新建

com.baidu.formula.ratelimiter.spring.boot.autoconfigure.util.HttpUtil类修改isBlockException方法

  1. public static boolean isBlockException(HttpServletResponse response, Exception e) throws IOException { 
  2.         if (e instanceof BlockException) { 
  3.             response.setStatus(429); // too many request 
  4.             response.setContentType("application/json; charset=utf-8"); 
  5.             response.setCharacterEncoding("UTF-8"); 
  6.             response.getWriter().print("{\"code\": -1, \"message\": \"你的请求太快了\"}") ; 
  7.             response.flushBuffer(); 
  8.             return true
  9.         } else { 
  10.             return false
  11.         } 

 测试:

完毕!!!

 

来源:今日头条内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯