基于令牌桶算法实现精确限流策略
- 引入依赖:在
pom.xml
中添加相关限流依赖,如guava
库,它提供了令牌桶算法的实现。
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>31.1-jre</version>
</dependency>
- 创建令牌桶:在Spring配置类中,创建令牌桶实例,设置每秒生成令牌数(限流速率)和令牌桶容量。
import com.google.common.util.concurrent.RateLimiter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class RateLimiterConfig {
@Bean
public RateLimiter rateLimiter() {
// 每秒生成2个令牌,桶容量为10
return RateLimiter.create(2);
}
}
- 在微服务方法中使用令牌桶限流:在需要限流的微服务方法调用前,尝试获取令牌。如果获取成功,则继续处理请求;否则,限流处理。
import com.google.common.util.concurrent.RateLimiter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class MyController {
@Autowired
private RateLimiter rateLimiter;
@GetMapping("/myEndpoint")
public String myEndpoint() {
if (rateLimiter.tryAcquire()) {
// 处理请求
return "Request processed successfully";
} else {
// 限流处理
return "Too many requests, please try again later";
}
}
}
基于漏桶算法实现精确限流策略
- 自定义漏桶算法实现:实现一个简单的漏桶算法,维护一个队列和固定的流出速率。
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
public class LeakyBucket {
private final long capacity;
private final long rate;
private long lastLeakTime;
private long water;
private final LinkedBlockingQueue<Runnable> requestQueue = new LinkedBlockingQueue<>();
public LeakyBucket(long capacity, long rate) {
this.capacity = capacity;
this.rate = rate;
this.lastLeakTime = System.nanoTime();
this.water = 0;
startLeak();
}
private void startLeak() {
Thread leakThread = new Thread(() -> {
while (true) {
try {
long now = System.nanoTime();
long elapsedTime = now - lastLeakTime;
long leakedWater = elapsedTime * rate / TimeUnit.SECONDS.toNanos(1);
water = Math.max(0, water - leakedWater);
lastLeakTime = now;
Runnable request = requestQueue.poll();
if (request != null && water < capacity) {
water++;
request.run();
}
TimeUnit.MILLISECONDS.sleep(10);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
});
leakThread.setDaemon(true);
leakThread.start();
}
public boolean tryEnqueue(Runnable request) {
if (water >= capacity) {
return false;
}
return requestQueue.offer(request);
}
}
- 在Spring中使用漏桶算法:在Spring配置类中创建漏桶实例,并在控制器中使用。
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class LeakyBucketConfig {
@Bean
public LeakyBucket leakyBucket() {
// 桶容量为10,每秒处理2个请求
return new LeakyBucket(10, 2);
}
}
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class MyController {
@Autowired
private LeakyBucket leakyBucket;
@GetMapping("/myEndpoint")
public String myEndpoint() {
if (leakyBucket.tryEnqueue(() -> {
// 处理请求逻辑
})) {
return "Request processed successfully";
} else {
return "Too many requests, please try again later";
}
}
}
处理限流后的请求
- 返回友好提示:如上述代码示例,直接返回类似“Too many requests, please try again later”的提示信息,告知用户请求过多,请稍后重试。
- 记录日志:使用日志框架记录限流的请求信息,包括请求来源、时间等,方便后续分析高负载情况和优化系统。
- 异步处理:将限流后的请求放入队列,通过异步线程或消息队列(如RabbitMQ、Kafka)进行处理,在系统负载降低时逐步处理这些请求。
- 熔断与降级:结合熔断机制(如Hystrix),当限流频繁发生时,触发熔断,直接返回降级处理结果,避免大量无效请求对系统造成更大压力。