Apabila masa berlalu, sistem akan mengikut selang masa 1/QPS malar (jika QPS=100, Kemudian selang adalah 10ms) Tambah Token ke baldi (bayangkan kebalikan daripada kebocoran, terdapat paip sentiasa menambah air), jika baldi penuh, tiada lagi akan ditambah Apabila permintaan baru datang, masing-masing akan mengambil Token . Jika tiada token tersedia, ia akan menyekat atau menafikan perkhidmatan.
Faedah lain baldi token ialah ia boleh menukar kelajuan dengan mudah , tambahkannya mengikut keperluan dan masukkan ke dalam baldi Kadar token Secara amnya, bilangan token tertentu akan ditambahkan secara tetap (seperti 100 milisaat). dalam masa nyata
Timba token ialah teknologi kawalan trafik yang biasa digunakan. Baldi token itu sendiri tidak mempunyai dasar pembuangan dan keutamaan.
1. Token dimasukkan ke dalam baldi pada kadar tertentu.
2. Setiap token membenarkan sumber menghantar bilangan bit tertentu.
3. Untuk menghantar paket, perapi trafik mengeluarkan beberapa token daripada baldi yang sama dengan saiz paket.
4. Jika token tidak mencukupi untuk menghantar paket, paket menunggu sehingga token mencukupi (dalam kes pembentuk) atau paket digugurkan, mungkin ditandakan dengan DSCP yang lebih rendah (dalam kes polisi).
5. Baldi mempunyai kapasiti tertentu Jika baldi penuh, token yang baru ditambah akan dibuang. Oleh itu, jumlah maksimum data pecah sumber boleh menghantar ke rangkaian pada bila-bila masa adalah berkadar dengan saiz baldi. Baldi token membenarkan pecah, tetapi tidak boleh melebihi had.
修饰符和类型 | 方法和描述 |
---|---|
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>
Had antara muka tersuai
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 aspek
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 "不限流执行了"; } }
Mulakan perkhidmatan dan akses antara muka yang menambah anotasi mengehadkan semasa
Lawati semula antara muka tanpa nota
Hasil cetakan konsol:
Atas ialah kandungan terperinci Cara menggunakan springboot untuk menyepadukan pengehadan RateLimiter semasa. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!