首页 > 其他分享 >服务器雪崩的应对策略之----限流

服务器雪崩的应对策略之----限流

时间:2024-06-18 19:32:41浏览次数:22  
标签:std count include int bucket ---- 限流 服务器 now

限流是一种控制流量的技术,旨在防止系统在高并发请求下被压垮。通过限流,可以确保系统在负载高峰期依然能保持稳定运行。常见的限流策略包括令牌桶算法、漏桶算法、计数器算法和滑动窗口算法。

常见的限流方法

1. 令牌桶算法 (Token Bucket Algorithm)

令牌桶算法是一种允许突发流量的限流算法。系统按照固定速率生成令牌,请求只有在获取到令牌后才能被处理。

原理

  • 系统按照固定速率往桶中添加令牌。
  • 当桶满时,多余的令牌会被丢弃。
  • 每个请求需要从桶中获取一个令牌,若令牌数量不足,请求被拒绝或等待。

示例代码

#include <iostream>
#include <chrono>
#include <thread>
#include <mutex>

class TokenBucket 
{
public:
    TokenBucket(int rate, int burst) : rate(rate), burst(burst), tokens(0) 
    {
        last_refill = std::chrono::steady_clock::now();
    }

    bool allow_request() 
    {
        std::lock_guard<std::mutex> lock(mutex);
        refill();
        if (tokens > 0) 
        {
            tokens--;
            return true;
        }
        return false;
    }

private:
    void refill() 
    {
        auto now = std::chrono::steady_clock::now();
        auto duration = std::chrono::duration_cast<std::chrono::seconds>(now - last_refill).count();
        tokens = std::min(burst, tokens + duration * rate);
        last_refill = now;
    }

    int rate; // 令牌生成速率
    int burst; // 桶的容量
    int tokens; // 当前令牌数量
    std::chrono::steady_clock::time_point last_refill;
    std::mutex mutex;
};

int main() 
{
    TokenBucket bucket(5, 10); // 每秒生成5个令牌,桶容量为10个令牌

    for (int i = 0; i < 20; ++i) 
    {
        if (bucket.allow_request()) 
        {
            std::cout << "Request " << i << " is allowed\n";
        } 
        else 
        {
            std::cout << "Request " << i << " is denied\n";
        }
        std::this_thread::sleep_for(std::chrono::milliseconds(200));
    }

    return 0;
}

2. 漏桶算法 (Leaky Bucket Algorithm)

漏桶算法是一种严格控制流量速率的限流算法。它将请求放入一个固定容量的桶中,并以固定速率处理请求,溢出的请求会被丢弃。

原理

  • 请求以任意速率进入桶。
  • 桶以固定速率漏出请求进行处理。
  • 如果桶满了,后续请求会被丢弃。

示例代码

#include <iostream>
#include <queue>
#include <thread>
#include <mutex>
#include <chrono>

class LeakyBucket 
{
public:
    LeakyBucket(int rate, int capacity) : rate(rate), capacity(capacity), water(0) 
    {
        last_check = std::chrono::steady_clock::now();
    }

    bool allow_request() 
    {
        std::lock_guard<std::mutex> lock(mutex);
        leak();
        if (water < capacity) 
        {
            water++;
            return true;
        }
        return false;
    }

private:
    void leak() 
    {
        auto now = std::chrono::steady_clock::now();
        auto duration = std::chrono::duration_cast<std::chrono::seconds>(now - last_check).count();
        int leaked = duration * rate;
        if (leaked > 0) 
        {
            water = std::max(0, water - leaked);
            last_check = now;
        }
    }

    int rate; // 漏出速率
    int capacity; // 桶的容量
    int water; // 当前水量
    std::chrono::steady_clock::time_point last_check;
    std::mutex mutex;
};

int main() 
{
    LeakyBucket bucket(1, 10); // 每秒处理1个请求,桶容量为10个请求

    for (int i = 0; i < 20; ++i) 
    {
        if (bucket.allow_request()) 
        {
            std::cout << "Request " << i << " is allowed\n";
        } 
        else 
        {
            std::cout << "Request " << i << " is denied\n";
        }
        std::this_thread::sleep_for(std::chrono::milliseconds(200));
    }

    return 0;
}

3. 计数器算法 (Counter Algorithm)

计数器算法是一种简单的限流策略,通过计数器在固定时间窗口内计数请求数量,如果超过限制,则拒绝请求。

原理

  • 在固定时间窗口内计数请求数量。
  • 如果请求数量超过设定的阈值,则拒绝请求。
  • 时间窗口结束后,重置计数器。

示例代码

#include <iostream>
#include <chrono>
#include <thread>
#include <mutex>

class CounterRateLimiter 
{
public:
    CounterRateLimiter(int limit, int window_size) : limit(limit), window_size(window_size), count(0) 
    {
        window_start = std::chrono::steady_clock::now();
    }

    bool allow_request() 
    {
        std::lock_guard<std::mutex> lock(mutex);
        auto now = std::chrono::steady_clock::now();
        if (std::chrono::duration_cast<std::chrono::seconds>(now - window_start).count() >= window_size) 
        {
            window_start = now;
            count = 0;
        }
        if (count < limit) 
        {
            count++;
            return true;
        }
        return false;
    }

private:
    int limit; // 时间窗口内允许的最大请求数
    int window_size; // 时间窗口大小(秒)
    int count; // 当前请求数
    std::chrono::steady_clock::time_point window_start;
    std::mutex mutex;
};

int main() 
{
    CounterRateLimiter limiter(5, 1); // 每秒最多处理5个请求

    for (int i = 0; i < 20; ++i) 
    {
        if (limiter.allow_request()) 
        {
            std::cout << "Request " << i << " is allowed\n";
        } 
        else 
        {
            std::cout << "Request " << i << " is denied\n";
        }
        std::this_thread::sleep_for(std::chrono::milliseconds(200));
    }

    return 0;
}

4. 滑动窗口算法 (Sliding Window Algorithm)

滑动窗口算法是计数器算法的改进版,通过滑动窗口精确统计请求数量,避免固定窗口带来的突发流量问题。

原理

  • 将时间窗口划分为多个小的子窗口。
  • 记录每个子窗口的请求数量。
  • 滑动窗口通过移动时间窗口来更新请求数量。

示例代码

#include <iostream>
#include <vector>
#include <chrono>
#include <thread>
#include <mutex>

class SlidingWindowRateLimiter 
{
public:
    SlidingWindowRateLimiter(int limit, int window_size, int bucket_count) 
        : limit(limit), window_size(window_size), bucket_count(bucket_count), buckets(bucket_count, 0), count(0) 
        {
        last_check = std::chrono::steady_clock::now();
    	}

    bool allow_request() 
    {
        std::lock_guard<std::mutex> lock(mutex);
        slide_window();
        if (count < limit) 
        {
            buckets[current_bucket]++;
            count++;
            return true;
        }
        return false;
    }

private:
    void slide_window() 
    {
        auto now = std::chrono::steady_clock::now();
        auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(now - last_check).count();
        int slide_count = duration * bucket_count / (window_size * 1000);
        if (slide_count > 0) 
        {
            for (int i = 0; i < slide_count && count > 0; ++i) 
            {
                current_bucket = (current_bucket + 1) % bucket_count;
                count -= buckets[current_bucket];
                buckets[current_bucket] = 0;
            }
            last_check = now;
        }
    }

    int limit; // 时间窗口内允许的最大请求数
    int window_size; // 时间窗口大小(秒)
    int bucket_count; // 子窗口数量
    std::vector<int> buckets; // 存储每个子窗口的请求数
    int count; // 当前请求总数
    int current_bucket = 0; // 当前子窗口索引
    std::chrono::steady_clock::time_point last_check;
    std::mutex mutex;
};

int main() 
{
    SlidingWindowRateLimiter limiter(5, 1, 10); // 每秒最多处理5个请求,划分为10个子窗口

    for (int i = 0; i < 20; ++i) 
    {
        if (limiter.allow_request()) 
        {
            std::cout << "Request " << i << " is allowed\n";
        } 
        else 
        {
            std::cout << "Request " << i << " is denied\n";
        }
        std::this_thread::sleep_for(std::chrono::milliseconds(200));
    }

    return 0;
}

结论

限流方法可以有效地保护系统免受过载的影响,确保系统在高并发情况下仍能稳定运行。通过选择适合的限流策略,可以根据不同场景和需求实现精确的流量控制。

标签:std,count,include,int,bucket,----,限流,服务器,now
From: https://blog.csdn.net/weixin_44046545/article/details/139757603

相关文章

  • Windows defender:威胁服务已经停止
    前言最近遇到了一件棘手的事情,Windowsdefender无法启动,Windows更新失败。我是发现电脑的好多文件被劫持,图片,excel表格,pdf文档,好多文件后缀被改为.locked,想解锁得花费0.1bit,大概5万元。网上的操作挺多的,又是命令行又是搞注册表的,没啥卵用。环境版本:Windows10专业版版本号:22......
  • 约瑟夫环递归算法详解与实现
    一、引言约瑟夫环问题是一个著名的理论问题,其背景是在古罗马时期,有n个犯人被围成一个圈,从第一个人开始报数,每次报到m的人将被处决,然后从下一个人开始重新报数,直到所有人都被处决。这个问题可以用递归算法来解决,本文将详细介绍约瑟夫环问题的递归算法,并给出C++代码实现。二......
  • 学习记录APP
    1、用户注册:用户注册信息包括用户ID(学号)、用户名(姓名),手机号码,用户单位(班级),用户班级四项基本信息,用户第一次注册后,用户姓名不用每次输入。2、设定每周学习目标:每周一设置学习目标。例如:本周完成数据库连接等等具体任务目标。3、每日学习记录:内容包括:开始时间、结束时间,每日学习......
  • 如何使用GPT?初学者的指南
    ChatGPT是一个非常先进的AI工具,它使用GPT-4架构,能够生成自然的语言回应。它的多功能性和理解复杂指令的能力,使得很多人用它来回答各种问题,就像用Google一样输入关键词。不过,ChatGPT还能做更多事情,下面我们来介绍一些技巧和提示,帮助你更好地使用ChatGPT。使用ChatGPT的步骤输......
  • 学习记录
     1.用户注册 用户可以通过注册功能创建自己的账户。注册信息包括以下内容:-用户ID(学号)-用户名(姓名)-手机号码-用户单位(班级)   首次注册后,用户的姓名将被记录,无需每次输入。    2.设定每周学习目标 每周一,用户可以设定学习目标,包括具体的任务目......
  • 基于知识图谱和neo4j图数据库的电影推荐系统(2024版)
    首先下载neo4j图数据库https://neo4j.com/deployment-center/知识图谱相关概念:知识图谱是一种结构化的知识存储形式,它以图形数据库为基础,用来表示实体(如人、地点、事件等)之间的复杂关系。这种技术结合了自然语言处理、信息提取、数据挖掘、图论等多种技术,目的是使机器能......
  • Rust中 测试用例编写
    //注定会断言失败的代码:断言1和2会不会相等#[cfg(test)]modtests{usesuper::*;#[test]fnone_result(){assert_eq!(1,2);}}注意点 1.编程环境:vscode+rust-analyzer(插件式)2.方法上添加标签(Attribute):#[cfg(test)]3.断言语句:asser......
  • C# 数字转罗马数字
    最近遇到一个需要整数转罗马数字的问题罗马数字的规则:I→1V→5X→10L→50C→100D→500M→1000字母从大到小依次排列,例如:8→XIII但存在一种特殊情况,使得小字母在大字母右侧,来表示后者减去前者:I可以放在V......
  • 在检视器Inspector中通过自定义属性实现显示中文名称
    在前人的基础上,整出来了一些完善一些的版本首先,在\Scripts下创建一个类CustomLabelAttribute usingSystem;usingUnityEngine;#ifUNITY_EDITOR[AttributeUsage(AttributeTargets.Field)]#endif///<summary>///使字段在Inspector中显示自定义的名称。///</summ......
  • 批量生产千万级数据 推送到kafka代码
    1、批量规则生成代码1、随机IP生成代码2、指定时间范围内随机日期生成代码3、随机中文名生成代码。packagecom.wfg.flink.connector.utils;importjava.time.LocalDate;importjava.time.LocalDateTime;importjava.time.LocalTime;importjava.util.ArrayList;i......