各大开源组件都在使用什么样的限流算法?

本文介绍了常见的限流算法,如固定窗口、滑动窗口和令牌桶,并用Rust实现了令牌桶算法。探讨了各开源组件如Nginx、Dubbo等采用的限流策略,如sentinel的滑动窗口算法和SpringCloudGateway的令牌桶策略。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

各大开源组件都在使用什么样的限流算法?

简介

本文引用其他博文的观点介绍几种常见的限流算法,并用rust实现一个令牌桶算法的限流器。最后总结一些开源组件实际上使用的是什么样的限流算法。

限流算法有哪些

分布式系统中为了对服务进行保护,必须配置限流,避免流量高峰时将整个服务搞挂。常见的单机限流算法(单机限流指各个节点单独计算限流)有:固定窗口限流算法、滑动窗口限流算法、漏桶限流算法以及令牌桶限流算法。在某些场景下需要对所有节点处理的总流量进行限流、此时就需要进行分布式限流,常见的解决方法是引入redis来进行全局的分布式限流。具体可以参考以下两篇文章:
面试必备:四种经典限流算法讲解
5 种限流算法,7 种限流方式,挡住突发流量?

rust实现

下面Rust 代码实现了一个令牌桶算法,用于限制某个操作的频率。令牌桶算法是一种流量控制算法,它通过限制单位时间内通过的请求数量来保护系统免受过载的影响。

代码中定义了两个结构体:ConfigTokenBucketConfig 结构体用于存储令牌桶的配置信息,包括间隔时间、每次添加的令牌数和令牌桶容量。TokenBucket 结构体用于实现令牌桶算法,包括令牌桶的状态信息和相关方法。

TokenBucket 结构体中的 new 方法用于创建一个新的令牌桶,allowable 方法用于判断是否允许通过,try_refill 方法用于尝试添加令牌。在 allowable 方法中,首先调用 try_refill 方法尝试添加令牌,然后判断当前令牌数是否为 0,如果不为 0,则将令牌数减 1 并返回 true,否则返回 false。

try_refill 方法中,首先计算经过的时间和经过的间隔数,然后根据间隔数计算添加的令牌数,并更新令牌桶的状态信息。如果时间间隔过长,则重置令牌数。

use std::{cmp::min, convert::TryInto, time::Instant};

/// 令牌桶配置
#[derive(Debug, Clone)]
pub struct Config {
    /// 间隔时间
    pub interval: usize,
    /// 每次添加的令牌数
    pub amount: usize,
    /// 令牌桶容量
    pub capacity: usize,
}

/// 令牌桶
#[derive(Debug, Clone)]
pub struct TokenBucket {
    config: Config,
    tokens: usize,
    last_refill_time: Instant,
}

impl TokenBucket {
    /// 创建一个新的令牌桶
    pub fn new(config: Config) -> Self {
        Self {
            tokens: config.capacity,
            config,
            last_refill_time: Instant::now(),
        }
    }

    /// 尝试添加令牌
    fn try_refill(&mut self) {
        match self.last_refill_time.elapsed().as_millis().try_into() {
            Ok(elapsed) => {
                // 计算经过的时间
                let elapsed: usize = elapsed;
                // 计算经过的间隔数
                let internal_count: usize = elapsed / self.config.interval;
                if internal_count > 0 {
                    // 计算添加的令牌数
                    self.tokens = min(
                        self.config.capacity,
                        self.tokens + internal_count * self.config.amount,
                    );
                    // 更新最后添加令牌的时间
                    self.last_refill_time = Instant::now();
                }
            }
            Err(_e) => {
                // 时间间隔过长,重置令牌数
                self.tokens = self.config.capacity;
            }
        };
    }

    /// 是否允许通过
    pub fn allowable(&mut self) -> bool {
        self.try_refill();
        if self.tokens == 0 {
            false
        } else {
            self.tokens -= 1;
            true
        }
    }
}

#[cfg(test)]
mod test {
    use std::time::Instant;

    use crate::Config;

    use super::TokenBucket;

    #[test]
    /// 令牌桶测试
    pub fn token_bucket_test() {
        // 配置令牌桶
        let config = Config {
            interval: 10, // 间隔时间为10ms
            amount: 100, // 每次添加的令牌数为100
            capacity: 100, // 令牌桶容量为100
        };
        let config_clone = config.clone();
        let mut bucket = TokenBucket::new(config); // 创建令牌桶
        let start = Instant::now(); // 记录开始时间
        let mut last_print = Instant::now(); // 记录上次输出时间
        let mut count = 0; // 记录通过的请求数
        loop {
            if bucket.allowable() { // 如果允许通过
                count += 1; // 记录通过的请求数加1
            }
            if last_print.elapsed().as_millis() > 100 { // 如果距离上次输出时间超过100ms
                println!("qps:{}", count * 10); // 输出qps
                assert!(count > 100 / config_clone.interval * config_clone.amount * 8 / 10); // 断言qps在合理范围内
                assert!(count < 100 / config_clone.interval * config_clone.amount * 12 / 10); // 断言qps在合理范围内
                count = 0; // 重置通过的请求数
                last_print = Instant::now(); // 更新上次输出时间
            }
            if start.elapsed().as_millis() > 1000 { // 如果经过时间超过1000ms
                break; // 退出循环
            }
        }
    }
}

fn main() {}

各开源组件中的限流算法

那么市面上常见的开源框架使用的是什么样的开源算法呢?见下表

开源组件算法参考资料
nginx漏桶算法文档
源码
dubbo令牌桶算法
间隔性发放令牌(满足一定间隔才会一次性发放令牌)
文档
源码
Sentinel(阿里的流量治理组件)滑动窗口算法
有等待+超时机制
文档
源码
rpcx (最好的Go语言的RPC服务治理框架)令牌桶算法
间隔性发放令牌
文档
源码
motan (微博的RPC框架)简单计数,仅限制当前的并发数量源码
spring cloud gateway令牌桶算法
匀速发放令牌
源码
brpc自适应限流文档
源码
orleans简单的阈值限流文档
源码
resilience4j自定义的限流文档
源码
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值