限流器:Semaphore,RateLimiter

Semaphore实现一个简单的限流器

class ObjPool<T, R> {  
	final List<T> pool;  
	// 用信号量实现限流器  
	final Semaphore sem; 
	 // 构造函数  
	 ObjPool(int size, T t){    
		 pool = new Vector<T>(){};    
		 for(int i=0; i<size; i++){      
		 pool.add(t);    
		 }    
		 sem = new Semaphore(size); 
	 }  
	 // 利用对象池的对象,调用 func  
	 R exec(Function<T,R> func) {    
		 T t = null;    
		 sem.acquire();    
		 try {      
			 t = pool.remove(0);      
			 return func.apply(t);   
		 } 
		 finally {      
			 pool.add(t);      
			 sem.release();    
		 }  
	 } 
 } 
 // 创建对象池
ObjPool<Long, String> pool =   new ObjPool<Long, String>(10, 2); 
// 通过对象池获取 t,之后执行 
pool.exec(t -> {    
	System.out.println(t);    
	return t.toString(); 
});

RateLimiter

Google开源工具包Guava提供了限流工具类RateLimiter
令牌桶算法

获取令牌接口

//阻塞等待获取
limiter.acquire()
//获取10个
limiter.acquire(10);

//非阻塞,尝试获取令牌,请求失败立即返回false
limiter.tryAcquire()
//尝试获取permits个令牌
limiter.tryAcquire(int permits)
//带超时时间
limiter.tryAcquire(long timeout, TimeUnit unit)
limiter.tryAcquire(int permits, long timeout, TimeUnit unit)

创建令牌接口

/**
* 创建一个稳定输出令牌的RateLimiter,保证了平均每秒不超过permitsPerSecond个请求
* 当请求到来的速度超过了permitsPerSecond,保证每秒只处理permitsPerSecond个请求
* 当这个RateLimiter使用不足(即请求到来速度小于permitsPerSecond),会囤积最多permitsPerSecond个请求
*/
public static RateLimiter create(double permitsPerSecond);

/**
* 创建一个稳定输出令牌的RateLimiter,保证了平均每秒不超过permitsPerSecond个请求
* 还包含一个热身期(warmup period),热身期内,RateLimiter会平滑的将其释放令牌的速率加大,直到起达到最大速率
* 同样,如果RateLimiter在热身期没有足够的请求(unused),则起速率会逐渐降低到冷却状态
* 
* 设计这个的意图是为了满足那种资源提供方需要热身时间,而不是每次访问都能提供稳定速率的服务的情况(比如带缓存服务,需要定期刷新缓存的)
* 参数warmupPeriod和unit决定了其从冷却状态到达最大速率的时间
*/
public static RateLimiter create(double permitsPerSecond, long warmupPeriod, TimeUnit unit);

//如:每秒两个
RateLimiter rateLimiter = RateLimiter.create(2.0);

storedPermits
过去剩余的令牌
这个字段的设计是为了怕如果限流长时间没有使用,而流量突然进来,会使之前的令牌都没有使用到。
比如QPS = 5,create(5),即一秒5个请求,如果前600ms的令牌都没有使用。则storedPermits = 3,
后面的400ms请求了5个令牌,会把storedPermits的令牌以及freshPermits都给他。如果超过,需要等待。

就好像如果每秒产生一个令牌,前面的50s都没有流量,但是如果突然请求了100个令牌,却需要这个请求等待100s。应该将过去剩余的50个令牌给予使用,并且在剩余的50s内,边执行边等待。

freshPermits
现有的令牌

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值