限流算法学习

文章目录

  • 限流算法
    • 基本介绍
    • 适用场景
      • 计数器算法
      • 滑动窗口算法
      • 令牌桶算法
      • 漏桶算法
      • 综合比较
    • 示例实现

限流算法

限流算法是在系统设计中常用来控制资源访问速率、防止服务过载的技术手段。

基本介绍

主要的限流算法有以下几种:

  1. 计数器算法
    计数器算法是最简单的限流算法,它在一个时间窗口内统计请求次数,如果请求次数超过了设定的阈值,则拒绝服务。这种方法实现简单,但存在时间窗口切换时的瞬间流量突增问题。
  2. 滑动窗口算法
    滑动窗口算法是对计数器算法的改进,它将时间窗口分成多个小的窗口,通过维护这些小窗口的计数,可以更平滑地控制流量。这种算法可以较好地解决计数器算法中存在的突增问题。
  3. 令牌桶算法
    令牌桶算法通过一个固定容量的令牌桶来控制流量,系统以恒定速率往桶中添加令牌,处理请求时需要从桶中取出令牌,如果桶中没有令牌,则拒绝服务。这种算法可以允许一定程度的突发流量,因为桶中可以积累令牌。
  4. 漏桶算法
    漏桶算法将请求放入到一个固定容量的桶中,系统以恒定的速率从桶中取出请求进行处理。如果桶满了,则新进的请求会被丢弃或排队等待。这种算法可以很好地控制数据的平均速率和突发速率。

适用场景

计数器算法

特点:简单直接,通过在固定的时间窗口内计数并限制请求的数量来实现限流。

​ 适用场景:

​ 适用于单一服务实例的场景。

​ 对于那些对流量突增不敏感的简单应用。

​ 局限性:在时间窗口切换的瞬间,可能会允许两倍于阈值的请求通过,导致服务瞬时压力加大。

滑动窗口算法

特点:在计数器算法的基础上改进,将时间窗口划分为多个小窗口,以达到更平滑控制流量的效果。

​ 适用场景:

​ 适合需要更平滑控制请求流量的场景。

​ 当需要减少由于时间窗口切换带来的流量波动时非常有用。

令牌桶算法

特点:通过固定速率添加令牌到桶中,请求需要消耗令牌才能被处理,支持一定程度的突发流量。

​ 适用场景:

​ 适合对突发流量有一定容忍度的场景。

​ 当需要对复杂的分布式系统进行限流,且要求系统能够应对短时间内的高流量压力时。

漏桶算法

特点:以恒定的速率处理请求,可以很好地控制数据的平均速率和突发速率,但超出容量的请求会被丢弃或等待。

​ 适用场景:

​ 适合需要严格控制请求处理速率,保证服务稳定性的场景。

​ 当系统处理能力有硬性限制,不能容忍超过一定速率的请求时。

综合比较

​ 对于简单应用或单实例服务,计数器算法因其实现简单而受到青睐。

​ 滑动窗口算法提供了比计数器更平滑的限流控制,适合对流量波动敏感的应用。

​ 令牌桶算法因其支持一定程度的突发流量而广泛应用于需要灵活处理高低流量变化的分布式系统中。

​ 漏桶算法适合对处理速率有严格要求,需要稳定处理请求的系统。

示例实现

'''计数器算法实现'''
import time

class RateLimiter:
    def __init__(self, max_requests, window_size):
        """
        初始化计数器限流器
        :param max_requests: 时间窗口内的最大请求数
        :param window_size: 时间窗口大小,单位为秒
        """
        self.max_requests = max_requests
        self.window_size = window_size
        self.request_counts = 0
        self.start_time = time.time()

    def allow_request(self):
        """
        判断是否允许当前请求
        :return: 如果允许请求,返回True;否则返回False
        """
        current_time = time.time()
        # 如果当前时间超出了时间窗口,则重置计数器和开始时间
        if current_time - self.start_time > self.window_size:
            self.request_counts = 0
            self.start_time = current_time

        # 如果当前请求次数小于最大请求数,则允许请求并增加计数
        if self.request_counts < self.max_requests:
            self.request_counts += 1
            return True
        else:
            # 否则,拒绝请求
            return False

# 示例使用
if __name__ == "__main__":
    limiter = RateLimiter(5, 60)  # 每60秒允许最多5个请求

    # 模拟请求
    for i in range(10):
        time.sleep(1)  # 每秒发送一个请求
        if limiter.allow_request():
            print(f"请求{i + 1}: 允许")
        else:
            print(f"请求{i + 1}: 被限流")
'''滑动窗口算法实现'''
import time
from collections import deque

class SlidingWindowLimiter:
    def __init__(self, max_requests, window_size):
        """
        初始化滑动窗口限流器
        :param max_requests: 时间窗口内允许的最大请求量
        :param window_size: 时间窗口大小,单位为秒
        """
        self.max_requests = max_requests
        self.window_size = window_size
        self.requests = deque()

    def allow_request(self):
        """
        判断是否允许当前请求通过
        :return: 如果允许请求通过,返回True;如果不允许,返回False
        """
        current_time = time.time()
        # 移除时间窗口之前的请求记录
        while self.requests and self.requests[0] < current_time - self.window_size:
            self.requests.popleft()
        
        if len(self.requests) < self.max_requests:
            # 如果当前时间窗口内的请求量小于最大允许请求量,则允许当前请求通过
            self.requests.append(current_time)
            return True
        else:
            # 否则,拒绝当前请求
            return False

# 示例使用
if __name__ == "__main__":
    # 创建一个滑动窗口限流器,最大请求量为3,时间窗口为10秒
    limiter = SlidingWindowLimiter(3, 10)

    # 模拟请求
    for _ in range(5):
        if limiter.allow_request():
            print("请求通过")
        else:
            print("请求被限流")
        time.sleep(1)

'''令牌桶算法实现'''

import time
from threading import Lock

class TokenBucket:
    def __init__(self, rate, capacity):
        self._rate = rate  # 每秒往桶里放入令牌的速率
        self._capacity = capacity  # 桶的容量
        self._tokens = capacity  # 当前桶内的令牌数量
        self._last_time = time.time()  # 上次放入令牌的时间
        self._lock = Lock()  # 线程锁

    def consume(self, tokens=1):
        with self._lock:
            # 计算自上次放入令牌以来应该放入的令牌数量
            now = time.time()
            tokens_to_add = (now - self._last_time) * self._rate
            self._tokens = min(self._capacity, self._tokens + tokens_to_add)
            self._last_time = now

            # 检查桶内是否有足够的令牌
            if tokens <= self._tokens:
                self._tokens -= tokens
                return True
            return False

# 使用示例
bucket = TokenBucket(5, 10)  # 每秒放入5个令牌,桶容量为10
print(bucket.consume(3))  # 请求3个令牌
print(bucket.consume(7))  # 请求7个令牌
time.sleep(1)
print(bucket.consume(6))  # 经过1秒后,再请求6个令牌

'''漏桶算法实现'''
import time
import threading

class LeakyBucket:
    def __init__(self, capacity, leak_rate):
        """
        初始化漏桶算法
        :param capacity: 桶的容量
        :param leak_rate: 桶的漏水速率(每秒)
        """
        self.capacity = capacity  # 桶的最大容量
        self.leak_rate = leak_rate  # 每秒漏水量
        self.water = 0  # 当前桶内水量(即当前累积的请求量)
        self.last_leak_time = time.time()  # 上一次漏水时间

    def allow_request(self, request_units=1):
        """
        判断请求是否可以通过
        :param request_units: 请求量(默认为1)
        :return: 如果允许请求通过,返回True;否则返回False
        """
        current_time = time.time()
        # 计算上次漏水后桶内剩余的水量
        self.water -= (current_time - self.last_leak_time) * self.leak_rate
        self.water = max(0, self.water)  # 水量不能为负
        self.last_leak_time = current_time
        
        if self.water + request_units <= self.capacity:
            # 如果加上当前请求后不会溢出,则允许请求通过
            self.water += request_units
            return True
        else:
            # 否则,拒绝请求
            return False

# 示例使用
if __name__ == "__main__":
    bucket = LeakyBucket(5, 1)  # 容量为5,每秒漏水速率为1

    def send_requests():
        for _ in range(10):
            print(f"请求发送时间: {time.strftime('%X')} - 请求{'通过' if bucket.allow_request() else '被限流'}")
            time.sleep(0.5)

    thread = threading.Thread(target=send_requests)
    thread.start()
    thread.join()

  for _ in range(10):
        print(f"请求发送时间: {time.strftime('%X')} - 请求{'通过' if bucket.allow_request() else '被限流'}")
        time.sleep(0.5)

thread = threading.Thread(target=send_requests)
thread.start()
thread.join()

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Linux/Intuition

Intuition Enumeration nmap 使用 nmap 扫描系统常见端口&#xff0c;发现对外开放了 22 和 80&#xff0c;然后扫描这两个端口的详细信息 ┌──(kali㉿kali)-[~/vegetable/HTB/Intuition] └─$ nmap -sC -sV -p 22,80 -oA nmap 10.10.11.15 Starting Nmap 7.93 ( https:…

Springboot+vue项目影城管理系统

摘 要 本论文主要论述了如何使用JAVA语言开发一个影城管理系统&#xff0c;本系统将严格按照软件开发流程进行各个阶段的工作&#xff0c;采用B/S架构&#xff0c;面向对象编程思想进行项目开发。在引言中&#xff0c;作者将论述影城管理系统的当前背景以及系统开发的目的&…

计算机SCI期刊,IF=9.657,1区TOP,2周内出版!

一、期刊名称 Neural Networks 二、期刊简介概况 期刊类型&#xff1a;SCI 学科领域&#xff1a;计算机科学 影响因子&#xff1a;7.8 中科院分区&#xff1a;1区TOP 出版方式&#xff1a;订阅模式/开放出版 版面费&#xff1a;选择开放出版需支付$3350 三、期刊简介 神…

Shell生成支持x264的ffmpeg安卓全平台so

安卓 FFmpeg系列 第一章 Ubuntu生成ffmpeg安卓全平台so 第二章 Windows生成ffmpeg安卓全平台so 第三章 生成支持x264的ffmpeg安卓全平台so&#xff08;本章&#xff09; 文章目录 安卓 FFmpeg系列前言一、实现步骤1、下载x264源码2、交叉编译生成.a3、加入x264配置4、编译ffmp…

【ZIP技巧】ZIP分卷压缩包如何解压?

经过压缩的文件仍然过大&#xff0c;大家可能都会选择“分卷压缩”来压缩ZIP文件&#xff0c;但是当我们将压缩包分卷之后&#xff0c;解压的时候该如何解压&#xff1f;今天我们分享两个ZIP分卷压缩包如何解压的方法给大家。 一、 我们可以直接点击第一个分卷压缩包&#xf…

DHC:用于类别不平衡的半监督医学图像分割的双重去偏异构协同框架

文章目录 DHC: Dual-Debiased Heterogeneous Co-training Framework for Class-Imbalanced Semi-supervised Medical Image Segmentation摘要方法Distribution-aware Debiased Weighting (DistDW)Difficulty-aware Debiased Weighting (DiffDW) 实验结果 DHC: Dual-Debiased He…

Context capture/Pix4Dmapper/AutoCAD/CASS/EPS软件的安装流程与使用方法;土方量计算;无人机摄影测量数据处理

目录 专题一 无人机摄影测量技术应用现状及其发展 专题二 基本原理和关键技术讲解 专题三 无人机影像外业数据获取 专题四 数据处理环境建立与软件熟悉 专题五 GNSS数据土方量计算 专题六 基于无人机影像数据的正射影像制作 专题七 基于无人机影像数据的三维模型制作 专…

TS流加扰的判断

一般情况下&#xff0c;1套节目是否加扰 在SDT表中或者包头的加扰位2处判断。 1.SDT表的free_CA_mode0是未加密&#xff0c;1是加密&#xff1b;在SDT表中&#xff0c;只是一个规范&#xff08;如果节目加密了&#xff0c;应该让free_CA_mode1&#xff09;。实际上&#xff0c…

燃气电力瓶装气行业入户安检小程序开发

我们开发的小区业主入户安检小程序&#xff0c;旨在满足燃气、电力以及其他需要入户安检的行业需求。该程序支持自定义安检项目&#xff0c;实现线下实地安检与线上数据保存的完美结合。在安检过程中&#xff0c;我们可以拍照或录像&#xff0c;以确保安检的透明性和可追溯性&a…

【C++】-【QT】类库使用-001

1主窗口创建 1.1【makefile】配置 1 源码 QT widgetsSOURCES main.cpp2 图示 1.2源码 1 源码 #include <QWidget> #include <QApplication>using namespace std;int main(int argc,char *argv[]) {QApplication a(argc,argv);QWidget w;w.show();return a…

应聘项目经理,软考证书会是一个加分项吗?

加分项是必需的&#xff0c;特别是IT行业的项目经理职位。您可以在各大招聘网站上搜索项目经理职位&#xff0c;前景好、薪资高、待遇好的项目经理岗位&#xff0c;基本上都有证书的要求。非IT行业项目经理&#xff0c;可以考虑PMP证书或者其他与专业相关的证书&#xff0c;比如…

Android 高版本实现沉浸式状态栏

目前实现的android高版本沉浸式状态栏分为两类&#xff1a; 1、是纯透明状态栏&#xff1b; 2、是纯透明状态栏&#xff0c;但是状态栏字体是黑色&#xff1b; 将状态栏的代码封装到BaseActivity中更方便使用&#xff1a; BaseActivity: public abstract class BaseActivit…

大模型微调实战之强化学习 贝尔曼方程及价值函数(一)

大模型微调实战之强化学习 贝尔曼方程及价值函数 强化学习&#xff08;RL&#xff09;是机器学习中一个话题&#xff0c;不仅在人工智能方面。它解决问题的方式与人类类似&#xff0c;我们每天都在学习并在生活中变得更好。 作为一名大模型学习者&#xff0c;当开始深入研究强…

校验--ECC详细分析

ECC介绍 ECC 以下是针对瑞萨MCU的应用的ECC检测的详细分析。 当前公认安全有效的三大类公钥密钥体制分别为基于大数因子分解难题(RSA)、离散对数难题(DSA)和椭圆曲线离散对数&#xff08;ECC&#xff09;难题的密码体制。 保证RSA的安全性&#xff0c;则必须要增加密钥长度…

【最优传输二十九】Wasserstein Barycenterand Its Application to Texture Mixing

motivation 本文提出了离散概率分布的平均作为Monge-Kantorovich最优传输空间重心的新定义。为了克服数值求解这类问题所涉及的时间复杂性&#xff0c;原始的Wasserstein度量被一维分布上的切片近似所取代。这使我们能够引入一种新的快速梯度下降算法来计算点云的Wasserstein质…

Cesium 问题:billboard 加载未出来

文章目录 问题分析问题 接上篇 Cesium 展示——图标的依比例和不依比例缩放,使用加载 billboard 时,怀疑是路径的原因导致未加载成功 分析 原先

初步了解Kubernetes

目录 1. K8S概述 1.1 K8S是什么 1.2 作用 1.3 由来 1.4 含义 1.5 相关网站 2. 为什么要用K8S 3. K8S解决的问题 4. K8S的特性 5. Kubernetes集群架构与组件 6. 核心组件 6.1 Master组件 6.1.1 Kube-apiserver 6.1.2 Kube-controller-manager 6.1.3 kube-schedul…

算法学习008-登山爬石梯 c++动态规划/递归算法实现 中小学算法思维学习 信奥算法解析

目录 C登山爬石梯 一、题目要求 1、编程实现 2、输入输出 二、算法分析 三、程序编写 四、程序说明 五、运行结果 六、考点分析 七、推荐资料 C登山爬石梯 一、题目要求 1、编程实现 小明周末和朋友约好了一起去爬山&#xff0c;来到山下&#xff0c;发现登山道是…

【问题实操】银河高级服务器操作系统实例分享,开机之后反复重启

1.服务器环境以及配置 物理机/虚拟机/云/容器 物理机 外网/私有网络/无网络 私有网络 处理器&#xff1a; PHYTIUM FT2000PLUS 2200 MHz 内存&#xff1a; 128 GiB 整机类型/架构&#xff1a; HIKVISION DS-V BIOS版本&#xff1a; HK 601FBE02HK 网卡&#xff1…

VTK数据的读写--Vtk学习记录1--《VTK图形图像开发进阶》

读和写操作是VTK可视化管线两端相关的类--Reader和Writer类 Reader:将外部数据读入可视化管线&#xff0c;主要步骤如下 s1:实例化Reader对象 s2:指定所要读取的文件名 s3:调用Update()促使管线执行 对应的Writer: s1:实例化Writer对象 s2输入要写的数据以及指定写入的文…
最新文章