限流算法深入

限流定义及目的

当系统流量达到系统或下游承受能力的阈值时对系统进行限流控制以防止系统或下游挂掉,减少影响面。

限流组成:阈值及限流策略。阈值是指系统单位时间接收到的请求qps总数;限流策略是指限流行业触发后对应的系统行为,如失败拒绝还是放入等待队列。

应用场景

如秒杀业务,商品变更消息等场景。

秒杀业务:通常来说是保护全链路系统不挂;特性是瞬时流量大;超过阈值时拒绝策略通常是返回失败。

商品变更消息:业务场景是需要将商品变更消息推送给下游商家,下游商家系统能力有限,因此需要做限制;这个场景更多是保护下游系统不挂(整条系统链路上最小短板)。

分类

4大类:计数,滑动窗口,漏桶,令牌。

计数(固定时间窗口)

单位时间窗口内进行计数,超过阈值则进行限流。

算法限制:只能限制一整秒流量。若出现第1秒中后500ms和第2秒中前500ms超过阈值则此时不生效。

实现代码

import exception.BlockException;
import java.util.concurrent.atomic.AtomicInteger;
public class CalNumProcessor {//限流窗口大小private static int WINDOW_TIME_MILL = 1000;//阈值private static final int LIMIT_NUMS = 10;//计数器private AtomicInteger count = new AtomicInteger(0);//开始时间private Long startTime;public static void main(String[] args) throws InterruptedException {CalNumProcessor calNumProcessor=new CalNumProcessor();for(int i=0;i<1000;i++){System.out.println(i);calNumProcessor.tryIncAndLimit();Thread.sleep(200);}}/*** 进行限流计数,超过限流阈值时会抛BlockException*/public void tryIncAndLimit() {//当前时间long curMill = System.currentTimeMillis();//开始时间初始化if (startTime == null) {startTime = curMill;}if ((curMill - startTime) > WINDOW_TIME_MILL) {//若时间计数超过一秒则重置计数为0并重新设置计数开始时间count.set(0);startTime = curMill;}int after = count.incrementAndGet();if (after > LIMIT_NUMS) {//超过阈值throw new BlockException();}}
}

滑动窗口

计数有个问题在于流量放大无法限流。如1秒为计数窗口。则第一秒后半秒和第二秒前半秒累计可能超过qps限制,但由于不是一个时间窗口此时反而不能限制住。

解决思路:每次请求计数每过一个时间窗口单位进行滑动计数。

整体算法思路详细

1.构建n个时间窗口单位,每个窗口单位有对应qps变量及窗口开始时间;初始化时间窗口单位的qps为0及开始时间为当前时间;

2.每次获取qps时计算当前时间应该在哪个时间窗口单位;

3.循环处理时间窗口,如果发现当前时间与时间窗口单位超过1秒(时间窗口单位最大时间)则重置窗口开始时间及qps为0。

4.将当前时间对应时间窗口qps加1;

5.返回所有时间窗口单位qps累计值;

代码实现

import java.time.LocalTime;
import java.util.concurrent.atomic.AtomicInteger;public class TimeWindow {/*** 时间窗口大小,如1秒*/private int windowTimeSize;/*** 窗口数*/private int windowNum;private Window[] windows;private int maxQps;public TimeWindow(int maxQps, int windowTimeSize, int windowNum) {this.maxQps = maxQps;this.windowTimeSize = windowTimeSize;this.windowNum = windowNum;windows = new Window[windowNum];for (int i = 0; i < windowNum; i++) {windows[i] = new Window();windows[i].setQps(new AtomicInteger(0));windows[i].setStartTime(System.currentTimeMillis());}}public static void main(String[] args) throws InterruptedException {int qps = 2;int count = 20;int sleep = 300;int success = 0;TimeWindow timeWindow = new TimeWindow(qps, 1000, 10);for (int i = 0; i < count; i++) {Thread.sleep(sleep);if (timeWindow.tryAcquire()) {success++;if (success % qps == 0) {System.out.println(LocalTime.now() + ": success, ");} else {System.out.print(LocalTime.now() + ": success, ");}} else {System.out.println(LocalTime.now() + ": fail");}}System.out.println();System.out.println("实际测试成功次数:" + success);}public boolean tryAcquire() {//计算当前时间落到哪个窗口位置int index = (int) (System.currentTimeMillis() % windowTimeSize) / (windowTimeSize / windowNum);//当前时间若超过时间累计窗口则重置窗口参数int r = 0;for (int i = 0; i < windowNum; i++) {Window curWindow = windows[i];if ((System.currentTimeMillis() - curWindow.getStartTime()) > windowTimeSize) {//当前时间减去时间窗口大于最大累计时间窗口大小则重置变量curWindow.setQps(new AtomicInteger(0));curWindow.setStartTime(System.currentTimeMillis());}//当前时间对应窗口累计qpsif (index == i) {curWindow.getQps().incrementAndGet();}r += curWindow.getQps().get();}return r <= maxQps;}class Window {/*** qps*/private AtomicInteger qps;/*** 开始时间*/private long startTime;public AtomicInteger getQps() {return qps;}public void setQps(AtomicInteger qps) {this.qps = qps;}public long getStartTime() {return startTime;}public void setStartTime(long startTime) {this.startTime = startTime;}}
}

 漏桶算法

流出衡定,不能应对突发流量,能较好保护下游。

令牌算法

优:能处理突出流量,流入相对衡定,流出允许有波动。秒杀场景适用。

这里核心概念:令牌桶(有令牌数及桶上限2个参数),令牌,获取令牌,存放令牌;

存放令牌策略有:1、有单独线路每秒加入n个令牌(相当于qps为n);2、懒计算:当获取令牌请求到来时进行计算,计算思路:Math.min(当前时间距离上次已存放令牌时间间隔秒数*令牌qps,令牌数上限)。

代码

 RateLimiter rateLimiter = RateLimiter.create(2);for (int i = 0; i < 10; i++) {String time = LocalDateTime.now().format(DateTimeFormatter.ISO_LOCAL_TIME);System.out.println(time + ":" + rateLimiter.tryAcquire());Thread.sleep(250);}

实现产品

guava,阿里的sentinal。TODO。

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

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

相关文章

FPGA GTX全网最细讲解,aurora 8b/10b协议,HDMI板对板视频传输,提供2套工程源码和技术支持

目录 1、前言免责声明 2、我这里已有的 GT 高速接口解决方案3、GTX 全网最细解读GTX 基本结构GTX 发送和接收处理流程GTX 的参考时钟GTX 发送接口GTX 接收接口GTX IP核调用和使用 4、设计思路框架视频源选择IT6802解码芯片配置及采集动态彩条视频数据组包GTX aurora 8b/10b数据…

Django(5)-视图函数和模板渲染

Django 中的视图的概念是「一类具有相同功能和模板的网页的集合」 在我们的投票应用中&#xff0c;我们需要下列几个视图&#xff1a; 问题索引页——展示最近的几个投票问题。 问题详情页——展示某个投票的问题和不带结果的选项列表。 问题结果页——展示某个投票的结果。 投…

SVN 项目管理笔记

SVN 项目管理笔记 主要是介绍 SVN 管理项目的常用操作&#xff0c;方便以后查阅&#xff01;&#xff01;&#xff01; 一、本地项目提交到SVN流程 在SVN仓库下创建和项目名同样的文件夹目录&#xff1b;选中本地项目文件&#xff0c;选择SVN->checkout,第一个是远程仓库项…

大数据Flink实时计算技术

1、架构 2、应用场景 Flink 功能强大&#xff0c;支持开发和运行多种不同种类的应用程序。它的主要特性包括&#xff1a;批流一体化、精密的状态管理、事件时间支持以及精确一次的状态一致性保障等。在启用高可用选项的情况下&#xff0c;它不存在单点失效问题。事实证明&#…

vue 学习笔记 简单实验

1.代码(html) <script src"https://unpkg.com/vuenext" rel"external nofollow" ></script> <div id"counter">Counter: {{ counter }} </div> <script> const Counter {data() {return {counter: 5}} } Vue.cr…

java-便签

--其实最痛的。不是离别。而是离别后的那些回忆。 java length( ) javalength中文占多长 1.一个中文字符或符号 2 个字节&#xff0c;一个英文字符或符号 1 个字节。 System.out.println("abc你好&#xff0c;".getBytes("gbk").length); System.out.pr…

【Linux】【驱动】驱动挂载的时候给驱动传递参数

【Linux】【驱动】驱动挂载的时候给驱动传递参数 绪论1.什么是驱动传参驱动传参就是传递参数给我们的驱动举例:2.驱动传参数有什么作用呢?3. 传递单个参数使用如下的数组4. 传递数组使用以下函数&#xff1a; 传递数字值代码指令 传递数组代码传递数组指令 绪论 1.什么是驱动…

C语言(第二十九天)

1.2.2 文件结构设计 之前学习了多文件的形式对函数的声明和定义&#xff0c;这里我们实践一下&#xff0c;我们设计三个文件&#xff1a; test.c //文件中写游戏的测试逻辑 game.c //文件中写游戏中函数的实现等 game.h //文件中写游戏需要的数据类型和函数声明等 2. 扫雷游戏的…

如何拼接两个视频在一起?

如何拼接两个视频在一起&#xff1f;在度过一个美好周末的时候&#xff0c;我和朋友一起拍摄了两组视频&#xff0c;准备将两个视频合并成一个并发布到朋友圈。这个想法非常棒&#xff0c;但是我在第一步就遇到了麻烦&#xff1a;如何将这两个视频拼接在一起&#xff1f;这听起…

Go 自学:struct结构体

以下代码展示如何建立一个结构体struct。 我们可以使用%v查看结构体的详情。 package mainimport ("fmt" )func main() {Jeff : User{"Jeff", "Jeffgo.dev", true, 16}fmt.Println((Jeff))fmt.Printf("Jeff details are: %v\n", Jeff…

7天GMV达220万美元!TikTok Shop爆品榜出炉。

7天GMV达220万美元&#xff01;TikTok Shop爆品榜出炉 8月28日消息&#xff0c;据跨境指南联合TikTok数据分析平台EchoTik发布的数据&#xff0c;监测了上周TikTok Shop印尼、马来西亚、泰国、美国市场GMV前10的商品。上周在印尼市场GMV排名前10的商品中&#xff1a;FREE ONGK…

RPA是什么样的机器人技术?RPA可以实现哪些流程的自动化?

一、RPA是什么样的机器人技术&#xff1f; RPA&#xff08;Robotic Process Automation&#xff09;即机器人流程自动化&#xff0c;是一种通过模拟人类在计算机系统上的操作&#xff0c;实现流程自动化的技术。RPA机器人可以代替人工执行各种重复性任务&#xff0c;如数据输入…

基于微服务、Java、Springcloud、Vue、MySQL开发的智慧工地管理系统源码

智慧工地聚焦施工现场岗位一线&#xff0c;围绕“人、机、料、法、环”五大要素&#xff0c;数字化工地平台与现场多个子系统的互联实现了工地业务间的互联互通和协同共享。数字化工地管理平台能够盘活工地各大项目之间孤立的信息系统&#xff0c;实现数据的统一接入、处理与维…

【Spring Boot】Spring Boot实现完整论坛功能示例代码

以下是一个简单的Spring Boot论坛系统示例代码&#xff1a; 首先是数据库设计&#xff0c;我们创建以下几张表&#xff1a; user表&#xff0c;存储用户信息&#xff0c;包括id、username、password、email、create_time等字段。topic表&#xff0c;存储帖子信息&#xff0c;…

迅睿系统二开自定义函数和插件的自定义函数

全局的自定义函数&#xff1a; 全局的自定义函数文件&#xff1a;dayrui/My/Helper.php 此文件用于放网站自定义函数&#xff0c;程序会自动加载 当前站点的自定义函数文件&#xff1a;网站主目录/config/custom.php 插件的自定义函数&#xff1a; 基于App目录下的插件或模块…

辉瑞乡村振兴战略下传统村落文化旅游设计小红书中美德少许

辉瑞乡村振兴战略下传统村落文化旅游设计小红书中美德少许

你会使用druid数据库连接池吗???

1.下载架包。下载地址&#xff1a;https://note.youdao.com/ynoteshare/index.html?id61e2cc939390acc9c7e5017907e98044&typenote&_time1693296531722 2.将架包加入项目文件。 创建一个lib目录&#xff0c;将架包复制进去 右键点击lib目录&#xff0c;将其添加为库。…

前端 -- 基础 VSCode 工具生成骨架标签新增代码 解释详解

目录 文档类型声明标签 Lang 语言种类 字符集 文档类型声明标签 <!DOCTYPE> 文档类型声明&#xff0c;作用就是告诉浏览器 当前的页面是 使用哪种 HTML 版本 来显示的网页 HTML 版本也很多呀 &#xff0c;比如 &#xff1a; HTML5 ,HTML4&#xff0c;XHTML 等…

【infiniband】rdma-core中的ibmad_port结构体

ibmad_port在rdma-core\libibmad\mad_internal.h文件中定义的结构体是&#xff1a; struct ibmad_port { int port_id; /* file descriptor returned by umad_open() */ int class_agents[MAX_CLASS]; /* class2agent mapper */ int timeout, retries; …

自动化PLC工程师能否转到c#上位机开发?

成功从自动化PLC工程师转向C#上位机开发的经历可能因人而异&#xff0c;以下是一些分享的思路和建议&#xff1a;扩展编程技能&#xff1a;学习C#语言和相关的开发工具和框架&#xff0c;掌握语言的基础知识和常用的编程技巧。可以通过在线教程、培训课程、书籍等途径进行学习&…