【知识点随笔分享 | 第九篇】常见的限流算法

这篇具有很好参考价值的文章主要介绍了【知识点随笔分享 | 第九篇】常见的限流算法。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

前言:

1.固定窗口限流: 

缺点: 

2.滑动窗口限流:

 优点:

滴桶限流:

缺点:

令牌桶限流: 

优点:

总结:


 文章来源地址https://www.toymoban.com/news/detail-764102.html

前言:

        当今互联网时代,随着网络流量的快速增长和系统负载的不断加重,限流算法作为一种重要的网络管理工具变得愈发重要。限流算法通过控制系统的输入和输出流量,有效地保护系统不受过载的影响,确保系统能够稳定可靠地运行。本文将介绍几种常见的限流算法及其应用场景,旨在帮助读者更好地理解限流算法的原理和实际应用,从而为网络性能优化提供有力支持。限流算法的研究和应用对于保障网络安全、提升系统稳定性具有重要意义,在当前信息化社会具有广泛的应用前景。 

【知识点随笔分享 | 第九篇】常见的限流算法,【知识点随笔分分享】,网络,java,算法,jvm,开发语言,spring

1.固定窗口限流: 

        固定窗口限流  就是在单位时间(时间窗口)内,只能接收指定数量的请求。

  • 在固定窗口限流算法中,时间被划分为固定大小的窗口,并且每个窗口内允许通过的请求数是固定的。
  • 算法步骤:
    • 统计当前窗口内的请求数;
    • 如果请求数超过了限制值,则拒绝该请求;
    • 重置新的窗口开始计数。

用汉堡店举例:固定窗口限流就是  在固定的时间内只能接待指定数量的顾客。比如一个小时只能接待10个顾客。

固定窗口限流的思路比较简单,代码实现为:

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

public class FixedWindowRateLimiter {
    private final int limit;  // 限制的请求数
    private final long windowSizeInMillis;  // 窗口大小(毫秒)
    private final AtomicInteger counter;
    private long windowStartTime;

    public FixedWindowRateLimiter(int limit, long windowSizeInMillis) {
        this.limit = limit;
        this.windowSizeInMillis = windowSizeInMillis;
        this.counter = new AtomicInteger(0);
        this.windowStartTime = System.currentTimeMillis();
    }

    public boolean allowRequest() {
        long currentTime = System.currentTimeMillis();
        long elapsedTime = currentTime - windowStartTime;

        if (elapsedTime > windowSizeInMillis) {
            // 进入新的窗口,重置计数器和窗口开始时间
            counter.set(0);
            windowStartTime = currentTime;
        }

        // 检查请求数是否超过限制
        if (counter.incrementAndGet() > limit) {
            return false;  // 超过限制,拒绝请求
        }

        return true;  // 没有超过限制,允许请求通过
    }
}

缺点: 

        固定窗口限流可能会引发流量突刺,也就是可能会发生以下情况:

【知识点随笔分享 | 第九篇】常见的限流算法,【知识点随笔分分享】,网络,java,算法,jvm,开发语言,spring

我们用红色来标识 在该时间窗口区域发生了请求,也就是说固定窗口限流在窗口的边界处可能会发生流量突刺,在短时间内发生多次请求

2.滑动窗口限流:

           滑动窗口限流  就是在单位时间(时间窗口)内,只能接收指定数量的请求。但单位时间是滑动的。

  • 在滑动窗口限流算法中,时间被划分为固定大小的窗口,每个窗口内允许通过的请求数是固定的,同时可以滑动窗口来适应请求的变化。
  • 算法步骤:
    • 统计当前窗口内的请求数;
    • 如果请求数超过了限制值,则拒绝该请求;
    • 滑动窗口,将旧的窗口移除。

我们用图片来标识滑动窗口限流和固定窗口限流的区别:

这是固定窗口限流,他的时间窗口是由时间窗口大小决定的。 

【知识点随笔分享 | 第九篇】常见的限流算法,【知识点随笔分分享】,网络,java,算法,jvm,开发语言,spring 这是滑动窗口限流,他的时间窗口是不断滑动的。

【知识点随笔分享 | 第九篇】常见的限流算法,【知识点随笔分分享】,网络,java,算法,jvm,开发语言,spring

也就是说:滑动窗口限流不会一次性消除旧窗口的请求次数,而是不断的通过滑动的方式抹除。

 用汉堡店举例:滑动窗口限流就是  单位时间内限制接客数,相比较于固定窗口而言,假设我们在5.59接待了五位客人,如果时间窗口长度为小时,滑动单位为1分钟,那么六点的时候,并不会刷新窗口接待客人人数,而是继续保留5.59的接待人数。因为此时二者仍位于一个窗口内。  

滑动窗口限流的代码思路为:

import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class SlidingWindowRateLimiter {
    private final int limit;  // 限制的请求数
    private final long windowSizeInMillis;  // 窗口大小(毫秒)
    private final int[] counter;
    private final Lock lock;
    private long windowStartTime;

    public SlidingWindowRateLimiter(int limit, long windowSizeInMillis) {
        this.limit = limit;
        this.windowSizeInMillis = windowSizeInMillis;
        this.counter = new int[(int) (windowSizeInMillis / 1000)];
        this.lock = new ReentrantLock();
        this.windowStartTime = System.currentTimeMillis();
    }

    public boolean allowRequest() {
        long currentTime = System.currentTimeMillis();
        long elapsedTime = currentTime - windowStartTime;

        lock.lock();
        try {
            // 滑动窗口,将旧的窗口移除
            if (elapsedTime > windowSizeInMillis) {
                int numToRemove = (int) ((elapsedTime - windowSizeInMillis) / 1000);
                for (int i = 0; i < numToRemove; i++) {
                    counter[i] = 0;
                }
                windowStartTime = currentTime - (elapsedTime % windowSizeInMillis);
            }

            // 统计请求数
            int currentWindowIndex = (int) (elapsedTime / 1000);
            counter[currentWindowIndex]++;

            // 检查请求数是否超过限制
            int totalRequests = 0;
            for (int i = 0; i < counter.length; i++) {
                totalRequests += counter[i];
            }
            if (totalRequests > limit) {
                return false;  // 超过限制,拒绝请求
            }
        } finally {
            lock.unlock();
        }

        return true;  // 没有超过限制,允许请求通过
    }
}

 优点:

                滑动窗口可以缓解流量突刺:例如固定窗口(窗口大小为1小时,每个窗口最多处理10个请求)可以在1.59进行了十次请求,2.01进行了十次请求。但是在滑动窗口中,如果我们将滑动参数设置为1min,窗口大小设置为1小时,那么1.59时,滑动窗口的范围是1.59-2.59。此时如果设置最大请求数量为10,那么1.59执行的十次请求就已经填满了请求数量上限。2.01的就无法进行请求。通过这种思路避免了窗口边界流量突刺这种情况。

滴桶限流:

滴桶限流 就是  接收指定数量的请求,按照指定的速率处理。

  • 在滴桶限流算法中,系统以恒定的速率漏水,并以固定速率接收请求。
  • 算法步骤:
    • 当有请求到达时,先检查桶中是否有水滴;
    • 如果有水滴可用,则允许请求通过并漏水;
    • 如果没有水滴可用,则拒绝该请求。

 【知识点随笔分享 | 第九篇】常见的限流算法,【知识点随笔分分享】,网络,java,算法,jvm,开发语言,spring

用汉堡店举例:滴桶限流就是每个小时接待6个客户,然后每十分钟处理一个客户的请求 

 java代码实现:

import java.util.concurrent.TimeUnit;

public class LeakyBucketRateLimiter {
    private final int capacity;  // 桶的容量
    private final double rate;   // 水滴漏出速率(水滴/秒)
    private double water;        // 当前桶中的水滴数量
    private long lastLeakTime;   // 上次漏水的时间戳

    public LeakyBucketRateLimiter(int capacity, double rate) {
        this.capacity = capacity;
        this.rate = rate;
        this.water = 0;
        this.lastLeakTime = System.nanoTime();
    }

    public synchronized boolean allowRequest() {
        leak();

        if (water >= 1) {
            water -= 1;
            return true;  // 水滴足够,允许请求通过
        } else {
            return false;  // 水滴不足,拒绝请求
        }
    }

    private void leak() {
        long now = System.nanoTime();
        double elapsedTime = (now - lastLeakTime) / 1e9;
        double waterToLeak = elapsedTime * rate;

        if (waterToLeak > 0) {
            water = Math.max(0, water - waterToLeak);
            lastLeakTime = now;
        }
    }
}

缺点:

        滴桶限流的并发性比较差,我们在代码中就可以看到,他需要对水滴(请求)逐个进行处理

令牌桶限流: 

        令牌桶限流就是创建一个桶,生成指定数量的令牌,只有拿到令牌的请求才可以进行处理。

  • 在令牌桶限流算法中,系统以恒定的速率生成令牌并放入令牌桶中,每个请求需要获取一个令牌才能通过。
  • 算法步骤:
    • 每隔一段时间生成一定数量的令牌放入桶中;
    • 当有请求到达时,从桶中获取一个令牌,如果没有令牌可用,则拒绝该请求。
import java.util.concurrent.TimeUnit;

public class TokenBucketRateLimiter {
    private final int capacity;  // 令牌桶容量
    private final double rate;   // 令牌生成速率(令牌/秒)
    private double tokens;       // 当前桶中的令牌数
    private long lastRefillTime; // 上次填充令牌的时间戳

    public TokenBucketRateLimiter(int capacity, double rate) {
        this.capacity = capacity;
        this.rate = rate;
        this.tokens = capacity;
        this.lastRefillTime = System.nanoTime();
    }

    public synchronized boolean allowRequest() {
        refill();

        if (tokens >= 1) {
            tokens -= 1;
            return true;  // 令牌足够,允许请求通过
        } else {
            return false;  // 令牌不足,拒绝请求
        }
    }

    private void refill() {
        long now = System.nanoTime();
        double elapsedTime = (now - lastRefillTime) / 1e9;
        double tokensToAdd = elapsedTime * rate;

        if (tokensToAdd > 0) {
            tokens = Math.min(capacity, tokens + tokensToAdd);
            lastRefillTime = now;
        }
    }
}

用汉堡店举例:令牌桶限流就是 汉堡店 有一个 餐卷桶,并且会按时补充餐卷桶的餐卷数,只有拿到了餐卷才可以购买汉堡

优点:

        令牌桶限流的并发性能比较高,我们可以批量对拿到令牌的请求进行处理。

总结:

        在实际的开发中,其实我们并不用手动去实现这些限流算法,很多第三方库都已经为我们实现了限流算法,我们只需要直接使用就好了。而在实际开发中,常用的限流算法是 滴桶限流和令牌桶限流。因此我们要掌握好这两个限流算法。

如果我的内容对你有帮助,请点赞,评论,收藏。创作不易,大家的支持就是我坚持下去的动力!

【知识点随笔分享 | 第九篇】常见的限流算法,【知识点随笔分分享】,网络,java,算法,jvm,开发语言,spring

 

到了这里,关于【知识点随笔分享 | 第九篇】常见的限流算法的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 微信小程序常见知识点

    小程序是一种开放能力,开发者可以快速地开发一个小程序。小程序可以在微信内被便捷的获取和传播,同时具有出色的使用体验。 微信小程序的优势: 微信助理,容易推广。 小程序拥有众多入口,这些入口有助于企业更好的获取流量,从而进行转化、变现。 使用便捷。

    2024年02月08日
    浏览(41)
  • 面试常见知识点--树的遍历

    算法流程 : 1. 先申请一个栈,记为 stk 。 2 .然后将根节点压入 stk 中。 3 .每次从 stk 中弹出栈顶节点,记为 cur ,然后打印 cur 的值。如果 cur 的右子树不为空,将 cur 的右子树压入 stk 中。如果 cur 的左子树不为空,将 cur 的左子树压入 stk 中。不断重复次步骤直到 stk 为空循

    2024年02月01日
    浏览(45)
  • WebSocket的11个面试常见知识点

    前端面试题库 ( 面试必备)              推荐:★★★★★ 地址:前端面试题库 WebSocket 作为一种基于 TCP 协议的实时通信协议,为前端应用提供了强大的双向通信能力。本文将深入探讨前端 WebSocket 的相关问题,包括协议区别、用法、关键技术点等。 WebSocket 是一种实时

    2024年01月22日
    浏览(41)
  • 软考知识点——常见算法策略、设计模式、常见排序算法

    目录 一、常见算法策略 二、设计模式 1.设计模式分类 2.创建型设计模式应用场景 3.结构型设计模式应用场景  4.行为型设计模式应用场景 三、常见排序算法 算法名称 关键点 特征 典型问题 分治法 递归技术 把一个问题拆分成多个小模块的相同子问题,一般可用递归解决。

    2024年02月07日
    浏览(40)
  • 《Windows核心编程》若干知识点实战应用分享

    目录 1、进程的虚拟内存分区与小于0x10000的小地址内存区 1.1、进程的虚拟内存分区 1.2、小于0x10000的小地址内存区 2、保存线程上下文的CONTEXT结构体 3、从汇编代码角度去理解多线程运行过程的典型实例 4、调用TerminateThread强制结束线程会导致线程中的资源没有释放的问题 5、

    2024年01月25日
    浏览(46)
  • 《Windows核心编程》若干知识点应用实战分享

    目录 1、进程的虚拟内存分区与小于0x10000的小地址内存区 1.1、进程的虚拟内存分区 1.2、小于0x10000的小地址内存区 2、保存线程上下文的CONTEXT结构体 3、从汇编代码角度去理解多线程运行过程的典型实例 4、调用TerminateThread强制结束线程会导致线程中的资源没有释放的问题 5、

    2024年01月22日
    浏览(48)
  • 【面试题】C#面试常见基础知识点整理(附示例代码)

    大家好,这是自己自行整理的c#面试题,方便自己学习的同时分享出来。 相同点 抽象方法和虚方法都可以供派生类重写, 派生类重写父类的方法都要使用override来声明。 不同点 虚方法必须有方法名称和方法实现;抽象方法是只有方法名称,没有方法实现; 虚方法在派生

    2024年02月02日
    浏览(55)
  • 分享刷题的一些小知识点--4.9日

    1.string库提供了 、、==、=、=、!= 等比较运算符,比如两个字符串s和t,直接(s==t)是正确的。 2.unordered_map 容器,直译过来就是\\\"无序 map 容器\\\"的意思。所谓“无序”,指的是 unordered_map 容器不会像 map 容器那样对存储的数据进行排序。换句话说,unordered_map 容器和 map 容器仅有

    2023年04月11日
    浏览(48)
  • 1.5万字+30张图盘点索引常见的11个知识点

    大家好,我是三友~~ 今天来盘点一下关于MySQL索引常见的知识点 本来这篇文章我前两个星期就打算写了,提纲都列好了,但是后面我去追《漫长的季节》这部剧去了,这就花了一个周末的时间,再加上后面一些其它的事,导致没来得及写 不过不要紧,好饭不怕晚,虽迟但到,

    2024年02月06日
    浏览(43)
  • Python入门知识点分享——(十六)标准库的导入和调用

    在正式学习面向对象编程之前,我们先讲一下怎么在代码中导入并调用现成的模组,也就是Python中的标准库。像我们之前介绍过的os模块就是其中之一,下面我将为大家分别介绍几个常用的标准库。 math 模块提供了许多对浮点数的数学运算函数,该模块下的函数返回值均为浮

    2024年01月17日
    浏览(40)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包