博客
关于我
[整理] 使用RateLimiter完成简单的大流量限流,抢购秒杀限流
阅读量:425 次
发布时间:2019-03-06

本文共 3055 字,大约阅读时间需要 10 分钟。

RateLimiter:基于令牌桶算法的限流解决方案

RateLimiter 是 Guava 库中基于令牌桶算法实现的限流工具,简单易用,适合根据系统需求调整令牌生成速率。它在抢购限流、网速限制等场景中表现出色。

1. 多任务处理:按秒限流

假设系统每秒最多允许处理 X 个任务,RateLimiter 可以帮助实现这个目标。通过创建一个 RateLimiter 实例,并在每个任务启动前调用 acquire 方法,可以确保每秒不超过指定数量的任务执行。

import com.google.common.util.concurrent.RateLimiter;import java.util.ArrayList;import java.util.List;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;public class Demo1 {    public static void main(String[] args) {        RateLimiter rateLimiter = RateLimiter.create(0.5); // 每秒最多 0.5 个令牌        List
tasks = new ArrayList<>(); for (int i = 0; i < 10; i++) { tasks.add(new UserRequest(i)); } ExecutorService threadPool = Executors.newCachedThreadPool(); for (Runnable runnable : tasks) { System.out.println("等待时间:" + rateLimiter.acquire()); threadPool.execute(runnable); } } private static class UserRequest implements Runnable { private int id; public UserRequest(int id) { this.id = id; } public void run() { System.out.println(id); } }}

运行结果表明,每 2 秒最多执行 1 个任务。通过 acquire 方法可以获取等待时间,确保无过度负载。

2. 抢购场景限流

在抢购场景中,RateLimiter 可以防止系统被过度负载。例如,数据库每秒可处理 10 个请求,超过限制会导致故障。

package com.tianyalei.controller;import com.google.common.util.concurrent.RateLimiter;import com.tianyalei.model.GoodInfo;import com.tianyalei.service.GoodInfoService;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;import javax.annotation.Resource;@RestControllerpublic class IndexController {    @Resource(name = "db")    private GoodInfoService goodInfoService;    RateLimiter rateLimiter = RateLimiter.create(10);    @RequestMapping("/miaosha")    public Object miaosha(int count, String code) {        System.out.println("等待时间" + rateLimiter.acquire());        if (goodInfoService.update(code, count) > 0) {            return "购买成功";        }        return "购买失败";    }    @RequestMapping("/add")    public Object add() {        for (int i = 0; i < 100; i++) {            GoodInfo goodInfo = new GoodInfo();            goodInfo.setCode("iphone" + i);            goodInfo.setAmount(100);            goodInfoService.add(goodInfo);        }        return "添加成功";    }}

测试显示,每秒前 10 个请求无需等待,后续请求每 0.1 秒一个,符合预期效果。

3. 抢购场景降级

直接使用 RateLimiter 可能导致用户等待,影响体验。通过 tryAcquire 方法设置超时,确保在指定时间内无法获取令牌时立即返回失败。

@RequestMapping("/buy")public Object miao(int count, String code) {    // 非阻塞获取令牌    if (!rateLimiter.tryAcquire(1000, TimeUnit.MILLISECONDS)) {        System.out.println("短期无法获取令牌,真不幸,排队也瞎排");        return "失败";    }    if (goodInfoService.update(code, count) > 0) {        System.out.println("购买成功");        return "成功";    }    System.out.println("数据不足,失败");    return "失败";}

在实际测试中,每秒大约有 22 个成功请求,78 个失败。通过降级策略,用户体验得到了显著提升。

补充:实际应用测试

部署到线上服务器后,测试结果如下:

  • 仅限流测试:数据库 CPU 占用率约 20%,Tomcat 超时较多。
  • 使用 RateLimiter 阻塞:数据库 CPU 不动,压力减少,但 Tomcat 超时仍有。
  • 使用非阻塞限流:QPS显著提升,压力降低,系统性能更优。
  • 通过 RateLimiter 的非阻塞方式,可以更好地控制流量,提升系统性能。

    转载地址:http://hhcuz.baihongyu.com/

    你可能感兴趣的文章
    NSSet集合 无序的 不能重复的
    查看>>
    NSUserdefault读书笔记
    查看>>
    NT AUTHORITY\NETWORK SERVICE 权限问题
    查看>>
    NT symbols are incorrect, please fix symbols
    查看>>
    ntelliJ IDEA 报错:找不到包或者找不到符号
    查看>>
    ntko web firefox跨浏览器插件_深度比较:2019年6个最好的跨浏览器测试工具
    查看>>
    ntko文件存取错误_苹果推送 macOS 10.15.4:iCloud 云盘文件夹共享终于来了
    查看>>
    ntpdate 通过外网同步时间
    查看>>
    NTP及Chrony时间同步服务设置
    查看>>
    NTP配置
    查看>>
    NUC1077 Humble Numbers【数学计算+打表】
    查看>>
    NuGet(微软.NET开发平台的软件包管理工具)在VisualStudio中的安装的使用
    查看>>
    Nuget~管理自己的包包
    查看>>
    nullnullHuge Pages
    查看>>
    NullPointerException Cannot invoke setSkipOutputConversion(boolean) because functionToInvoke is null
    查看>>
    Numix Core 开源项目教程
    查看>>
    NumPy 或 Pandas:将数组类型保持为整数,同时具有 NaN 值
    查看>>
    numpy 数组 dtype 在 Windows 10 64 位机器中默认为 int32
    查看>>
    numpy 数组与矩阵的乘法理解
    查看>>
    numpy 用法
    查看>>