Guava RateLimiter客户端限流
如果用RateLimiter不是分布式限流,只是单机限流,适用于calculate // 内存 cpu 防止本地的资源消耗过快
- 创建rate-limit子项目,引入依赖项
- 非阻塞式的限流方案
- 同步阻塞式的限流方案
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>spring-cloud-demo</artifactId>
<groupId>com.imooc</groupId>
<version>1.0.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>rate-limiter</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>18.0</version>
</dependency>
</dependencies>
</project>
启动类
package com.imooc.springcloud;
import org.springframework.boot.WebApplicationType;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
/**
* Created by 半仙.
*/
@SpringBootApplication
public class RateLimiterApplication {
public static void main(String[] args) {
new SpringApplicationBuilder(RateLimiterApplication.class)
.web(WebApplicationType.SERVLET)
.run(args);
}
}
controller
package com.imooc.springcloud;
import com.google.common.util.concurrent.RateLimiter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.concurrent.TimeUnit;
/**
* Created by 半仙.
*/
@RestController
@Slf4j
public class Controller {
// 2.0的意思是每秒钟发放2个通行证
RateLimiter limiter = RateLimiter.create(2.0);
// 非阻塞限流
@GetMapping("/tryAcquire")
public String tryAcquire(Integer count) {
if (limiter.tryAcquire(count)) {
log.info("success, rate is {}", limiter.getRate());
return "success";
} else {
log.info("fail, rate is {}", limiter.getRate());
return "fail";
}
}
// 限定时间的非阻塞限流
// limiter.getRate 速率
@GetMapping("/tryAcquireWithTimeout")
public String tryAcquireWithTimeout(Integer count, Integer timeout) {
if (limiter.tryAcquire(count, timeout, TimeUnit.SECONDS)) {
log.info("success, rate is {}", limiter.getRate());
return "success";
} else {
log.info("fail, rate is {}", limiter.getRate());
return "fail";
}
}
}
非阻塞模型
我们利用每秒2的请求从测试
你会发现前面放行了4个请求,那么是为什么呢,因为涉及到预热。
我们利用每秒4个请求的测试
你会发现,需要每两秒完成一次请求,同时刚开始奇怪的现象也出现了。
限定时间的非阻塞限流
如果将时间调为0
那么它和非阻塞没啥区别。
如果将时间调为2秒
全部成功
同步阻塞式的限流方案
上面接着的方法
// 同步阻塞限流
@GetMapping("/acquire")
public String acquire(Integer count) {
limiter.acquire(count);
log.info("success, rate is {}", limiter.getRate());
return "success";
}
他会在原地等待,等到通行为止。