4种常见的限流算法

限流算法

1、固定窗口

含义: 在一个固定长度的时间窗口内限制请求数量,每来一个请求,请求次数加一,如果请求数量超过最大限制,就拒绝该请求
优点: 实现简单,容易理解。
缺点: ①限流不够平滑。例如:限流是每秒3个,在第一毫秒发送了3个请求,达到限流,窗口剩余时间的请求都将会被拒绝,体验不好。
②无法处理窗口边界问题。因为是在某个时间窗口内进行流量控制,所以可能会出现窗口边界效应,即在时间窗口的边界处可能会有大量的请求被允许通过,从而导致突发流量

public class FixWindowLimiter {

    /**
     * 每个窗口的最大请求数量
     */
    public static long threshold = 10;
    /**
     * 窗口大小,1000ms
     */
    public static long windowUnit = 1000;
    /**
     * 窗口内的当前请求数量
     */
    public static long count = 0;
    /**
     * 窗口的开始时间
     */
    public static long lastTime = 0;

    /**
     * 限流方法,返回true表示通过
     */
    public boolean limit() {
        // 获取系统当前时间
        long currentTime = System.currentTimeMillis();
        // 判断是否在当前时间窗口内,如果不在就开启一个新的时间窗口
        if (currentTime - lastTime > windowUnit) {
            // 计数器清零
            count = 0;
            // 开启新的时间窗口
            lastTime = currentTime;
        }
        // 判断是否超过最大请求量
        if (count < threshold) {
            count++;
            return true;
        }
        return false;
    }

}

2、滑动窗口

定义:每来一个请求,就向后推一个时间窗口,计算这个窗口内的请求数量。如果请求数量超过限制就拒绝请求,否则就处理请求,并记录请求的时间戳。另外还需要一个任务清理过期的时间戳。
优点: 解决了固定窗口算法的窗口边界问题,避免突发流量压垮服务器。
缺点: 还是存在限流不够平滑的问题

public class SlidingWindowLimiter {

    /**
     * 每个窗口的最大请求数量
     */
    public static long threshold = 10;
    /**
     * 窗口大小,1000ms
     */
    public static long windowUnit = 1000;
    /**
     * 请求集合,用来存储窗口内的请求数量
     */
    public static List<Long> requestList = new ArrayList<>();

    /**
     * 限流方法,返回true表示通过
     */
    public boolean limit() {
        // 获取系统当前时间
        long currentTime = System.currentTimeMillis();
        // 统计当前窗口内,有效的请求数量
        int sizeOfValid = this.sizeOfValid(currentTime);
        // 判断是否超过最大请求数量
        if (sizeOfValid < threshold) {
            // 把当前请求添加到请求集合里
            requestList.add(currentTime);
            return true;
        }
        return false;
    }

    /**
     * 统计当前窗口内,有效的请求数量
     */
    private int sizeOfValid(long currentTime) {
        int sizeOfValid = 0;
        for (Long requestTime : requestList) {
            // 判断是否在当前时间窗口内
            if (currentTime - requestTime <= windowUnit) {
                sizeOfValid++;
            }
        }
        return sizeOfValid;
    }

    /**
     * 清理过期的请求(单独启动一个线程处理)
     */
    private void clean() {
        // 判断是否超出当前时间窗口内
        requestList.removeIf(requestTime -> System.currentTimeMillis() - requestTime > windowUnit);
    }

}

3、漏桶算法

定义:一个固定容量的漏桶,按照固定速率出水(处理请求); 当流入水(请求数量)的速度过大会直接溢出(请求数量超过限制则直接拒绝)。桶里的水(请求)不够则无法出水(桶内没有请求则不处理)
优点:
①平滑流量。由于漏桶算法以固定的速率处理请求,可以有效地平滑和整形流量,避免流量的突发和波动(类似于消息队列的削峰填谷的作用)。
②防止过载。当流入的请求超过桶的容量时,可以直接丢弃请求,防止系统过载。
缺点:
①无法处理突发流量:由于漏桶的出口速度是固定的,无法处理突发流量。例如,即使在流量较小的时候,也无法以更快的速度处理请求。
②可能会丢失数据:如果入口流量过大,超过了桶的容量,那么就需要丢弃部分请求。在一些不能接受丢失请求的场景中,这可能是一个问题。
③不适合速率变化大的场景

public class LeakyBucketLimiter {

    /**
     * 桶的最大容量
     */
    public static long threshold = 10;
    /**
     * 桶内当前水量
     */
    public static long count = 0;
    /**
     * 漏水速率(每秒5次)
     */
    public static long leakRate = 5;
    /**
     * 上次漏水时间
     */
    public static long lastLeakTime = System.currentTimeMillis();

    /**
     * 限流方法,返回true表示通过
     */
    public boolean limit() {
        // 调用漏水方法
        this.leak();
        // 判断是否超过最大请求数量
        if (count < threshold) {
            count++;
            return true;
        }
        return false;
    }

    /**
     * 漏水方法,计算并更新这段时间内漏水量
     */
    private void leak() {
        // 获取系统当前时间
        long currentTime = System.currentTimeMillis();
        // 计算这段时间内,需要流出的水量
        long leakWater = (currentTime - lastLeakTime) * leakRate / 1000;
        count = Math.max(count - leakWater, 0);
        lastLeakTime = currentTime;
    }

}

4、令牌桶

在这里插入图片描述

定义: 统以固定的速率向桶中添加令牌; 当有请求到来时,会尝试从桶中移除一个令牌,如果桶中有足够的令牌,则请求可以被处理或数据包可以被发送;
如果桶中没有令牌,那么请求将被拒绝; 桶中的令牌数不能超过桶的容量,如果新生成的令牌超过了桶的容量,那么新的令牌会被丢弃
令牌桶算法的一个重要特性是,它能够应对突发流量。当桶中有足够的令牌时,可以一次性处理多个请求,这对于需要处理突发流量的应用场景非常有用
优点:
①可以处理突发流量:令牌桶算法可以处理突发流量。当桶满时,能够以最大速度处理请求。这对于需要处理突发流量的应用场景非常有用。
②限制平均速率:在长期运行中,数据的传输率会被限制在预定义的平均速率(即生成令牌的速率)。
③灵活性:与漏桶算法相比,令牌桶算法提供了更大的灵活性。例如,可以动态地调整生成令牌的速率。
缺点:
①可能导致过载:如果令牌产生的速度过快,可能会导致大量的突发流量,这可能会使网络或服务过载。
②需要存储空间:令牌桶需要一定的存储空间来保存令牌,可能会导致内存资源的浪费。
③实现稍复杂:相比于计数器算法,令牌桶算法的实现稍微复杂一些

public class TokenBucketLimiter {

    /**
     * 桶的最大容量
     */
    public static long threshold = 10;
    /**
     * 桶内当前的令牌数量
     */
    public static long count = 0;
    /**
     * 令牌生成速率(每秒5次)
     */
    public static long tokenRate = 5;
    /**
     * 上次生成令牌的时间
     */
    public static long lastRefillTime = System.currentTimeMillis();

    /**
     * 限流方法,返回true表示通过
     */
    public boolean limit() {
        // 调用生成令牌方法
        this.refillTokens();
        // 判断桶内是否还有令牌
        if (count > 0) {
            count--;
            return true;
        }
        return false;
    }

    /**
     * 生成令牌方法,计算并更新这段时间内生成的令牌数量
     */
    private void refillTokens() {
        long currentTime = System.currentTimeMillis();
        // 计算这段时间内,需要生成的令牌数量
        long refillTokens = (currentTime - lastRefillTime) * tokenRate / 1000;
        count = Math.min(count + refillTokens, threshold);
        lastRefillTime = currentTime;
    }

}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/226234.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Ngxin实现301重定向映射

要实现将abc.love域名映射到http://baidu.com网站&#xff0c;并进行重定向&#xff0c;你需要在Nginx的配置文件中添加一个新的server块&#xff0c;如下所示&#xff1a; server {listen 80;server_name abc.com; #替换成自己的域名&#xff0c;记得要映射到这台服务器&…

element UI改写时间线组件为左右分布

2023.12.4今天我学习了如何使用element的时间线组件&#xff0c;效果如&#xff1a; 代码如下&#xff1a;&#xff08;关键代码 v-if"item.send_type"&#xff09;判断左右分布情况。因为如果没有这个判断的话&#xff0c;其实会两边都有显示。可以用一个判断表示0显…

OpenEuler_22.03升级mongdb到7.0.4

使用命令&#xff1a;lscpu&#xff0c;查看cpu架构为aarch64为arm架构的一种执行状态。 所以我们直接下载arm的包安装即可。无需自己编译源码。 下载地址&#xff1a;https://www.mongodb.com/try/download/community 下载解压 wget https://fastdl.mongodb.org/linux/mong…

使用腾讯逆地理位置编码获取地理位置信息

文章目录 前言一、代码二、开放平台操作步骤1.开发者认证2.创建应用 总结 前言 最近项目中一个发帖的功能需要获取当前用户的发帖位置&#xff0c;由于是在APP内部使用&#xff0c;而且APP是使用uniApp开发的&#xff0c;所以在使用开放平台的SDK选用上有些麻烦&#xff0c;有…

echarts环形饼图

效果示例 代码汇总 pieCharts() {let data [];const providerResult [{name: 智诺, value: 23},{name: 海康, value: 5},{name: 大华, value: 5}, {name: 云科, value: 23},{name: 四信, value: 22},{name: 九物, value: 22}]let charts echarts.init(document.getElemen…

11K+ Star!图解计算机网络、操作系统、计算机组成、数据库!

大家好&#xff0c;我是 Java陈序员。 俗话说得好&#xff0c;面试造火箭&#xff0c;入职拧螺丝。我们在工作中&#xff0c;其实很少用到一些计算机底层知识&#xff0c;往往只要编码完事。但是&#xff0c;知其然还要知其所以然&#xff0c;我们不仅要做一个合格的“CV 工程…

Vector Quantized Diffusion Model for Text-to-Image Synthesis

Vector Quantized Diffusion Model for Text-to-Image Synthesis Shuyang Gu, University of Science and Technology of China, Microsoft, CVPR2022, Cited: 340, Code, Paper 1. 前言 我们提出了用于文本到图像生成的矢量量化扩散(Vector Quantized Diffusion Model&…

JavaScript如何实现按键音效、视频播放,标签分类切换横向滚动

1.使用HTML5的audio标签 &#xff08;音频播放&#xff09; <audio id"click-sound"><source src"audio/show.mp3" type"audio/mpeg"> </audio> <button id"button">按钮</button> var clickSound d…

北京市经信局局长姜广智带队调研三六零 强调大模型应与行业结合

12月6日&#xff0c;北京市经济和信息化局局长姜广智、副局长王磊带队走访调研三六零集团&#xff0c;就共促城市级数字安全基础设施项目落地&#xff0c;打造引领行业发展标杆项目&#xff0c;推动大模型落地应用赋能产业、行业发展等话题进行交流。360集团创始人周鸿祎接待来…

【FPGA】Quartus18.1打包封装网表文件(.qxp)详细教程

当我们在做项目的过程中&#xff0c;编写的底层Verilog代码不想交给甲方时怎么办呢&#xff1f;此时可以将源代码打包封装成网表文件&#xff08;.qxp&#xff09;进行加密&#xff0c;并且在工程中进行调用。 Quartus II的.qxp文件为QuartusII Exported Partition&#xff0c;…

探索 Linux Namespace:Docker 隔离的神奇背后

来自&#xff1a;探索云原生 https://www.lixueduan.com 原文&#xff1a;https://www.lixueduan.com/posts/docker/03-container-core/ 在 深入理解 Docker 核心原理&#xff1a;Namespace、Cgroups 和 Rootfs 一文中我们分析了 Docker 是由三大核心技术实现的。 今天就一起分…

C++多态(详解)

一、多态的概念 1.1、多态的概念 多态&#xff1a;多种形态&#xff0c;具体点就是去完成某个行为&#xff0c;当不同的对象去完成时会产生出不同的状态。 举个例子&#xff1a;比如买票这个行为&#xff0c;当普通人买票时&#xff0c;是全价买票&#xff1b;学生买票时&am…

【离散数学】——期末刷题题库(等价关系与划分)

&#x1f383;个人专栏&#xff1a; &#x1f42c; 算法设计与分析&#xff1a;算法设计与分析_IT闫的博客-CSDN博客 &#x1f433;Java基础&#xff1a;Java基础_IT闫的博客-CSDN博客 &#x1f40b;c语言&#xff1a;c语言_IT闫的博客-CSDN博客 &#x1f41f;MySQL&#xff1a…

漏洞复现-速达软件全系产品存在任意文件上传漏洞(附漏洞检测脚本)

免责声明 文章中涉及的漏洞均已修复&#xff0c;敏感信息均已做打码处理&#xff0c;文章仅做经验分享用途&#xff0c;切勿当真&#xff0c;未授权的攻击属于非法行为&#xff01;文章中敏感信息均已做多层打马处理。传播、利用本文章所提供的信息而造成的任何直接或者间接的…

12/07

#include "widget.h"Widget::Widget(QWidget *parent): QWidget(parent) {//设置面板框this->resize(1000,580); //设置尺寸大小this->setFixedSize(1000,580); //固定尺寸大小this->setWindowFlag(Qt::Frameles…

XC4060 40V降5V/3.3V 0.6A小电流高耐压芯片 适用于单片机供电输出、电池供电设备

XC4060器件是高效率&#xff0c;同步降压DC/DC稳压器。具有较宽的输入范围&#xff0c;它们适用于广泛的应用&#xff0c;例如来自非稳压源的功率调节。他们的特点是一个长距离(500mQ/300mQ2型) 内部开关的效率最高 (92%)。Sum od (非A选项)和PWM模式(A选项)&#xff0c;工作频…

IDEA maven无法下载源代码处理

1、使用idea内置maven 在idea中新增一个mvn运行项,截图如下: 输入命令: dependency:resolve -Dclassifiersources 2、如果外部maven&#xff0c;不使用idea内部maven 在工程目录下命令行执行命令: mvn dependency:resolve -Dclassifiersources

simulink中 Data store memory、write和read模块及案例介绍

目录 1.Data store memory模块 2.data store write模块 3.data store read模块 4.仿真分析 4.1简单使用三个模块 4.2 模块间的调用顺序剖析 1.Data store memory模块 向右拖拉得到Data store read模块&#xff0c;向左拉得到Data write模块 理解&#xff1a;可视为定义变量…

C++ 函数详解

目录 函数概述 函数的分类 函数的参数 函数的调用 函数的嵌套调用 函数的链式访问 函数声明和定义 函数递归 函数概述 函数——具有某种功能的代码块。 一个程序中我们经常会用到某种功能&#xff0c;如两数相加&#xff0c;如果每次都在需要用到时实现&#xff0c;那…

有了安卓模拟器,就能在Windows 10或11上像使用安卓操作系统一样使用安卓

你可以使用Android模拟器在Windows 11或Windows 10中运行Android应用程序。如果你喜欢的应用程序只在手机上运行,但你想在电脑上使用,这些模拟器会很有用。 BlueStacks 与整个操作系统模拟器不同,BlueStacks只在Windows上模拟Android应用程序。它真的很容易使用,所以你不需…