Java限流之令牌桶与漏桶

  • 介绍 
     1.常见限流算法常用的限流算法有:令牌桶,漏桶、滑动窗口算法。
     2.市面上常用实现限流框架 有Nginx+Lua、Guava、Hystrix等  
  1. 令牌桶算法原理 
    以规定的速率往令牌桶中存入Token,用户请求必须获取到令牌中的Token才可以处理请求,如果没有从令牌桶中获取到令牌则丢失该请求。
    例如:令牌桶中最多只能存放20个Token,以规定速率存入Token实现在高并发情况下限流
    优势:控制请求的速率匀速相等的  1s/10r 
      
  2. 漏桶实现原理
    漏桶算法思路很简单,水(请求)先进入到漏桶里,漏桶以一定的速度出水,当水流入速度过大会直接溢出,可以看出漏桶算法能强行限制数据的传输速率。  
      
     
  3. 漏洞算法与令牌桶算法区别
    漏桶算法与令牌桶算法在表面看起来类似,很容易将两者混淆。但事实上,这两者具有截然不同的特性,且为不同的目的而使用。
    漏桶算法与令牌桶算法的区别在于,漏桶算法能够强行限制数据的传输速率,令牌桶算法能够在限制数据的平均传输速率的同时还允许某种程度的突发传输。
    需要注意的是,在某些情况下,漏桶算法不能够有效地使用网络资源,因为漏桶的漏出速率是固定的,所以即使网络中没有发生拥塞,漏桶算法也不能使某一个单独的数据流达到端口速率。因此,漏桶算法对于存在突发特性的流量来说缺乏效率。而令牌桶算法则能够满足这些具有突发特性的流量。通常,漏桶算法与令牌桶算法结合起来为网络流量提供更高效的控制。  
     
  4. 基于RateLimiter实现QPS限流
    RateLimiter是基于“令牌通算法”来实现限流的。 
    <dependency>
        <groupId>com.google.guava</groupId>
        <artifactId>guava</artifactId>
    </dependency>
    
    
        // 表示每秒往令牌桶中存入1个token, 具体根据服务器配置设置
        private RateLimiter rateLimiter = RateLimiter.create(1); 
    
    	// 每秒中限制1个请求  0:表示等待超时时间,设置0表示不等待,直接拒绝请求
    	boolean tryAcquire = rateLimiter.tryAcquire(0, TimeUnit.SECONDS);
    	if (!tryAcquire) { // 如果tryAcquire:false表示没有获取到token
    	    return "现在抢购的人数过多,请稍等一下下哦!";
    	}
    
     
  5.  基于Semaphore(信号量)实现线程数限流 
     Semaphore是基于“漏通算法”来实现限流的。 底层采用AQS原理
    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.Semaphore;
    
    @RestController
    public class LimitController {
    
        // 1. 设置容器为2  底层基于AQS实现
        public static Semaphore semaphore = new Semaphore(2);
    
        @GetMapping("limit1")
        public String index(@RequestParam(name = "num", defaultValue = "1") int num) {
            boolean b = false;
            try {
                // 2. 获取信号量  进行减1操作
                b = semaphore.tryAcquire();
                if (!b) {
                    return "我被限流了";
                }
                Thread.sleep(2000);
                return "执行业务代码:" + (num);
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                // 3. 释放信号量  进行加1操作
                if (b) {
                    semaphore.release();
                }
            }
            return null;
        }
    }
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值