首页 > 编程语言 >限流算法

限流算法

时间:2022-12-13 08:33:14浏览次数:73  
标签:令牌 return long 算法 限流 private now

1.为什么要限流

  • 系统上游流量未知,如果超载引起雪崩。
  • 系统下游吞吐能力一般,直连带宽有限。

2.常见的几种限流算法

  1. 计数器限流

    在一段时间间隔内,对请求进行计数,与阀值进行比较判断是否需要限流,一旦到了时间临界点,将计数器清零

    优点:简单

    缺点:很难处理单位时间内的临界问题

 

  demo代码示例:

public class CountLimiter implements Limiter {       //时间窗口     private long timeStamp= System.currentTimeMillis();     //请求次数     private int reqCount;     //时间间隔     private long interval=1000;     //限流次数     private long limitNum=100;       /**      * (单机限流,分布式限流用 redis)      * 返回 true 代表限流, false 代表通过      * @return      */     @Override     public synchronized Boolean limit(){         long now = System.currentTimeMillis();           //判断当前时         if(now<timeStamp+interval){             //判断档期窗口内请求次数是否超过每秒限流的最大请求次数             if(reqCount+1>limitNum){                 //限流了                 return true;             }             reqCount++;             return false;           }else {             //开启新的时间窗口             timeStamp=now;             //重置计数器             reqCount=1;             return false;           }     } }

 

  2. 滑动窗口

    把固定时间片进行划分,并且随着时间的流逝,进行移动,固定数量的可以移动的格子,进行计数并判断阀值

    优点:将固定时间段分块,时间比“计数器”复杂,适用于稍微精准的场景

    缺点:格子的数量影响着滑动窗口算法的精度,依然有时间片的概念,无法根本解决临界点问题

   demo代码示例

  

package com.example.limit;   import java.util.LinkedList;   public class SlideTimeWindowLimiter implements Limiter {       private int reqCount;     //记录滑动的窗口的10个格子     private LinkedList<Integer> slots = new LinkedList<>();     //每秒限流的最大请求次数     private int limitNum = 100;     //滑动时间窗口里的每个格子的时间长度,单位 ms     private long windowLength = 100L;     //滑动时间窗口里的格子数量     private int windowNum = 10;         @Override     public synchronized Boolean limit() {         if ((reqCount + 1) > limitNum) {             return true;         }         slots.set(slots.size() - 1, slots.peekLast() + 1);         reqCount++;         return false;     }         //滑动窗口实现     public SlideTimeWindowLimiter(){         slots.addLast(0);         new Thread(()->{             while (true){                 try {                     Thread.sleep(windowLength);                 }catch (InterruptedException e){                     e.printStackTrace();                 }                 synchronized (this){                     slots.addLast(0);                     if(slots.size()>windowNum){                         //滑动窗口,删除第一个格子,                         reqCount=reqCount-slots.peekFirst();                         slots.removeFirst();                     }                 }               }         }).start();     }     }

  3. 漏桶算法

     一个固定容量的漏桶,按照固定速率流出水滴

     特点:

        1.以任意速率往桶中放入水滴。

        2.以固定速率从桶中流出水滴。

        3.如果流入水滴超出了桶的容量,则流入的水滴溢出(新请求被拒绝)

    优点:可以很好的控制消费频率

    缺点:限制的是常量流出速率(即流出速率是一个固定常量值),所以最大的速率就是出水的速率,不能出现突发流量

demo代码示例

package com.example.limit;   public class LeakyBucketLimiter implements Limiter {       private long timeStamp=System.currentTimeMillis();     private long capacity=100;//桶的容量     private long rate=10//水漏出的速度(每秒系统能处理的请求数)     private long water=20//当前水量(当前累计的请求数)       @Override     public synchronized Boolean limit() {         long now = System.currentTimeMillis();         water = Math.max(0, water - ((now - timeStamp) / 1000) * rate);         timeStamp = now;         if ((water + 1) <= capacity) {             //加水             water++;             return false;         else {             //水满拒绝加水;             return true;         }     } }

4. 令牌桶算法

     一个固定的桶,桶里存放着令牌(token)。一开始桶是空的,系统按固定的时间(rate)往桶里添加令牌,直到桶里的令牌数满,多余的请求会被丢弃。当请求来的时候,从桶里移除一个令牌,如果桶是空的则拒绝请求或者阻塞。

     特点:

        1. 流入桶的速率一定

        2.请求需要被处理,则需要先从桶里获取一个令牌,当桶里没有令牌可取时,则拒绝服务

        3.能够应对突发流量

demo代码示例

package com.example.limit;   public class TokenBucketLimiter implements Limiter {     private long timeStamp=System.currentTimeMillis();     private long capacity=100;//桶的容量     private long rate=10// 令牌放入速度     private long tokens=20// 当前令牌数量       @Override     public Boolean limit() {         long now = System.currentTimeMillis();         //添加令牌         tokens = Math.min(capacity, tokens + (now - timeStamp) / 1000 * rate);         timeStamp = now;         if (tokens < 1) {             return true;         else {             //还有令牌,领取令牌             tokens--;             return false;         }     } }
   
写评论...

标签:令牌,return,long,算法,限流,private,now
From: https://www.cnblogs.com/guanbin-529/p/16977629.html

相关文章

  • 一文带你入木三分地理解字符串KMP算法(next指针解法)
    1.KMP算法简介温馨提示:在通篇阅读完并理解后再看简介效果更佳以下简介由百度百科提供https://baike.baidu.com/item/KMP%E7%AE%97%E6%B3%95/10951804:KMP算法是一种改......
  • 算法第五章
    1.1对于该题样例n=3,m=3,解空间为(1,1,1),(1,1,2),(1,1,3),(1,2,1),(1,2,2),(1,2,3),(1,3,1),(1,3,2),(1,3,3)(2,1,1),(2,1,2),(2,1,3......
  • Java实现LRU算法
    文章目录1、内存空间有限,当缓存满的时候,如何淘汰缓存?2、实现LRUdemo使用Java容器LinkedHashMap哈希表(HashMap)+双向链表 1、内存空间有限,当缓存满的时候,如何淘汰缓......
  • 【数据结构-树】二叉树的相关算法
    目录1计算二叉树中双分支结点的个数2交换二叉树中所有左右子树3求先序遍历第k个元素4删去值为x的子树5计算二叉树的带权路径长度(WPL)6将表达式树转化为等价的中缀......
  • 温州大学《深度学习》课程课件(六、优化算法)
    这学期我上的另一门课是本科生的《深度学习》,主要用的是吴恩达老师的《深度学习》视频课的内容。使用教材:吴恩达《深度学习》课程笔记课外参考书:《深度学习》,人民邮电出版社......
  • 基础算法学习笔记
    #笔记-基础算法快速排序将序列按从小到大或从大到小顺序排序。时间复杂度\(O(nlogn)\),不稳定。步骤确定分界点\(x\):\(q[l]\)、\(q[(l+r)\div2]\),\(q[r]\)、\(......
  • 算法基础课
    给定一个字符串SS,以及一个模式串PP,所有字符串中只包含大小写英文字母以及阿拉伯数字。模式串PP在字符串SS中多次作为子串出现。求出模式串PP在字符串SS中所有......
  • C语言 (数据结构)在顺序表中用二分查找和冒泡排序算法
    main.c:#include<stdio.h>#include<stdlib.h>#include"SequenceList.h"intmain(){//创建顺序表和指针SequenceListSL,*P_SL;intchoice=0;......
  • 优先队列算法
    publicclassBinaryHeap<AnyTypeextendsComparable<?superAnyType>>{privatestaticfinalintDEFAULT_CAPACITY=10;privateintcurrentSize;privat......
  • 算法与数据结构实验四
    实验项目名称:实验四       一、 实验目的1)掌握图的邻接矩阵、邻接表存储结构表示及其创建算法2)掌握图的深度优先搜索遍历算法和图的广度优先搜索遍历算法;3)掌握图......