高可用之限流 08-leaky bucket漏桶算法

限流系列

开源组件 rate-limit: 限流

高可用之限流-01-入门介绍

高可用之限流-02-如何设计限流框架

高可用之限流-03-Semaphore 信号量做限流

高可用之限流-04-fixed window 固定窗口

高可用之限流-05-slide window 滑动窗口

高可用之限流-06-slide window 滑动窗口 sentinel 源码

高可用之限流-07-token bucket 令牌桶算法

高可用之限流 08-leaky bucket漏桶算法

高可用之限流 09-guava RateLimiter 入门使用简介 & 源码分析

漏桶算法

漏桶算法,又称 leaky bucket。

为了理解漏桶算法,我们看一下对于该算法的示意图:

image

从图中我们可以看到,整个算法其实十分简单。首先,我们有一个固定容量的桶,有水流进来,也有水流出去。

对于流进来的水来说,我们无法预计一共有多少水会流进来,也无法预计水流的速度。但是对于流出去的水来说,这个桶可以固定水流出的速率。而且,当桶满了之后,多余的水将会溢出。

我们将算法中的水换成实际应用中的请求,我们可以看到漏桶算法天生就限制了请求的速度。当使用了漏桶算法,我们可以保证接口会以一个常速速率来处理请求。

所以漏桶算法天生不会出现临界问题

漏桶算法可以粗略的认为就是注水漏水过程,往桶中以一定速率流出水,以任意速率流入水,当水超过桶流量则丢弃,因为桶容量是不变的,保证了整体的速率。

java 实现

/** Copyright (c)  2018. houbinbin Inc.* rate-acquire All rights reserved.*/package com.github.houbb.rate.limit.core.core.impl;import com.github.houbb.log.integration.core.Log;
import com.github.houbb.log.integration.core.LogFactory;
import com.github.houbb.rate.limit.core.core.ILimitContext;
import org.apiguardian.api.API;/*** 漏桶算法** @author houbinbin* Created by bbhou on 2017/9/20.* @since 0.0.7*/
@API(status = API.Status.EXPERIMENTAL)
public class LimitLeakyBucket extends LimitAdaptor {private static final Log LOG = LogFactory.getLog(LimitLeakyBucket.class);/*** 令牌的发放速率* <p>* 每一秒发放多少。** @since 0.0.6*/private final long rate;/*** 容量* <p>* 后期暴露为可以配置** @since 0.0.6*/private final long capacity;/*** 水量** @since 0.0.6*/private volatile long water;/*** 上一次的更新时间** @since 0.0.6*/private volatile long lastUpdateTime;/*** 构造器** @param context 上下文* @since 0.0.4*/public LimitLeakyBucket(final ILimitContext context) {// 暂不考虑特殊输入,比如 1s 令牌少于1 的场景long intervalSeconds = context.timeUnit().toSeconds(context.interval());this.rate = context.count() / intervalSeconds;// 8 的数据this.capacity = this.rate * 8;// 这里可以慢慢的加,初始化设置为0// 这样就有一个 warmUp 的过程this.water = 0;this.lastUpdateTime = System.currentTimeMillis();}/*** 获取锁** (1)未满加水:通过代码 water +=1进行不停加水的动作。* (2)漏水:通过时间差来计算漏水量。* (3)剩余水量:总水量-漏水量。** @since 0.0.5*/@Overridepublic synchronized boolean acquire() {long now = System.currentTimeMillis();// 先执行漏水,计算剩余水量long durationMs = now - lastUpdateTime;long leakyWater = (long) (durationMs * 1.0 * rate / 1000);LOG.debug("[Limit] leaky water is " + leakyWater);water = Math.max(0, water - leakyWater);// 这里应该加一个判断,如果漏水量较小,直接返回。避免开始时,大量流量通过if(leakyWater < 1) {LOG.debug("[Limit] leaky water is too small!");return false;}if ((water + 1) < capacity) {// 尝试加水,并且水还未满water++;lastUpdateTime = now;return true;} else {// 水满,拒绝加水LOG.debug("[Limit] leaky water is has been full!");return false;}}}

和令牌桶核心的不同,是出的速度实际上是固定的。

不会像令牌同时可以消费多个的情况。

当水桶满时,和令牌满是类似的,直接返回 false。

测试

public class LimitLeakyBucketTest {private static final Log LOG = LogFactory.getLog(LimitTokenBucket.class);/*** 2S 内最多运行 5 次* @since 0.0.5*/private static final ILimit LIMIT = LimitBs.newInstance().interval(1).count(5).limit(LimitLeakyBucket.class).build();static class LimitRunnable implements Runnable {@Overridepublic void run() {for(int i = 0; i < 6; i++) {while (!LIMIT.acquire()) {// 等待令牌TimeUtil.sleep(100);}LOG.info("{}-{}", Thread.currentThread().getName(), i);}}}public static void main(String[] args) {new Thread(new LimitRunnable()).start();}}
  • 日志
23:55:54.911 [Thread-1] INFO  com.github.houbb.rate.limit.core.core.impl.LimitTokenBucket - Thread-1-0
23:55:55.113 [Thread-1] INFO  com.github.houbb.rate.limit.core.core.impl.LimitTokenBucket - Thread-1-1
23:55:55.313 [Thread-1] INFO  com.github.houbb.rate.limit.core.core.impl.LimitTokenBucket - Thread-1-2
23:55:55.513 [Thread-1] INFO  com.github.houbb.rate.limit.core.core.impl.LimitTokenBucket - Thread-1-3
23:55:55.713 [Thread-1] INFO  com.github.houbb.rate.limit.core.core.impl.LimitTokenBucket - Thread-1-4
23:55:55.913 [Thread-1] INFO  com.github.houbb.rate.limit.core.core.impl.LimitTokenBucket - Thread-1-5

主要问题

因为漏桶的漏出速率是固定的,因此它对于存在突发特性的流量来说缺乏效率。

算法对比

计数器 VS 滑动窗口:

计数器算法是最简单的算法,可以看成是滑动窗口的低精度实现。

滑动窗口由于需要存储多份的计数器(每一个格子存一份),所以滑动窗口在实现上需要更多的存储空间。也就是说,如果滑动窗口的精度越高,需要的存储空间就越大。

漏桶算法 VS 令牌桶算法:

漏桶算法和令牌桶算法最明显的区别是令牌桶算法允许流量一定程度的突发。

因为默认的令牌桶算法,取走token是不需要耗费时间的,也就是说,假设桶内有100个token时,那么可以瞬间允许100个请求通过。

令牌桶算法由于实现简单,且允许某些流量的突发,对用户友好,所以被业界采用地较多。

当然我们需要具体情况具体分析,只有最合适的算法,没有最优的算法。

单点应用限流 vs 分布式集群限流

单点应用下,对应用进行限流,既能满足本服务的需求,又可以很好的保护好下游资源。

在选型上,可以采用Google Guava的RateLimiter即可。

而在多机部署场景下,对单点的限流,则不能达到最好效果,需要引入分布式限流。分布式限流的算法,依然可以采用令牌桶算法,只不过将令牌桶的发放、存储改为全局的模型。

真正实现中,可以采用redis+lua的方式,通过把逻辑放在redis端,来减少调用次数。

lua的逻辑如下:

1,redis中存储剩余令牌的数量cur_token,和上次获取令牌的时间last_time。

2,在每次申请令牌时,可以根据(当前时间cur_time - last_time)的时间差 乘以 令牌发放速率,算出当前可用令牌数。

3,如果有剩余令牌,则准许请求通过;否则不通过。

拓展阅读

guava RateLimiter 源码

常见的限流组件:

Sentinel

Hystrix

resilience4j

参考资料

「限流算法第四把法器:漏桶算法」

限流限速RateLimiter

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

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

相关文章

SCALABLEANDEFFECTIVE IMPLICIT GRAPH NEURALNETWORKS ON LARGEGRAPHS

ICLR24 推荐指数&#xff1a; #paper/⭐⭐ 领域&#xff1a; 大图&#xff0c;图扩展 大概的工作&#xff1a;提出了针对子图的虚拟节点&#xff0c;让所有点都与其相连 相关工作&#xff1a; 传统GNN与Inplicit gnn 传统GNN的传播函数&#xff1a; Z ( l 1 ) ϕ ( W ( …

Karmada核心概念

以下内容为翻译&#xff0c;原文地址 Karmada 是什么&#xff1f; | karmada 一、Karmada核心概念 一&#xff09;什么是Karmada 1、Karmada&#xff1a;开放&#xff0c;多云&#xff0c;多集群Kubernetes业务流程 Karmada (Kubernetes Armada)是一个Kubernetes管理系统&…

【OpenCV】(六)—— 阈值处理

阈值处理&#xff08;Thresholding&#xff09;用于将灰度图像转换为二值图像。通过设定一个或多个阈值&#xff0c;可以将图像中的像素分为不同的类别&#xff0c;通常用于分割前景和背景、简化图像、去除噪声等任务。OpenCV 提供了多种阈值处理方法&#xff0c;下面介绍基本阈…

让AI像人一样思考和使用工具,reAct机制详解

reAct机制详解 reAct是什么reAct的关键要素reAct的思维过程reAct的代码实现查看效果引入依赖&#xff0c;定义模型定义相关工具集合工具创建代理启动测试完整代码 思考 reAct是什么 reAct的核心思想是将**推理&#xff08;Reasoning&#xff09;和行动&#xff08;Acting&…

探索人工智能:深度解析未来科技的核心驱动力

目录 &#x1f354; 人工智能的应用方向 &#x1f354; 人工智能的发展历史 &#x1f354; 人工智能、机器学习、深度学习关系 &#x1f354; 为什么学习机器学习&#xff1f; &#x1f354; 小节 学习目标 &#x1f340; 了解人工智能的应用方向 &#x1f340; 了解人工智…

【千库网-注册安全分析报告】

前言 由于网站注册入口容易被黑客攻击&#xff0c;存在如下安全问题&#xff1a; 暴力破解密码&#xff0c;造成用户信息泄露短信盗刷的安全问题&#xff0c;影响业务及导致用户投诉带来经济损失&#xff0c;尤其是后付费客户&#xff0c;风险巨大&#xff0c;造成亏损无底洞…

iPad备份软件哪个好?好用的苹果备份软件推荐

苹果手机在将数据备份到电脑时&#xff0c;需要通过第三方的管理软件&#xff0c;才可以将手机连接到电脑进行备份。苹果手机备份软件有很多&#xff0c;常用的有&#xff1a;爱思助手、iMazing、iTuns等。那么这三款常用的备份软件究竟哪款更好呢&#xff1f;下面就给大家盘点…

uniapp学习(004-2 组件 Part.2生命周期)

零基础入门uniapp Vue3组合式API版本到咸虾米壁纸项目实战&#xff0c;开发打包微信小程序、抖音小程序、H5、安卓APP客户端等 总时长 23:40:00 共116P 此文章包含第31p-第p35的内容 文章目录 组件生命周期我们主要使用的三种生命周期setup(创建组件时执行)不可以操作dom节点…

Kimi AI助手重大更新:语音通话功能闪亮登场!

Kimi人工智能助手近日发布了一项令人瞩目的重大更新&#xff0c;其中最引人注目的是新增的语音通话功能。这一创新不仅拓展了用户与AI互动的方式&#xff0c;还为学习和工作场景提供了突破性的解决方案。 Ai 智能办公利器 - Ai-321.com 人工智能 - Ai工具集 - 全球热门人工智能…

使用 python 下载 bilibili 视频

本文想要达成的目标为&#xff1a;运行 python 代码之后&#xff0c;在终端输入视频链接&#xff0c;可自动下载高清 1080P 视频并保存到相应文件夹。 具体可分为两大步&#xff1a;首先&#xff0c;使用浏览器开发者工具 F12 获取请求链接相关信息&#xff08;根据 api 接口下…

性能测试持续继承 CICD

目录 一、如何实现性能测试持续继承操作 下载ant 验证ant是否安装成功 二、jmeterant结合 1、我们需要把jmeter中extres 中的ant-jmeter-1.1.1.jar 复制到ant的安装目录中的lib目录中 2、把jmeter中extres中的build.xml 复制到ant的安装目录中的bin目录 3、编辑build.x…

uniapp 设置 tabbar 的 midButton 按钮

效果展示&#xff1a; 中间的国际化没生效&#xff08;忽略就行&#xff09; 示例代码&#xff1a; 然后在 App.vue 中进行监听&#xff1a; <script>export default {onLaunch(e) {// #ifdef APPuni.onTabBarMidButtonTap(()>{console.log("中间按钮点击回调…

Nacos安装指南

1.Windows安装 开发阶段采用单机安装即可。 1.1.下载安装包 在Nacos的GitHub页面,提供有下载链接,可以下载编译好的Nacos服务端或者源代码: GitHub主页:https://github.com/alibaba/nacos GitHub的Release下载页:https://github.com/alibaba/nacos/releases 如图: …

C1. Adjust The Presentation (Easy Version) 双指针

C1. Adjust The Presentation (Easy Version) 妈呀, 最难读懂的一道题(英语不好) 原题 思路 这道题读懂之后就是双指针. 不难想到只要之前出现过, 就一定可以展示出来, 唯一需要注意的时不能在a里有多余的科幻片 代码 #include <bits/stdc.h> #define int long long…

Python爬虫之正则表达式于xpath的使用教学及案例

正则表达式 常用的匹配模式 \d # 匹配任意一个数字 \D # 匹配任意一个非数字 \w # 匹配任意一个单词字符&#xff08;数字、字母、下划线&#xff09; \W # 匹配任意一个非单词字符 . # 匹配任意一个字符&#xff08;除了换行符&#xff09; [a-z] # 匹配任意一个小写字母 […

牛客:Holding Two,Inverse Pair,Counting Triangles

Holding Two 题目描述 登录—专业IT笔试面试备考平台_牛客网 ​​运行代码 #include<bits/stdc.h> using namespace std; const int N3e45; string s1,s2; int main(){int n,m;cin>>n>>m;for(int i0;i<m;i){if(i&1){s10;s21;} else{s11;s20;} }fo…

jvm内存溢出问题排查Java服务自动停止问题排查

Java服务自动停止&#xff0c;Java服务内存溢出问题解决记录。 过程描述 服务器上的一个项目突然服务不了了&#xff0c;登录服务器一看&#xff0c;服务被停了&#xff0c;第一反应大概率就是内存溢出导致的&#xff0c;结果查看日志没有任何报错&#xff0c;就很奇怪&#…

鸿蒙开发案例:HarmonyOS NEXT语法实现2048

【实现的功能】 • 游戏逻辑&#xff1a;实现了2048游戏的核心逻辑&#xff0c;包括初始化游戏盘面、添加随机方块、处理四个方向的滑动操作等。 • UI展示&#xff1a;构建了游戏的用户界面&#xff0c;显示得分、游戏盘面&#xff0c;并提供了重新开始按钮。 • 用户交互&…

OpenAI 公布了其新 o1 模型家族的元提示(meta-prompt)

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

出处不详 取数游戏

目录 取数游戏题目描述背景输入输出数据范围 题解解法优化 打赏 取数游戏 题目描述 背景 两人将 n n n个正整数围成一个圆环&#xff0c;规则如下&#xff1a; 第一名玩家随意选取数字&#xff1b;第二名玩家从与第一名玩家相邻的两个数字中选择一个&#xff1b;而后依次在…