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

       📝个人主页:五敷有你      
 🔥系列专栏: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/sprivate 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/sprivate 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请求,很危险!!!

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

数据中心--AI时代的“炼油厂”

数据中心正在成为AI时代的“炼油厂”&#xff01; 众所周知&#xff0c;AI的高歌猛进催生了对数据的海量处理需求。为了满足蓬勃的算力需求&#xff0c;全球开启了新一轮的数据中心建设热潮&#xff0c;数据中心业务正在以指数级的速度疯狂扩张。 此番情景&#xff0c;和第二…

Git系列:git grep 被忽视的操作细节

&#x1f49d;&#x1f49d;&#x1f49d;欢迎莅临我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:「stormsha的主页」…

java面试题(常见集合)

算法复杂度分析 时间复杂度分析 时间复杂度分析&#xff1a;来评估代码的执行耗时的 大O表示法&#xff1a;不具体表示代码真正的执行时间&#xff0c;而是表示代码执行时间随数据规模增长的变化趋势 空间复杂度 空间复杂度的全称是渐进空间复杂度&#xff0c;表示算法占用…

webpack5以下的项目,前端引入node的path模块需要额外配置

webpack5以下的项目&#xff0c;前端import * as path from path时需要额外配置&#xff0c;这里以vue.config.js为例 刚开始引入时报错 其实就是在打包前端项目的时候&#xff0c;将path模块替换成 path-browserify 模块&#xff0c;所以还需要安装 path-browserfify 模块 …

【Linux】磁盘文件

思维导图 学习目标 了解磁盘的物理结构和存储结构&#xff0c;并将其存储结构进行抽象&#xff01;&#xff01; 一、了解一下磁盘及其物理结构 1.1 计算机只认识二进制 什么是二进制&#xff1f;&#xff1f;0&#xff0c;1是被规定出来的&#xff0c;在计算机里面我们用高低…

Excel Module: Iteration #1 EasyExcel生成下拉列表模版时传入动态参数查询下拉数据

系列文章 EasyExcel生成带下拉列表或多级级联列表的Excel模版自定义校验导入数据(修订) 目录 系列文章前言仓库一、实现1.1 下拉元数据对象1.2 构建下拉元数据的映射关系1.3 框架方式1.3.1 框架实现1.3.2 框架用例模版类加载下拉业务导出接口 1.4 EasyExcel方式1.4.1 EasyExce…

灵活QinQ

拓扑图 配置 sysname AR1 # interface GigabitEthernet0/0/0.10dot1q termination vid 10ip address 12.1.1.1 255.255.255.0 arp broadcast enable # interface GigabitEthernet0/0/0.20dot1q termination vid 20ip address 21.1.1.1 255.255.255.0 arp broadcast enable # …

重学SpringBoot3-SPI机制

更多SpringBoot3内容请关注我的专栏&#xff1a;《SpringBoot3》 期待您的点赞&#x1f44d;收藏⭐评论✍ 重学SpringBoot3-SPI机制 什么是 SPI&#xff1f;Spring Boot 中的 SPI 机制spring.factories 文件自动配置的实现启动流程中的作用 SPI实际应用步骤 1: 新建模块步骤 2:…

(超详细讲解)实现将idea的java程序打包成exe (新版,可以在没有java的电脑下运行,即可以发给好朋友一起玩)

目录 实现打包到exe大概步骤 工具准备 1.将java程序文件打包成jar文件 2.准备好jre文件 3.使用exe4j软件打包好 4.最终打包 实现打包到exe大概步骤 1.打包需要满足的条件&#xff1a;将java文件转成jar文件的工具exe4j、 以及需要满足jdk1.8以上&#xff08;因安装exe4…

Embedding技术学习

可能很多人并没有关注Embedding技术&#xff0c;但实际上它是GPT非常重要的基础&#xff0c;准备的说&#xff0c;它是GPT模型中理解语言/语义的基础。 【解释什么是Embedding】 对于客观世界&#xff0c;人类通过各种文化产品来表达&#xff0c;比如&#xff1a;语言&#x…

如何快速提取出一个文件里面全部指定类型的文件的全部路径

首先&#xff0c;需要用到的这个工具&#xff1a; 度娘网盘 提取码&#xff1a;qwu2 蓝奏云 提取码&#xff1a;2r1z 打开工具&#xff0c;切换到第五个模块&#xff0c;文件批量复制模块&#xff08;快捷键&#xff1a;Ctrl5&#xff09; 点击右边的“搜索添加”按钮&#…

unordered系列关联式容器底层哈希结构的介绍,哈希表的模拟实现(哈希冲突的解决方法采用闭散列线性探测)

目录 前言 unordered系列关联式容器之所以处理数据的效率比较高&#xff0c;是因为底层使用了哈希结构&#xff0c;哈希结构的优点是&#xff1a;不经过任何比较&#xff0c;一次直接从表中得到要搜索的元素&#xff0c;通过某种函数(hashFunc)使元素的存储位置与它的关键码之…

mapreduce | 自定义Partition分区(案例2)

1.需求 统计每个手机号消费总金额&#xff0c;按照消费金额降序排序&#xff0c;最终联通、电信、移动分别写入不同的文件。 130、131、132&#xff08;联通&#xff09; 133&#xff08;电信&#xff09; 135、136、137、138、139 &#xff08;移动&#xff09; 手机号,消费记…

全局变量在函数中的使用:Python 编程技巧解析

在Python编程中&#xff0c;全局变量是一种在程序的多个部分中共享数据的机制。全局变量在函数中使用时&#xff0c;需要特别注意其作用域和访问方式。本文将详细讲解如何在函数中使用全局变量&#xff0c;并提供示例代码&#xff0c;帮助初学者深入理解这一概念。 基本原理 …

AI作画涉及的深度学习算法

AI作画中使用的深度学习算法多种多样&#xff0c;这些算法主要基于神经网络的结构和训练方式&#xff0c;以生成和改进艺术作品。以下是一些在AI作画中常用的深度学习算法&#xff1a; 生成对抗网络&#xff08;GANs, Generative Adversarial Networks&#xff09;&#xff1a…

Linux —— 线程

Linux —— 线程 什么是线程Linux如何实现线程Winodws如何实现线程使用一下线程pthread_create函数原型参数说明返回值 如何解决 ps -aL 查看线程线程为什么轻量 我们今天进入线程的学习&#xff1a; 什么是线程 我们先来了解一个笼统的概念&#xff1a;简单来说&#xff0c;…

计算机发展史故事【12】

芯片计算机 众所周知&#xff0c;所谓286、386、486 个人电脑等名称的起源&#xff0c;在于它们采用了英特尔公司研制的微处理器X86 系列芯片286、386 和486。然而&#xff0c;这种以数字为电脑命名的奇特现象&#xff0c;却来源于霍夫博士等人发明的世界上第一个微处理器芯片…

动态路由-链路状态路由协议ospf案例

实验拓扑和要求如图 ospf实验 1.设置各个接口地址 2.测试ar5到ar6的连通性 3.配置ospf协议&#xff0c;routerid&#xff0c;area&#xff0c; 详细的网络信息&#xff0c;等待网络收敛后&#xff0c; 查看ospf信息&#xff0c;路由表信息&#xff0c;再次测试连通性 注意区域…

防火墙技术基础篇:网络地址转换(NAT):防火墙技术的核心机制

防火墙技术基础篇&#xff1a;网络地址转换&#xff08;NAT&#xff09;&#xff1a;防火墙技术的核心机制 网络地址转换&#xff08;NAT&#xff09;是现代网络架构中不可或缺的一个组成部分&#xff0c;尤其在防火墙技术的实现中扮演着重要角色。本文旨在全面解读NAT的工作机…

AI算法-高数5.1-线性代数-向量定义、表示和向量间的关系

看线性代数这篇文章&#xff08;AI算法-高数5-线性代数1-基本概念、向量-CSDN博客&#xff09;理解有些吃力的朋友们&#xff0c;可以先学下宋浩老师的这些课程。 宋浩老师&#xff1a; 3.1 n维向量及其运算_哔哩哔哩_bilibili 3.2 向量间的线性关系&#xff08;一&#xff…