加入收藏 | 设为首页 | 会员中心 | 我要投稿 | RSS
您当前的位置:首页 > 公告

限流的简单使用及学习

时间:2024-11-13 13:48:37  来源:http://www.baidu.com/  作者:亲卫队请问

前言

近期,我们的系统经历了重大的架构重构与下游子服务的升级改造。整个系统采用Spring Cloud进行服务间的调用与交互。作为负责业务服务端的我,专为Web端和PC端提供接口调用。在系统刚上线之际,我们遭遇了一场突如其来的雪崩事件。调用链路相当简洁:由于文本匹配服务需要分词、匹配,并从ES获取匹配后的术语语料等数据,导致了请求堆积,最终服务在短暂时间内崩溃。为了紧急应对这种情况,我们决定在业务方实施限流机制,并着手优化下游的匹配算法。这也为我提供了学习限流算法的良好机会。

限流算法概述

常见的限流算法包括:令牌桶、漏桶和计数器。

计数器限流算法详解

计数器是最简单且常用的限流算法之一,主要用于限制总并发数。无论是数据库连接池大小、线程池大小还是程序访问并发数,都常采用计数器算法。

在Redis中实施限流的方法

针对方法级别的限流措施,我们采用了Redis作为实现手段。以下是一个服务类的方法展示:

@Service

@Transactional

@Slf4j

public class MethodThrottleService {

@Autowired

private RedisTemplate redisTemplate;

/

限流方法,通过Redis进行方法级别的限流措施。

通过指定key值验证是否为合法请求,如果在规定缓存时间内该key值仍存在,则视为非法请求。

@param key 请求key值

@param expireTime 缓存过期时间

@param timeUnit 缓存时间单位(如秒、毫秒等)

@return 是否过期(true或false)

/

public Boolean validateKeyRequest(String key, int expireTime, TimeUnit timeUnit) {

ValueOperations ops = redisTemplate.opsForValue(); // 获取值操作对象

String result = ops.get(key); // 获取缓存中的值

if (StringUtils.isNotBlank(result)) { // 如果缓存中存在值(非空),说明是非法请求或已处理过的请求,返回false表示请求不合法。否则设置缓存并返回true表示是合法请求。}

ops.set(key, key, expireTime, timeUnit); // 设置缓存键值对及其过期时间。

通过Redis进行限流可以精确到用户及方法的级别。基于请求的key值进行限流,限制了特定时间段内相同参数请求的次数。Redis限流存在性能瓶颈,频繁的读写操作以及设置过期时间会对Redis性能产生较大影响。此种方法并不推荐。

对于限流策略,我们还有其他的选择如计数器(可以使用AtomicInteger和Semaphore)和两种常见的算法:令牌桶和漏桶。令牌桶算法描述的是一个拥有固定容量的桶以固定的速率添加令牌。当桶满时,新添加的令牌会被丢弃或拒绝。每个数据包到达时,会删除相应数量的令牌并发送数据包。如果令牌不足,则数据包会被限流。关于令牌桶的实现,我们可以使用Guava开源库的RateLimiter。每秒产生固定数量的令牌是这种算法的一个常见设置。漏桶算法则是固定容量的桶以常量的固定速率流出水滴,无论流入的速度如何,流出的速度始终保持不变。如果流入的请求超过了容量限制,则请求会被丢弃。令牌桶和漏桶算法各有特点,可以根据实际需求选择使用哪种算法。这两种算法在实际应用中都有很好的表现,可以根据具体情况选择最适合的限流策略。具体实现方式可以参考原文出处提供的链接内容了解更多细节。

来顶一下
返回首页
返回首页
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表
推荐资讯
相关文章
    无相关信息
栏目更新
栏目热门