【sentinel】漏桶算法在Sentinel中的应用

news/2025/2/5 6:42:01/

漏桶算法

漏桶算法介绍

漏桶算法,又称leaky bucket。

从图中我们可以看到,整个算法其实十分简单。首先,我们有一个固定容量的桶,有水流进来,也有水流出去。对于流进来的水来说,我们无法预计一共有多少水会流进来,也无法预计水流的速度。但是对于流出去的水来说,这个桶可以固定水流出的速率。而且,当桶满了之后,多余的水将会溢出。

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

漏桶算法的实现

漏桶算法具体的实现代码如下:

package com.morris.user.demo;import lombok.extern.slf4j.Slf4j;import java.util.Random;
import java.util.concurrent.TimeUnit;/*** 漏桶算法*/
@Slf4j
public class LeakyBucketDemo {public static void main(String[] args) {LeakyBucket sideWindow = new LeakyBucket(2);for (int i = 0; i < 30; i++) {int finalI = i;new Thread(() -> {try {TimeUnit.MILLISECONDS.sleep(new Random().nextInt(30000));} catch (InterruptedException e) {e.printStackTrace();}log.info(finalI + "--> " + sideWindow.canPass());}).start();}}public static class LeakyBucket {// 桶的容量private static final long CAPACITY = 10;// 水漏出的速度(每秒系统能处理的请求数)private final long rate;// 当前水量(当前累积请求数)private double water = 0;// 上一次请求的时间private long lastRequestTime = System.currentTimeMillis();/*** @param maxCount 1秒内允许的最大请求数*/public LeakyBucket(int maxCount) {// 每秒允许的最大请求数this.rate = maxCount;}public synchronized boolean canPass() {long now = System.currentTimeMillis();// 去除从lastRequestTime~now时间段应该从桶中漏出的水this.water = Math.max(0, water - (now - lastRequestTime) * 1.0D / 1000 * this.rate);this.lastRequestTime = now;if (this.water + 1 > CAPACITY) {// 桶满了return false;}this.water++;return true;}}
}

漏桶算法的实现2

漏桶算法的另一种具体实现代码如下:

package com.morris.user.demo;import lombok.extern.slf4j.Slf4j;import java.util.Random;
import java.util.concurrent.TimeUnit;/*** 漏桶算法*/
@Slf4j
public class LeakyBucketDemo2 {public static void main(String[] args) {LeakyBucket sideWindow = new LeakyBucket(2);for (int i = 0; i < 30; i++) {int finalI = i;new Thread(() -> {try {TimeUnit.MILLISECONDS.sleep(new Random().nextInt(3000));} catch (InterruptedException e) {e.printStackTrace();}log.info(finalI + "--> " + sideWindow.canPass());}).start();}}public static class LeakyBucket {// 上一次请求的时间private long lastRequestTime = System.currentTimeMillis();// 两次请求之间的最小时间间隔private final int interval;public LeakyBucket(int maxCount) {this.interval = 1000 / maxCount;}public synchronized boolean canPass() {long now = System.currentTimeMillis();// 两次请求之间的时间间隔if (now - lastRequestTime >= interval) {lastRequestTime = now;return true;}return false;}}
}

漏桶算法的优缺点

优点:

  • 可以平滑限制请求的处理速度,避免瞬间请求过多导致系统崩溃或者雪崩。
  • 可以控制请求的处理速度,使得系统可以适应不同的流量需求,避免过载或者过度闲置。
  • 可以通过调整桶的大小和漏出速率来满足不同的限流需求,可以灵活地适应不同的场景。

缺点:

  • 需要对请求进行缓存,会增加服务器的内存消耗。
  • 对于流量波动比较大的场景,需要较为灵活的参数配置才能达到较好的效果。
  • 但是面对突发流量的时候,漏桶算法还是循规蹈矩地处理请求,这不是我们想看到的啦。流量变突发时,我们肯定希望系统尽量快点处理请求,提升用户体验嘛。

漏桶算法的缺点主要是由于服务和漏下来的请求之间没有交互,要么服务太忙,要么服务太闲,这就引出了令牌桶算法。

漏桶算法在sentinel中的应用

漏桶算法主要用于流控规则中流控效果为排队等待。

com.alibaba.csp.sentinel.slots.block.flow.controller.RateLimiterController#canPass(com.alibaba.csp.sentinel.node.Node, int, boolean)

public boolean canPass(Node node, int acquireCount, boolean prioritized) {// Pass when acquire count is less or equal than 0.if (acquireCount <= 0) {return true;}// Reject when count is less or equal than 0.// Otherwise,the costTime will be max of long and waitTime will overflow in some cases.if (count <= 0) {return false;}// 当前时间long currentTime = TimeUtil.currentTimeMillis();// 计算两个请求中间允许的时间间隔// Calculate the interval between every two requests.long costTime = Math.round(1.0 * (acquireCount) / count * 1000);// Expected pass time of this request.// 下一次请求期待的访问时间long expectedTime = costTime + latestPassedTime.get();if (expectedTime <= currentTime) {// 当前时间大于下一次请求期待的访问时间,允许通过// Contention may exist here, but it's okay.latestPassedTime.set(currentTime);return true;} else {// Calculate the time to wait.// 计算当前线程需要等待的时间long waitTime = costTime + latestPassedTime.get() - TimeUtil.currentTimeMillis();if (waitTime > maxQueueingTimeMs) {// 等待时间大于设置的最大的等待超时时间return false;} else {// latestPassedTime+costTime就是下一次请求期待的访问时间long oldTime = latestPassedTime.addAndGet(costTime);try {waitTime = oldTime - TimeUtil.currentTimeMillis();if (waitTime > maxQueueingTimeMs) {// 说明latestPassedTime被另一个线程改了// 把时间改回去,然后请求不允许通过latestPassedTime.addAndGet(-costTime);return false;}// in race condition waitTime may <= 0if (waitTime > 0) {// 线程休眠,排队等待Thread.sleep(waitTime);}return true;} catch (InterruptedException e) {}}}return false;
}

http://www.ppmy.cn/news/213988.html

相关文章

数据分析与数据挖掘实战案例本地房价预测(716):

数据分析与数据挖掘实战案例&#xff08;7/16&#xff09;&#xff1a; 2022 年首届钉钉杯大学生大数据挑战赛练习题目 练习题 A&#xff1a;二手房房价分析与预测 要点&#xff1a; 1、机器学习 2、数据挖掘 3、数据清洗、分析、pyeahcrs可视化 4、随机森林回归预测模型…

python面向对象操作1(速通版)

目录 一、高阶函数 1.lambda函数 2.lambda函数注意事项 3.map用法 4.map和lambda函数配合 二、reduce函数 1.reduce基本应用 2.reduce和匿名函数配合 三、filter()函数 1.简单用法 2.高阶应用 四、列表排列方法&#xff08;key和lambda问题&#xff09; 1.正常排序…

你真的理解CSS的linear-gradient?

想要在你的网站有一个好看的渐变背景吗&#xff1f;background-image:linear-gradient(red,blue)&#xff0c;就能很轻易的实现一个red至blue的渐变背景图片。就是这么的简单。 感觉老话重提&#xff0c;有点无聊。如果您想了解更多这方面的知识&#xff0c;建议你阅读以前整理…

什么是JIT

1、动态编译&#xff08;dynamic compilation&#xff09;指的是“在运行时进行编译”&#xff1b;与之相对的是事前编译&#xff08;ahead-of-time compilation&#xff0c;简称AOT&#xff09;&#xff0c;也叫静态编译&#xff08;static compilation&#xff09;。 2、JIT…

吐血整理50家企业真实大数据面试题!!学长实测,真实面试!!快收藏!

文章目录 前言京东面试题58面试题新浪面试题搜狐面试题360面试题小米面试题顺丰面试题OPPO面试题VIVO面试题华为面试题boss直聘面试题搜狗金融面试题瓜子二手车面试题猎豹移动面试题作业盒子面试题每日优鲜美团面试要求快手面试题新美互通面试题金山云面试题图新瀚合面试题中创…

HiMPP V3.0 媒体处理软件笔记(六)

4.3 API参考 视频输出&#xff08;VO&#xff09;实现启用视频输出设备或通道、发送视频数据到输出通道等功能。该功能模块提供以下MPI: 设备操作&#xff1a;  HI_MPI_VO_Enable :启用视频输出设备。  HI_MPI_VO_Disable :禁用视频输出设备。  HI_MPI_VO_SetPubAttr :设置…

pandas将df赋值到另一个df_pandas基础

1 dataframe和series操作 1.1 构造dataframe 1) 空dataframe 通过columns,index参数指定dataframe的行索引、列名。 df1 = pd.DataFrame(columns=[c1, c2], index=[ind1, ind2]) 2) 通过字典构造dataframe,并给dataframe添加列;可以通过index=[]参数设置df的索引。 dict_v = …

黑苹果电池电量补丁_修改DSDT实现电量显示方法【转载】

这篇帖子主要来源于论坛https://github.com/RehabMan/Laptop-DSDT-Patch。 但是很多笔记本并未出现在这个补丁源里&#xff0c;并且我们要了解补丁的意思才知道它适不适合我们的电脑。 电量补丁制作过程 我们需要确定DSDT里的哪些部分需要改。 用MaciASL软件打开DSDT&#xff0…