中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

SpringBoot項目中怎么實現接口限流

發布時間:2021-07-08 16:58:00 來源:億速云 閱讀:241 作者:Leah 欄目:web開發

這篇文章將為大家詳細講解有關SpringBoot項目中怎么實現接口限流,文章內容質量較高,因此小編分享給大家做個參考,希望大家閱讀完這篇文章后對相關知識有一定的了解。

限流算法

一般有漏桶算法和令牌桶算法及計數器三種方式。

計數器

用計數器實現限流有點簡單粗暴,一般我們會限  制一秒鐘的能夠通過的請求數,比如限流QPS為100,算法的實現思路就是從第一個請求進來開始計時,在接下去的1s內,每來一個請求,就把計數加1,如果累加的數字達到了100,那么后續的請求就會被全部拒絕。等到1s結束后,把計數恢復成0,重新開始計數。

具體的實現可以是這樣的:對于每次服務調用,可以通過  AtomicLong#incrementAndGet()方法來給計數器加1并返回最新值,通過這個最新值和閾值進行比較。

這種實現方式,有一個弊端:如果我在單位時間1s內的前10ms,已經通過了100個請求,那后面的990ms,只能眼巴巴的把請求拒絕,我們把這種現象稱為“突刺現象”。

漏桶算法

漏桶算法主要是控制數據注入到網絡的速率,平滑網絡上的突發流量。漏桶算法提供了一種機制,通過它,突發流量可以被整形以便為網絡提供一個穩定的流量。

漏桶可以看作是一個帶有常量服務時間的單服務器隊列,如果漏桶(包緩存)溢出,那么數據包會被丟棄。  在網絡中,漏桶算法可以控制端口的流量輸出速率,平滑網絡上的突發流量,實現流量整形,從而為網絡提供一個穩定的流量。

如圖所示,把請求比作是水,水來了都先放進桶里,并以限定的速度出水,當水來得過猛而出水不夠快時就會導致水直接溢出,即拒絕服務。

SpringBoot項目中怎么實現接口限流

image

可以看出,漏桶算法可以很好地控制流量的訪問速度,一旦超過該速度就拒絕服務。

令牌桶算法

令牌桶算法的原理是系統會以一個恒定的速度往桶里放入令牌,而如果請求需要被處理,則需要先從桶里獲取一個令牌,當桶里沒有令牌可取時,則拒絕服務。從原理上看,令牌桶算法和漏桶算法是相反的,一個“進水”,一個是“漏水”。

SpringBoot項目中怎么實現接口限流

image

了解完后3種限流算法后,接下來我們看看在項目中如何應用。

  • 使用Google Guava庫RateLimiter

RateLimiter使用的是一種叫令牌桶的流控算法,RateLimiter會按照一定的頻率往桶里扔令牌,線程拿到令牌才能執行;且RateLimiter不支持集群環境,集群環境需要借助Redis等第三方工具實現。

依賴

<dependency>     <groupId>org.springframework.boot</groupId>     <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency>     <groupId>com.google.guava</groupId>     <artifactId>guava</artifactId>     <version>30.1.1-jre</version> </dependency>

實現目標:每秒只允許3個請求通過。

@RestController @RequestMapping("/products") public class ProductController {          private final RateLimiter rateLimiter = RateLimiter.create(5.0) ;          @GetMapping("/{id}")     public ResponseEntity<R> queryProducts(@PathVariable("id")  String id) throws Exception {         if (rateLimiter.tryAcquire(1)) {             TimeUnit.MILLISECONDS.sleep(200) ;             return new ResponseEntity<R>(R.success("查詢商品【" + id + "】成功"), HttpStatus.OK) ;         }         return new ResponseEntity<R>(R.failure("你訪問的太快了"), HttpStatus.INTERNAL_SERVER_ERROR) ;     } }

通過Jmeter測試,版本5.4.1

線程配置,100個并發循環2次

SpringBoot項目中怎么實現接口限流

接口配置

SpringBoot項目中怎么實現接口限流

測試結果

SpringBoot項目中怎么實現接口限流

RateLimiter相關方法說明:

SpringBoot項目中怎么實現接口限流

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

  • 使用百度的ratelimiter-spring-boot-starter

ratelimiter-spring-boot-starter為服務端限流的SDK,提供單節點維度的限流功能,通過限流算法,在流量過大時保證服務端按照一定速率平滑處理請求。

基于Spring Boot框架開發,目的是為Spring Cloud項目增加限流功能,同樣在Spring Boot項目中也能正常使用。  本Starter的目前的應用場景為在Spring Cloud/Spring Boot的Web項目中引入該限流Starter,配置限流規則開啟限流功能。  非Spring Web項目的特性正在規劃中。

限流維度為:節點級、方法維度、服務維度限流。

  • 節點級別含義為限流SDK引入目標服務代碼,限流規則針對目標服務部署的每個實例單獨生效。

  • 方法維度含義為可以為目標服務的每個方法單獨配置限流規則,該規則針對當前方法生效,與其他方法互不影響,目前方法僅支持HttpMethod+uri。

  • 服務維度含義為可針對每個服務實例配置全局規則,流入該服務實例的每個請求都將先進行服務限流判斷。  服務級和方法級同時存在,將先后進過服務級、方法級兩種限流器,任意一個限流器拒絕都將拒絕請求。

目前方法級只提供http方法的規則配置與生效,后續有計劃支持Rpc方法的限流。

依賴

<dependency>         <groupId>com.baidubce.formula</groupId>         <artifactId>ratelimiter-spring-boot-starter</artifactId>         <version>2.1.1.1</version> </dependency>

應用配置

spring:   application:     name: ratelimiter --- formula:   ratelimiter:     enabled: true     ratelimiters:     # 限流生效的位置,配置具體的uri     - effectiveLocation: /products/q/**       # 限流類型:1表示http,2表示rpc(暫未支持)       effectiveType: 1       # 該規則是否生效       enabled: true       httpMethod: GET       # 限流器類型,1表示令牌桶       limiterType: 1       # 請求來源,當前版本不區分請求來源,區分請求來源的需求正在開發       # source:       # 限流的QPS值       threshold: 5

注意:這里的spring.application.name必須配置,不然啟動報錯;

formula.ratelimiter.ratelimiters.source這個沒有搞懂怎么配置的,官方文檔沒找到。

接口

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

測試

SpringBoot項目中怎么實現接口限流

對于失敗的請求,返回狀態碼429(Too Many Request)

baidu的這個限流工具,核心過濾器:

RateLimiterEffectiveFilter.java

SpringBoot項目中怎么實現接口限流

waitForPermit方法

SpringBoot項目中怎么實現接口限流

waitForPermission方法

SpringBoot項目中怎么實現接口限流

HttpUtil#isBlockException方法

SpringBoot項目中怎么實現接口限流

看到這里你想修改返回信息只能是重寫它的代碼了。

重寫該類:

在我們項目src新建

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

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

測試:

SpringBoot項目中怎么實現接口限流

關于SpringBoot項目中怎么實現接口限流就分享到這里了,希望以上內容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

普格县| 阿巴嘎旗| 色达县| 交口县| 东港市| 滦南县| 康定县| 天峻县| 锡林郭勒盟| 广元市| 襄樊市| 乌拉特前旗| 静海县| 石棉县| 文昌市| 武定县| 靖江市| 中西区| 和田市| 公安县| 巴楚县| 平南县| 樟树市| 闻喜县| 澜沧| 华宁县| 井冈山市| 淮北市| 阜康市| 竹山县| 科技| 崇州市| 新巴尔虎左旗| 台安县| 桃源县| 北安市| 安仁县| 股票| 扎鲁特旗| 惠州市| 谢通门县|