RateLimiter令牌桶原理圖
#隨著時間流逝,系統會依恆定1/QPS時間間隔(如果QPS=100,則間隔是10ms)往桶裡加入Token(想像和漏洞漏水相反,有個水龍頭在不斷的加水),如果桶已經滿了就不再加了.新請求來臨時,會各自拿走一個Token,如果沒有Token可拿了就阻塞或拒絕服務.
令牌桶的另外一個好處是可以方便的改變速度. 一旦需要提高速率,則按需提高放入桶中的令牌的速率. 一般會定時(比如100毫秒)往桶中增加一定數量的令牌, 有些變種演算法則實時的計算應該增加的令牌的數量.
令牌桶是一種常用的流量控制技術。令牌桶本身沒有丟棄和優先策略。
原理
1.令牌以一定的速率放入桶中。
2.每個令牌允許來源發送一定數量的位元。
3.發送一個包,流量調節器就要從桶中刪除與包大小相等的令牌數。
4.如果沒有足夠的令牌發送包,這個包就會等待直到有足夠的令牌(在整形器的情況下)或者包被丟棄,也有可能被標記更低的DSCP(在策略者的情況下)。
5.桶子有特定的容量,如果桶子已經滿了,新加入的令牌就會被丟棄。因此,在任何時候,來源發送到網路上的最大突發資料量與桶的大小成比例。令牌桶允許突發,但是不能超過限制。
方法摘要
修飾符和類型 | 方法和描述 |
---|---|
double | acquire() 從RateLimiter取得一個許可,該方法會被阻斷直到取得到請求 |
double | acquire(int permits) 從RateLimiter取得指定許可數,該方法會被阻塞直到取得到請求 |
#static RateLimiter | create(double permitsPerSecond) 根據指定的穩定吞吐率創建RateLimiter,這裡的吞吐率是指每秒多少許可數(通常是指QPS,每秒多少查詢) |
static RateLimiter | create(double permitsPerSecond, long warmupPeriod, TimeUnit unit) 根據指定的穩定吞吐率和預熱期來創建RateLimiter,這裡的每秒吞吐率是指每秒鐘授權數(通常是指QPS,每秒多少請求量),在這段預熱時間內,RateLimiter每秒分配的授權數會平穩地成長直到預熱期結束時達到其最大速率。 (只要有足夠請求數來使其飽和) |
double | getRate() 傳回RateLimiter 配置中的穩定速率,該速率單位是每秒多少個許可數 |
void | setRate(double permitsPerSecond) 更新RateLimite的穩定速率,參數permitsPerSecond 由建構RateLimiter的工廠方法提供。 |
String | toString() 傳回物件的字元表現形式 |
boolean | tryAcquire()從RateLimiter 取得許可,如果該許可可以在無延遲下的情況下立即取得得到的話 |
boolean | tryAcquire(int permits) 從RateLimiter 取得許可數,如果該許可數可以在無延遲下的情況下立即取得得到的話 |
boolean | tryAcquire(int permits, long timeout, TimeUnit unit) 從RateLimiter 取得指定許可數如果該許可數可以在不超過timeout的時間內獲取得到的話,或者如果無法在timeout 過期之前獲取得到許可數的話,那麼立即返回false (無需等待) |
#boolean | tryAcquire(long timeout, TimeUnit unit) 從RateLimiter 取得許可如果該許可可以在不超過timeout的時間內獲取得到的話,或者如果無法在timeout 過期之前獲取得到許可的話,那麼立即返回false(無需等待) |
開始貼程式碼
pom.xml
<!--guava RateLimiter限流--> <!-- https://mvnrepository.com/artifact/com.google.guava/guava --> <dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> <version>28.2-jre</version> </dependency>
自訂介面Limit
package com.zjy.knife4j.inte; import java.lang.annotation.*; /** * 限流注解 */ @Inherited @Documented @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface Limit { // 默认每秒放入桶中的token double limitNum() default 20; String name() default ""; }
# aop切面
package com.zjy.knife4j.aspect; import com.google.common.util.concurrent.RateLimiter; import com.zjy.knife4j.inte.Limit; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.Signature; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Pointcut; import org.aspectj.lang.reflect.MethodSignature; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component; import java.lang.reflect.Method; import java.util.concurrent.ConcurrentHashMap; @Aspect @Component public class RateLimitAspect { /**日志对象*/ private static final Logger logger = LoggerFactory.getLogger(RateLimitAspect.class); private ConcurrentHashMap<String, RateLimiter> RATE_LIMITER = new ConcurrentHashMap<>(); private RateLimiter rateLimiter; @Pointcut("@annotation(com.zjy.knife4j.inte.Limit)") public void serviceLimit() { } @Around("serviceLimit()") public Object around(ProceedingJoinPoint point) throws Throwable { Object obj = null; //获取拦截的方法名 Signature sig = point.getSignature(); //获取拦截的方法名 MethodSignature msig = (MethodSignature) sig; //返回被织入增加处理目标对象 Object target = point.getTarget(); //为了获取注解信息 Method currentMethod = target.getClass().getMethod(msig.getName(), msig.getParameterTypes()); //获取注解信息 Limit annotation = currentMethod.getAnnotation(Limit.class); double limitNum = annotation.limitNum(); //获取注解每秒加入桶中的token String functionName = msig.getName(); // 注解所在方法名区分不同的限流策略 if(RATE_LIMITER.containsKey(functionName)){ rateLimiter=RATE_LIMITER.get(functionName); }else { RATE_LIMITER.put(functionName, RateLimiter.create(limitNum)); rateLimiter=RATE_LIMITER.get(functionName); } if(rateLimiter.tryAcquire()) { logger.info("执行成功!!!...做一些业务处理"); return point.proceed(); } else { logger.info("请求繁忙...做一些业务处理"); return null; } } }
RateLimiterController
package com.zjy.knife4j.controller; import com.zjy.knife4j.inte.Limit; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RequestMapping("/ratelimiter") @RestController public class RateLimiterController { /** * 开启限流 * @return */ @GetMapping("/open") @Limit(limitNum = 1, name = "test1") public String openRateLimiter1() { System.out.println("【限流执行了....编写业务....】"); return "限流执行了"; } /** * 开启限流 * @return */ @GetMapping("/open2") @Limit(limitNum = 1, name = "test2") public String openRateLimiter2() { System.out.println("【限流执行了222】"); return "限流执行了222"; } /** * 未开启限流 * @return */ @GetMapping("/close") public String closeRateLimiter() { System.out.println("【不限流执行了】"); return "不限流执行了"; } }
程式碼貼完了,開始測試
#啟動服務,存取新增限流註解的介面
#再存取沒加註解的介面
控制台列印結果:
以上是如何使用springboot整合RateLimiter限流的詳細內容。更多資訊請關注PHP中文網其他相關文章!

新興技術對Java的平台獨立性既有威脅也有增強。 1)雲計算和容器化技術如Docker增強了Java的平台獨立性,但需要優化以適應不同雲環境。 2)WebAssembly通過GraalVM編譯Java代碼,擴展了其平台獨立性,但需與其他語言競爭性能。

不同JVM實現都能提供平台獨立性,但表現略有不同。 1.OracleHotSpot和OpenJDKJVM在平台獨立性上表現相似,但OpenJDK可能需額外配置。 2.IBMJ9JVM在特定操作系統上表現優化。 3.GraalVM支持多語言,需額外配置。 4.AzulZingJVM需特定平台調整。

平台獨立性通過在多種操作系統上運行同一套代碼,降低開發成本和縮短開發時間。具體表現為:1.減少開發時間,只需維護一套代碼;2.降低維護成本,統一測試流程;3.快速迭代和團隊協作,簡化部署過程。

Java'splatformindependencefacilitatescodereusebyallowingbytecodetorunonanyplatformwithaJVM.1)Developerscanwritecodeonceforconsistentbehavioracrossplatforms.2)Maintenanceisreducedascodedoesn'tneedrewriting.3)Librariesandframeworkscanbesharedacrossproj

要解決Java應用程序中的平台特定問題,可以採取以下步驟:1.使用Java的System類查看系統屬性以了解運行環境。 2.利用File類或java.nio.file包處理文件路徑。 3.根據操作系統條件加載本地庫。 4.使用VisualVM或JProfiler優化跨平台性能。 5.通過Docker容器化確保測試環境與生產環境一致。 6.利用GitHubActions在多個平台上進行自動化測試。這些方法有助於有效地解決Java應用程序中的平台特定問題。

類加載器通過統一的類文件格式、動態加載、雙親委派模型和平台無關的字節碼,確保Java程序在不同平台上的一致性和兼容性,實現平台獨立性。

Java編譯器生成的代碼是平台無關的,但最終執行的代碼是平台特定的。 1.Java源代碼編譯成平台無關的字節碼。 2.JVM將字節碼轉換為特定平台的機器碼,確保跨平台運行但性能可能不同。

多線程在現代編程中重要,因為它能提高程序的響應性和資源利用率,並處理複雜的並發任務。 JVM通過線程映射、調度機制和同步鎖機制,在不同操作系統上確保多線程的一致性和高效性。


熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

WebStorm Mac版
好用的JavaScript開發工具

SublimeText3 Linux新版
SublimeText3 Linux最新版

VSCode Windows 64位元 下載
微軟推出的免費、功能強大的一款IDE編輯器

MinGW - Minimalist GNU for Windows
這個專案正在遷移到osdn.net/projects/mingw的過程中,你可以繼續在那裡關注我們。 MinGW:GNU編譯器集合(GCC)的本機Windows移植版本,可自由分發的導入函式庫和用於建置本機Windows應用程式的頭檔;包括對MSVC執行時間的擴展,以支援C99功能。 MinGW的所有軟體都可以在64位元Windows平台上運作。

記事本++7.3.1
好用且免費的程式碼編輯器