在当今互联网高速发展的时代,系统的稳定性和性能变得越来越重要。客户端限流作为一种保障系统稳定、应对流量高峰的重要手段,已经成为开发者和运维人员必备的技能。本文将深入解析客户端限流的原理,并结合五大实战案例,教你如何轻松应对流量高峰。
一、客户端限流原理
客户端限流是指限制客户端在单位时间内对服务端发起的请求次数,从而保证系统在高并发情况下不会因为请求过多而崩溃。常见的限流算法有:
- 令牌桶算法:通过一个桶来存储令牌,客户端每次请求都需要从桶中取出一个令牌,如果没有令牌则拒绝请求。
- 漏桶算法:允许一定速率的请求通过,超过速率的请求将被丢弃。
- 计数器算法:记录一定时间内的请求次数,超过预设阈值则拒绝请求。
二、实战案例一:基于令牌桶算法的限流器
以下是一个简单的基于令牌桶算法的限流器实现:
public class TokenBucketLimiter {
private final long capacity; // 桶容量
private final long fillInterval; // 填充间隔时间(毫秒)
private final long fillPerInterval; // 每个间隔时间填充的令牌数
private long lastFillTime; // 上次填充时间
private long tokens; // 当前令牌数
public TokenBucketLimiter(long capacity, long fillInterval, long fillPerInterval) {
this.capacity = capacity;
this.fillInterval = fillInterval;
this.fillPerInterval = fillPerInterval;
this.lastFillTime = System.currentTimeMillis();
this.tokens = capacity;
}
public boolean acquire() {
long now = System.currentTimeMillis();
long passedTime = now - lastFillTime;
long tokensToAdd = passedTime * (fillPerInterval / fillInterval);
tokens = Math.min(capacity, tokens + tokensToAdd);
lastFillTime = now;
if (tokens > 0) {
tokens--;
return true;
}
return false;
}
}
三、实战案例二:基于漏桶算法的限流器
以下是一个简单的基于漏桶算法的限流器实现:
public class LeakBucketLimiter {
private final long maxRate; // 最大速率
private long lastTime; // 上次通过时间
private long lastCount; // 上次通过计数
public LeakBucketLimiter(long maxRate) {
this.maxRate = maxRate;
this.lastTime = System.currentTimeMillis();
this.lastCount = 0;
}
public boolean acquire() {
long now = System.currentTimeMillis();
long passedTime = now - lastTime;
long countToAdd = passedTime * (maxRate / 1000);
long count = Math.min(maxRate, lastCount + countToAdd);
if (count > maxRate) {
count = maxRate;
}
long diff = count - lastCount;
lastCount = count;
lastTime = now;
if (diff > 0) {
return true;
}
return false;
}
}
四、实战案例三:基于计数器算法的限流器
以下是一个简单的基于计数器算法的限流器实现:
public class CounterLimiter {
private final long maxCount; // 最大计数
private long count; // 当前计数
private long startTime; // 开始时间
public CounterLimiter(long maxCount) {
this.maxCount = maxCount;
this.count = 0;
this.startTime = System.currentTimeMillis();
}
public boolean acquire() {
long now = System.currentTimeMillis();
long passedTime = now - startTime;
long countToAdd = passedTime * (maxCount / 1000);
if (countToAdd > maxCount) {
countToAdd = maxCount;
}
count += countToAdd;
if (count > maxCount) {
count = maxCount;
}
if (count > 0) {
count--;
return true;
}
return false;
}
}
五、实战案例四:基于Redis的限流器
以下是一个基于Redis的限流器实现:
public class RedisLimiter {
private final Jedis jedis;
public RedisLimiter(Jedis jedis) {
this.jedis = jedis;
}
public boolean acquire(String key, long count, long duration) {
String script = "if redis.call('exists', KEYS[1]) == 0 then "
+ "redis.call('set', KEYS[1], ARGV[2], 'PX', ARGV[3]) "
+ "return 1 "
+ "else "
+ "return redis.call('incr', KEYS[1]) <= ARGV[2] "
+ "end";
return jedis.eval(script, 1, key, String.valueOf(count), String.valueOf(duration * 1000)) == 1;
}
}
六、实战案例五:基于Guava的限流器
以下是一个基于Guava的限流器实现:
public class GuavaLimiter {
private final RateLimiter rateLimiter;
public GuavaLimiter(long permitsPerSecond) {
this.rateLimiter = RateLimiter.create(permitsPerSecond);
}
public boolean acquire() {
return rateLimiter.tryAcquire();
}
}
七、总结
客户端限流是保障系统稳定、应对流量高峰的重要手段。本文介绍了客户端限流的原理和五大实战案例,包括令牌桶算法、漏桶算法、计数器算法、基于Redis的限流器和基于Guava的限流器。通过学习和实践这些案例,相信你能够轻松应对流量高峰,守护系统稳定。
