Java中实现接口限流的方案详解

 更新时间:2023年05月31日 11:19:09   作者:iiopsd  
常用的接口限流方案就是计数器限流方案、时间窗口限流方案和令牌桶限流方案等,这些方案的概念大致也知道,但是实际上也没有实现过,所以本文就来自动动手实践一下吧

前言

今天看技术文章时看到一篇文章在讨论接口限流问题,觉得业务场景经常会使用到,就思考了一下如果是我会怎么实现?常用方案就是计数器限流方案、时间窗口限流方案和令牌桶限流方案等。这些方案的概念大致也知道,但是实际上也没有实现过,于是就自己试试实现逻辑,先动手再说。

场景

假设我们的场景是:

接口10秒内最多请求3次

思路

我想到的实现思路是有点时间窗口方案的样子,大致就是缓存请求时间,然后在每次请求的时候去校验10秒内是否超过3次请求。

图示

假设下面是请求的时间(单位:秒),那么前三次都可以请求成功,一个大小为3的数组缓存数据cache就是红框所示:

接下去的第四个请求、第五个请求和第一个缓存时间对比,发现都小于10秒,则请求不通过。

第六个请求时间和第一个请求时间对比,时间大于10秒,所以请求通过,然后更新缓存数据cache,缓存的第一个数据改为第二个请求时间,缓存第二个数据改为第三个请求时间,缓存第三个数据改为第6个请求时间,如下图蓝框所示,依次类推校验每次请求是否符合场景要求。

实现

1.声明一个数组cache(数组大小可以为最大请求次数3),储存请求时间;

因为我们要对比请求时间,所以讲请求缓存下来可以节省查数据库的时间。因为场景说明限制3次,所以我们只需要知道最后3个请求的时间就可以完成校验,之前的数据可以忽略。

2.首先是初始化情况,当请求小于3的时候,请求直接通过,并缓存当前请求时间;

3.当请求大于等于3的时候,判断当前请求时间和倒数第三次请求(cache[0]的数据)的间隔时间是否超过10秒,如果是则通过,否则通过。

通过的时候,要更新缓存数据,将数据前移,这次请求时间就是最后一次请求时间。

// 更新缓存
cache.set(0, cache.get(1));
cache.set(1, cache.get(2));
cache.set(2, now);

4.最后执行下代码验证下结果

完整代码如下所示:

package demo;
import cn.hutool.core.date.DateUtil;
import lombok.SneakyThrows;
import lombok.val;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Random;
/**
 * 限流示例,每分钟只能请求3次
 */
public class LimitFlowDemo {
    // 记录最后3次请求时间
    List<Long> cache = new ArrayList<>();
    int limitTime = 10;
    public boolean validate() {
        boolean res = false;
        val now = DateUtil.currentSeconds();
        System.out.println("当前时间:" + DateUtil.format(new Date(now * 1000), "HH:mm:ss"));
        if (cache.size() < 3) {
            res = true;
            cache.add(now);
        } else if(now - cache.get(0) > limitTime){
            res = true;
            // 更新缓存
            cache.set(0, cache.get(1));
            cache.set(1, cache.get(2));
            cache.set(2, now);
        }
        System.out.println("请求结果:" + res);
        return res;
    }
    @SneakyThrows
    public static void main(String[] args) {
        Random rd = new Random();
        LimitFlowDemo demo = new LimitFlowDemo();
        for (int i = 0; i < 1000; i++) {
            demo.validate();
            //            Thread.sleep(rd.nextInt(3000));
            Thread.sleep(500);
        }
    }
}

到此这篇关于Java中实现接口限流的方案详解的文章就介绍到这了,更多相关Java接口限流内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • SpringCloud Feign转发请求头(防止session失效)的解决方案

    SpringCloud Feign转发请求头(防止session失效)的解决方案

    这篇文章主要介绍了SpringCloud Feign转发请求头(防止session失效)的解决方案,本文给大家分享两种解决方案供大家参考,感兴趣的朋友跟随小编一起看看吧
    2020-10-10
  • Java中的运算符有哪些详解

    Java中的运算符有哪些详解

    这篇文章主要给大家介绍了关于Java中运算符有哪些的相关资料,包括算术运算符、关系运算符、逻辑运算符、位运算符、增量运算符和自增/自减运算符,文中通过代码介绍的非常详细,需要的朋友可以参考下
    2024-10-10
  • SpringBoot实现文件下载的限速功能

    SpringBoot实现文件下载的限速功能

    在SpringBoot项目中,实现文件下载的限速功能可以有效控制服务器带宽的占用,并防止单个用户消耗过多的资源,本文将通过具体的代码示例和详细的流程解释,介绍如何在SpringBoot项目中实现文件下载的限速功能,需要的朋友可以参考下
    2024-07-07
  • Java构造函数通透理解篇

    Java构造函数通透理解篇

    这篇文章主要介绍了Java构造函数,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-09-09
  • Mybatis-plus中IService接口的基本使用步骤

    Mybatis-plus中IService接口的基本使用步骤

    Mybatis-plus是一个Mybatis的增强工具,它提供了很多便捷的方法来简化开发,IService是Mybatis-plus提供的通用service接口,封装了常用的数据库操作方法,包括增删改查等,下面这篇文章主要给大家介绍了关于Mybatis-plus中IService接口的基本使用步骤,需要的朋友可以参考下
    2023-06-06
  • Java RandomAccessFile的用法详解

    Java RandomAccessFile的用法详解

    下面小编就为大家带来一篇Java RandomAccessFile的用法详解。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2016-06-06
  • Java实现AOP面向切面编程的实例教程

    Java实现AOP面向切面编程的实例教程

    这篇文章主要介绍了Java实现AOP面向切面编程的实例教程,通常Java中的AOP都是利用Spring框架中造好的轮子来开发,而本文则关注于Java本身AOP的设计模式实现,需要的朋友可以参考下
    2016-04-04
  • 记一次Feign中实现传实体Bean的问题

    记一次Feign中实现传实体Bean的问题

    这篇文章主要介绍了记一次Feign中如何传实体Bean的问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-03-03
  • 使用Spring和Redis创建处理敏感数据的服务的示例代码

    使用Spring和Redis创建处理敏感数据的服务的示例代码

    许多公司处理的用户敏感数据由于法律限制不能永久存储,根据规定,这些数据的存储时间不能超过预设期限,并且最好在用于服务目的之后就将其删除,解决这个问题有多种可能的方案,在本文中,我想展示一个利用 Spring 和 Redis 处理敏感数据的应用程序的简化示例
    2025-04-04
  • Spring IOC与DI核心重点分析

    Spring IOC与DI核心重点分析

    IOC也是Spring的核心之一了,之前学的时候是采用xml配置文件的方式去实现的,后来其中也多少穿插了几个注解,但是没有说完全采用注解实现。那么这篇文章就和大家分享一下,全部采用注解来实现IOC + DI
    2022-10-10

最新评论