限流算法(令牌桶漏桶计数器)

       📝个人主页:五敷有你      
 🔥系列专栏:Spring
⛺️稳中求进,晒太阳

业务重的三种情况:突发流量、恶意流量、业务本身需要

限流:   是为了保护自身系统和下游系统不被高并发流量冲垮,导致系统雪崩。

保证系统在可用的情况下尽可能增加进入的请求,其余的请求在排队等待,或者返回友好提示。保证进入系统的用户可以友好使用。

令牌桶算法

令牌桶算法是一个设定的速率产生令牌(token) 并放入令牌通,每次用户请求都得申请令牌。如果令牌不足,则拒绝请求。

        令牌桶算法中新请求到来时会从桶中拿走一个令牌,如果桶内没有i令牌可拿,就拒绝服务。

        当然令牌的数量也是有上限的。令牌的数量与时间和发放速率强相关。时间流逝的时间越长,会不断往桶里加入越多的令牌,如果令牌发送的速度比申请速度快,令牌会放满令牌桶,直到令牌占满令牌桶

令牌桶的算法特点:

好处:可以方便地应对突发出口流量。

比如:可以改变令牌发放速度(需要后端系统能力的提升),算法能按照新的发送速率调大令牌的发放数量,使得出口突发流量能被处理。

令牌生成的速度固定,消费速度不固定。

代码简单实现:

package ratelimit;


import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.logging.Logger;


public class TokenBucketLimiter {


    //桶的容量
    private static int capacity=100;
    //令牌生成速度 rate/s
    private static final int rate=50;
    //令牌数量
    private volatile static AtomicInteger tokens=new AtomicInteger(0);

    /**
     * 开启一个线程,按固定频率放入令牌桶固定个数
     */
    public static void productTokens(){
        ScheduledExecutorService scheduledExecutorService= Executors.newScheduledThreadPool(1);
        scheduledExecutorService.scheduleAtFixedRate(()->{
            int allTokens = tokens.get()+rate;
            //设置当前的tokens数量
            tokens.set(allTokens);
        },1000,1000,TimeUnit.MILLISECONDS);

    }


    /**
     * true是被限流了
     *
     * @param needCount
     * @return
     */
    public static synchronized boolean limited(int needCount){
        if(tokens.get()<needCount){

            return true;
        }

        System.out.println("此时令牌桶中数量有: "+tokens.getAndDecrement());
        return false;
    }
    public static void main(String[] args) {
        //开启生产者任务
        productTokens();
        //定义一个原子类,
        AtomicInteger atomicInteger=new AtomicInteger(0);
        ExecutorService executorService=Executors.newFixedThreadPool(5);
        for(int i=0;i<10000;i++){
            executorService.submit(()->{
                try {
                    Thread.sleep(200);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                //当前线程的名称
                String taskName=Thread.currentThread().getName();
                boolean isLimit=limited(1);
                //true被限流了
                if(isLimit){
                    System.out.println(taskName+"被限流了,累计限流次数: "+atomicInteger.incrementAndGet());
                }else {
                    System.out.println(taskName+"请求被正常处理了");
                }
            });

        }



    }




}

 

漏桶算法

漏桶(Leak Bucket) 算法限流的基本原理:

水(对应请求) 从进水口到漏桶里,漏桶以一定的速度出水(请求放行),当水流速度过大,桶内的总水量大于桶容量会直接溢出,请求拒绝。

大致的规则如下:

1)进水口(对应客户端请求) 以任意速率流入漏桶。

2)漏桶的容量是固定的,出水(放行)速率也是固定的。

3)漏桶容量是不变的,如果处理速度太慢,桶内水的容量就会超出桶的容量,则后面的水滴会标识请求拒绝。

流程:

水(请求)先进入桶中,漏桶按照一定的速率进行漏水,如果漏桶满了,那么水就会溢出(请求拒绝),可以看出来漏桶算法能强行限制数据的传输速率。

代码实现

package ratelimit;

import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;

public class LeakBucketLimiter {
    //漏桶的容量
    private static int capacity=10;
    //漏水的速度 rate/s
    private static final int leakRate=5;
    //桶中水量
    private volatile static AtomicInteger waterLeaf=new AtomicInteger(0);

    /**
     * 开启一个线程,按固定频率放入令牌桶固定个数
     */
    public static void leakWater(){
        ScheduledExecutorService scheduledExecutorService= Executors.newScheduledThreadPool(1);
        scheduledExecutorService.scheduleAtFixedRate(()->{
            //现在桶中的水
            int water = waterLeaf.get()-leakRate;
            //设置当前的水量
            waterLeaf.set(Math.max(0,water));
        },1,1, TimeUnit.SECONDS);

    }
    public static synchronized boolean limited(int waterCount){
        if(waterLeaf.get()+waterCount>capacity){
            //水满了拒绝
            return true;
        }
        waterLeaf.addAndGet(waterCount);
        System.out.println("此时漏桶水量有: "+waterLeaf);
        return false;
    }
    public static void main(String[] args) {

        //开始漏水
        leakWater();

        //开启请求
        ScheduledExecutorService executorService=Executors.newScheduledThreadPool(5);
        AtomicInteger atomicInteger=new AtomicInteger(0);
        for(int i=0;i<10000;i++){
            executorService.submit(()->{
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                String taskName=Thread.currentThread().getName();
                boolean limited = limited(1);
                if(limited){
                    System.out.println(taskName+"请求被拦截,累计拦截次数"+atomicInteger.incrementAndGet());
                }else{
                    System.out.println(taskName+"请求访问成功!!!");
                }
            });

        }



    }


}

计数器算法

        计数器算法在一段时间间隔内(时间窗/时间区间),处理请求的最大数量固定,超过部分不做处理。计数器算法是限流算法中最简单的,也是最容易实现的一种算法。

举个例子:

比如:我们规定对于A接口,我们一分钟访问次数不能超过100个。

可以这么做:

1. 在一开始的时候,我们可以设置一个计数器counter,每当一个请求过来的时候,counter就+1,如果counter的值大于100,并且该请求与第一个请求的间隔在一分钟之内,那么说明请求数过多,拒绝访问;

2. 如果该请求与第一个请求的间隔时间大于1分钟,且counter的值还在限流范围内,那么重置counter,就是这么简单粗暴

问题:临界问题

计数器限流的严重问题:这个算法虽然简单,但是有一个十分致命的问题,就是临界问题

两分钟之间的临界突发200请求,很危险!!!

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

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

相关文章

AI智剪轻松学:一键操作技巧,批量视频剪辑不求人

随着科技的飞速发展&#xff0c;人工智能已经渗透到我们生活的方方面面&#xff0c;其中AI在视频剪辑领域的应用更是为众多创作者带来了福音。AI智剪技术&#xff0c;以其高效、便捷的特点&#xff0c;正在逐步改变着传统视频剪辑的方式。今天&#xff0c;我们就来探讨一下如何…

新火种AI|清华开发首个AI医院小镇!开启智能医疗新纪元。

作者&#xff1a;小岩 编辑&#xff1a;彩云 AI技术飞速发展&#xff0c;它的影响力正在逐渐渗透到各行各业&#xff0c;医疗领域也不例外。 人生无非是生老病死&#xff0c;医疗领域与其中的“病”息息相关。所以&#xff0c;每每医疗领域产生什么重大进展&#xff0c;都会…

ranger配置ha高可用方案

变更影响面 变更完需要重启所有组件 配置lb(需要客户侧配置并提供LB地址) 转发方式选择ip hash(哈希) 监听端口为6080 协议为tcp 配置后端监听

考研数学|24像张宇那样的题?李林880和李永乐660不够用了?

以前的卷子就不说了&#xff0c;就说说最近的24年的考研数学题 24年考研数学真题评价&#xff1a; 首先数学二在计算量上超过了数学三&#xff0c;尤其是在高等数学的选择题部分&#xff0c;这使得数学二的难度可能略高于数学三&#xff0c;尽管两者之间并没有本质的差异。与…

测试二(测试点)

能掌握80% 一、能对穷举场景设计测试点 能对穷举场景设计测试点——>等价类划分法 1.1、等价类划分法 1.1.1. 说明 | 分类 | 步骤 说明&#xff1a;在所有测试数据中&#xff0c;具有某种共同特征的数据集合进行划分。 分类&#xff1a;有效等价类&#xff1a;满足…

Multisim14 安装教程

1、下载压缩包 链接&#xff1a;https://pan.baidu.com/s/1L50kBBKWFtud6GhmmqHLiw?pwd8888 提取码&#xff1a;8888 2、解压 3、运行应用程序&#xff0c;开始安装&#xff0c; 4、点击确定 5、点击unzip&#xff0c;解压 6、点击确定 7、点击安装 8、填写name和organ&a…

排序-快速排序(Quick Sort)

快排的简介 快速排序&#xff08;Quick Sort&#xff09;是一种高效的排序算法&#xff0c;采用分治法的策略&#xff0c;其基本思想是选择一个基准元素&#xff0c;通过一趟排序将待排序的数据分割成独立的两部分&#xff0c;其中一部分的所有数据都比另外一部分的所有数据要…

pywinauto,一款Win自动化利器!

pywinauto&#xff0c;一款Win自动化利器&#xff01; 1.安装 pywinauto是一个用于自动化Python模块&#xff0c;适合Windows系统的软件&#xff08;GUI&#xff09;&#xff0c;可以通过Pywinauto遍历窗口&#xff08;对话框&#xff09;和窗口里的控件&#xff0c;也可以控…

11、FreeRTOS 队列、队列集,邮箱的使用

文章目录 一、队列的特性1.1 队列常规操作1.2 传输数据的两种方法1.3 队列的阻塞访问 二 队列函数2.1创建2.2 复位2.3 删除2.4 写队列2.5 读队列2.6 查询2.7 覆盖/偷看 三、示例3.1示例 队列的基本使用3.2 示例: 分辨数据源3.3 示例: 传输大块数据3.4 : 邮箱(Mailbox) 四、队列…

多人同时导出 Excel 干崩服务器!新来的阿里大佬给出的解决方案太优雅了!

前言 业务诉求&#xff1a;考虑到数据库数据日渐增多&#xff0c;导出会有全量数据的导出&#xff0c;多人同时导出可以会对服务性能造成影响&#xff0c;导出涉及到mysql查询的io操作&#xff0c;还涉及文件输入、输出流的io操作&#xff0c;所以对服务器的性能会影响的比较大…

十进制整数转平衡三进制

求解原视频&#xff1a;平衡三进制 求赞&#xff01;100赞买个乒乓球拍&#xff01;_哔哩哔哩_bilibili 题目&#xff1a; 上海市计算机学会竞赛平台 | YACS 求解程序&#xff1a; using namespace std; #include <iostream> #include <cstring>string work(int n…

网页版五子棋的自动化测试

目录 前言 一、主要技术 二、测试环境的准备部署 三、测试用例 四、执行测试 4.1、公共类设计 创建浏览器驱动对象 测试套件 释放驱动类 4.2、功能测试 登录页面 注册页面 游戏大厅页面 游戏房间页面 测试套件结果 4.3、界面测试 登录页面 注册页面 游戏大…

【Linux基础】Vim保姆级一键配置教程(手把手教你把Vim打造成高效率C++开发环境)

目录 一、前言 二、安装Vim 三、原始Vim编译器的缺陷分析 四、Vim配置 &#x1f95d;预备知识----.vimrc 隐藏文件 &#x1f34b;手动配置 Vim --- &#xff08;不推荐&#xff09; &#x1f347;自动化一键配置 Vim --- (强烈推荐) ✨功能演示 五、共勉 一、前言 Vim作为…

如何8步完成hadoop单机安装

前言 Hadoop是一个开源框架&#xff0c;用于存储和处理大规模数据集。 系统要求 Ubuntu 20.044GB&#xff08;建议8GB&#xff09;hadoop-3.3.6 步骤1&#xff1a;更新系统 打开终端并输入以下命令来更新您的系统&#xff1a; apt update 步骤2&#xff1a;安装Java Had…

NSSCTF Web方向的例题和相关知识点(一)

[SWPUCTF 2021 新生赛]jicao 解题&#xff1a; 打开环境&#xff0c;是一段php代码 包含了flag.php文件&#xff0c;设定了一个POST请求的id和GET请求的json 语句会对GET请求的数据进行json解码 如果id和json变量的值都等于设定字符串&#xff0c;则得到 flag 我们可以使用…

测试人的福音:开源流量回放工具快速上手实践

笔者前段时间在参加测开大会时了解到了一款开源的自动化回归测试工具 AREX。主要是通过复制线上真实流量到测试环境进行回归测试&#xff0c;同时还做到了接口返回值的比对和写接口的验证&#xff0c;回放不会产生真实的数据或者调用&#xff0c;都是基于 Mock 数据的&#xff…

VastGaussian:用于大型场景重建的巨大3D高斯函数

VastGaussian:用于大型场景重建的巨大3D高斯函数 摘要IntroductionRelated WorkPreliminariesMethod VastGaussian: Vast 3D Gaussians for Large Scene Reconstruction. 摘要 现有基于NeRF的大型场景重建方法在视觉效果和渲染速度方面往往存在限制。虽然最近的3D高斯分裂在小…

基于Python的校园舆情管理系统(附源码、文档说明)

博主介绍&#xff1a;✌IT徐师兄、7年大厂程序员经历。全网粉丝15W、csdn博客专家、掘金/华为云//InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;&#x1f3…

SpringAMQP-消息转换器

这边发送消息接收消息默认是jdk的序列化方式&#xff0c;发送到服务器是以字节码的形式&#xff0c;我们看不懂也很占内存&#xff0c;所以我们要手动设置一下 我这边设置成json的序列化方式&#xff0c;注意发送方和接收方的序列化方式要保持一致 不然回报错。 引入依赖&#…

微信小程序之转盘抽奖

1. 实现效果 2. 实现过程 话不多说&#xff0c;直接上代码 /**index.wxml */ <view class"title">旋转大转盘</view> <view class"rote-box fcc"><view class"box fcc"><image class"bg" src"/stat…