限流器(一):guava应用级限流器RateLimiter之SmoothBursty

本文介绍了Guava的RateLimiter限流器,特别是SmoothBursty策略。SmoothBursty使用令牌桶算法,允许在空闲时积累令牌以应对突发流量。文章通过示例和时序图详细解析了其工作原理,包括关键属性如stableIntervalMicros、maxBurstSeconds和storedPermits,并展示了如何创建和使用限流器。
摘要由CSDN通过智能技术生成

一、前言

本系列是针对源码实现来讲解的。
本篇是限流器讲解的第一篇,最近在使用限流器,然后研究了下,本系列也是为了记录自己的研究成果,方便以后自己回来复习。
常用的限流器有令牌桶限流器和漏桶限流器,guava实现的限流器RateLimiter算是比较常用的应用级限流器。RateLimiter内部有两个实现:SmoothBursty和SmoothWarmingUp,这一篇先讲解SmoothBursty限流器。
SmoothBursty限流器使用令牌桶算法实现,这个限流器在空闲时候能够存储一定的令牌(默认是1秒钟时间产生的令牌),可以应对空闲一段时间后突然的爆发量请求。
guava的RateLimiter有一个核心的设计思想:当前请求的债务(请求的令牌大于限流器存储的令牌数)由下一个请求来偿还(上个请求亏欠的令牌,下个请求需要等待亏欠令牌生产出来以后才能被授权)

二、令牌桶限流器示意图

令牌桶限流器
限流器随着时间的推移会不断生产令牌,请求到来以后需要请求令牌,得到令牌以后就可以通过并开始业务处理,如果暂时没有可用的令牌则需要等待令牌的生产,待拿到令牌以后才能开始进行业务处理。

三、使用示例

这里看一下guava给出的使用示例。

  • 当我们有一系列的任务需要执行,并且我们期望是每秒执行2个任务:
  final RateLimiter rateLimiter = RateLimiter.create(2.0); // 速率是2令牌/秒
  void submitTasks(List tasks, Executor executor) {
    for (Runnable task : tasks) {
      r
在 Spring 微服务中,可以使用 Zuul 网关实现基于过滤限流。Zuul 是 Netflix 开源的一个基于 JVM 的路由和服务端负载均衡,可以用来构建微服务架构中的网关。 以下是使用 Zuul 实现基于过滤限流的步骤: 1. 添加 Zuul 依赖。可以在 Spring Boot 项目中添加以下依赖: ``` <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-zuul</artifactId> </dependency> ``` 2. 创建一个 Zuul 过滤。可以实现 com.netflix.zuul.ZuulFilter 接口,并重写其抽象方法。在该过滤中,可以实现限流逻辑。 3. 将过滤注册到 Zuul 中。可以在 Spring Boot 应用的配置文件中添加以下配置: ``` zuul: routes: my-service: path: /my-service/** serviceId: my-service filters: rate-limit: type: pre url: http://localhost:8080/limit ``` 其中,my-service 是需要进行限流的服务名,/my-service/** 是需要进行限流的路径,my-service 是该服务的注册名,rate-limit 是自定义的限流过滤名。 4. 配置限流参数。可以在应用的配置文件中添加以下配置: ``` rate-limiter: enabled: true limit: 1000 time-interval: 1 ``` 其中,enabled 表示是否启用限流limit 表示每个时间间隔内允许的请求数,time-interval 表示时间间隔。 5. 编写限流逻辑。在自定义的限流过滤中,可以使用 Redis、Guava、Bucket4j 等工具实现限流逻辑。以下是一个使用 Redis 实现限流的示例: ```java @Component public class RateLimitFilter extends ZuulFilter { private RedisTemplate<String, String> redisTemplate; @Autowired public RateLimitFilter(RedisTemplate<String, String> redisTemplate) { this.redisTemplate = redisTemplate; } @Override public String filterType() { return "pre"; } @Override public int filterOrder() { return 1; } @Override public boolean shouldFilter() { return true; } @Override public Object run() throws ZuulException { String ipAddress = RequestContext.getCurrentContext().getRequest().getRemoteAddr(); String key = "rate-limit:" + ipAddress; ValueOperations<String, String> ops = redisTemplate.opsForValue(); Long count = ops.increment(key, 1); if (count == 1) { redisTemplate.expire(key, 1, TimeUnit.SECONDS); } Long limit = Long.valueOf(redisTemplate.opsForValue().get("rate-limiter:limit")); Long timeInterval = Long.valueOf(redisTemplate.opsForValue().get("rate-limiter:time-interval")); if (count > limit) { throw new RuntimeException("Rate limit exceeded"); } return null; } } ``` 在上面的示例中,我们使用 Redis 存储每个 IP 地址的请求数,并在达到限流阈值时抛出异常。同时,我们从 Redis 中获取限流参数,即每个时间间隔内允许的请求数和时间间隔。 以上就是使用 Zuul 实现基于过滤限流的步骤。通过配置和编写逻辑,我们可以在微服务架构中对单个服务或多个服务进行限流
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值