Java实现接口限流方案

Java实现接口限流,通常有三种方案,分别是计数器算法、令牌桶算法和漏桶算法。下面分别介绍这三种方案的实现方法和代码示例。

1. 计数器算法

计数器算法的核心思想是,对窗口内的API请求进行计数,当计数超过设定的阈值时,拒绝请求。其中,窗口有两种实现方式:滑动窗口和计时窗口。

滑动窗口的实现方法如下(以限制1秒内请求不超过5次为例):

1.1 代码实现

import java.util.concurrent.ArrayBlockingQueue;

public class SlidingWindowRateLimiter {
    private int permitsPerSecond;
    private int maxPermits;
    private volatile int count;
    private ArrayBlockingQueue<Long> timestamps;

    public SlidingWindowRateLimiter(int permitsPerSecond, int maxPermits) {
        this.permitsPerSecond = permitsPerSecond;
        this.maxPermits = maxPermits;
        this.count = 0;
        this.timestamps = new ArrayBlockingQueue<>(maxPermits);
        for (int i = 0; i < maxPermits; i++) {
            this.timestamps.offer(System.currentTimeMillis() / 1000);
        }
    }

    public synchronized boolean tryAcquire() {
        long now = System.currentTimeMillis() / 1000;
        long last = this.timestamps.poll();
        this.timestamps.offer(now);
        this.count += this.permitsPerSecond * (now - last);
        if (this.count > this.maxPermits) {
            this.count = this.maxPermits;
        }
        if (this.count <= 0) {
            return false;
        } else {
            this.count--;
            return true;
        }
    }
}

1.2 示例说明

public class TestSlidingWindowRateLimiter {
    public static void main(String[] args) throws InterruptedException {
        int permitsPerSecond = 5;
        int maxPermits = 10;
        SlidingWindowRateLimiter rateLimiter = new SlidingWindowRateLimiter(permitsPerSecond, maxPermits);
        while (true) {
            if (rateLimiter.tryAcquire()) {
                System.out.println("请求成功");
            } else {
                System.out.println("请求失败");
            }
            Thread.sleep(200);
        }
    }
}

运行上述示例,可以看到程序每隔200毫秒尝试向接口发送请求,当请求次数超过10次时,接口将返回“请求失败”的提示信息。

2. 令牌桶算法

令牌桶算法的核心思想是,维护一个令牌桶,每秒钟往桶中添加一定数量的令牌,API请求从桶中获取令牌,如果桶中没有令牌,则拒绝请求。

2.1 代码实现

import java.util.concurrent.*;

public class TokenBucketRateLimiter {
    private int permitsPerSecond;
    private int maxPermits;
    private volatile int count;
    private final ScheduledExecutorService scheduler;
    private ScheduledFuture<?> scheduledFuture;

    public TokenBucketRateLimiter(int permitsPerSecond, int maxPermits) {
        this.permitsPerSecond = permitsPerSecond;
        this.maxPermits = maxPermits;
        this.count = maxPermits;
        this.scheduler = Executors.newScheduledThreadPool(1);
        this.scheduledFuture = this.scheduler.scheduleAtFixedRate(() -> {
            int newCount = count + permitsPerSecond;
            if (newCount > maxPermits) {
                count = maxPermits;
            } else {
                count = newCount;
            }
        }, 0, 1, TimeUnit.SECONDS);
    }

    public synchronized boolean tryAcquire() {
        if (this.count <= 0) {
            return false;
        } else {
            this.count--;
            return true;
        }
    }

    public void shutdown() {
        this.scheduledFuture.cancel(true);
        this.scheduler.shutdownNow();
    }
}

2.2 示例说明

public class TestTokenBucketRateLimiter {
    public static void main(String[] args) throws InterruptedException {
        int permitsPerSecond = 1;
        int maxPermits = 10;
        TokenBucketRateLimiter rateLimiter = new TokenBucketRateLimiter(permitsPerSecond, maxPermits);
        while (true) {
            if (rateLimiter.tryAcquire()) {
                System.out.println("请求成功");
            } else {
                System.out.println("请求失败");
            }
            Thread.sleep(500);
        }
    }
}

运行上述示例,可以看到程序每隔0.5秒尝试向接口发送请求,当桶中没有令牌时,接口将返回“请求失败”的提示信息。

3. 漏桶算法

漏桶算法的核心思想是,限制请求发送速率,即将API请求压入一个漏桶中,漏桶以固定速率将请求处理,当API请求超过漏桶最大容量时,拒绝请求。

3.1 代码实现

import java.util.concurrent.TimeUnit;

public class LeakyBucketRateLimiter {
    private int permitsPerSecond;
    private int maxPermits;
    private volatile int count;
    private long lastLeakTime;

    public LeakyBucketRateLimiter(int permitsPerSecond, int maxPermits) {
        this.permitsPerSecond = permitsPerSecond;
        this.maxPermits = maxPermits;
        this.count = 0;
        this.lastLeakTime = System.currentTimeMillis();
    }

    public boolean tryAcquire() {
        long now = System.currentTimeMillis();
        long leakTime = (now - lastLeakTime) / 1000;
        lastLeakTime = now;
        int leakCount = (int) (leakTime * permitsPerSecond);
        count = Math.max(0, count - leakCount);
        if (count >= maxPermits) {
            return false;
        } else {
            count++;
            return true;
        }
    }
}

3.2 示例说明

public class TestLeakyBucketRateLimiter {
    public static void main(String[] args) throws InterruptedException {
        int permitsPerSecond = 1;
        int maxPermits = 10;
        LeakyBucketRateLimiter rateLimiter = new LeakyBucketRateLimiter(permitsPerSecond, maxPermits);
        while (true) {
            if (rateLimiter.tryAcquire()) {
                System.out.println("请求成功");
            } else {
                System.out.println("请求失败");
            }
            Thread.sleep(500);
        }
    }
}

运行上述示例,可以看到程序每隔0.5秒尝试向接口发送请求,当请求数量超过漏桶的最大容量时,接口将返回“请求失败”的提示信息。

以上三种接口限流算法均有各自的优缺点,可根据具体需求选择适合的实现方式。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java实现接口限流方案 - Python技术站

(0)
上一篇 2023年5月19日
下一篇 2023年5月19日

相关文章

  • apache简介_动力节点Java学院整理

    Apache简介——动力节点Java学院整理 什么是Apache Apache是一种开源的、跨平台的Web服务器软件。它最初由美国国家超级电脑应用中心(NCSA)开发,随后成为了Apache软件基金会的一项开源软件项目。它可以运行在几乎所有包括Windows、Linux、Unix、MacOS在内的操作系统上。目前,Apache已成为世界上最流行的Web服务器…

    Java 2023年6月2日
    00
  • JavaSpringBoot报错“NotSupportedException”的原因和处理方法

    原因 “NotSupportedException” 错误通常是以下原因引起的: 数据库问题:如果您的数据库存在问题,则可能会出现此错误。在这种情况下,需要检查您的数据库并确保它们正确。 数据库驱动问题:如果您的数据库驱动存在问题,则可能会出现此错误。在这种情况下,需要检查您的数据库驱动并确保它们正确。 数据库版本问题:如果您的数据库版本与您的数据库驱动不兼…

    Java 2023年5月4日
    00
  • java多线程通过CompletableFuture组装异步计算单元

    使用CompletableFuture可以很方便地组装异步计算单元,让多个线程并发执行并将结果组合起来,以达到更高效的计算效果。下面我们来详细讲解Java多线程通过CompletableFuture组装异步计算单元的完整攻略。 1. CompletableFuture的创建 CompletableFuture是由Java8引入的异步编程API,通过它可以方便…

    Java 2023年5月19日
    00
  • Docker 搭建 Tomcat 运行环境的方法

    下面我来详细讲解一下“Docker 搭建 Tomcat 运行环境的方法”的完整攻略。 背景介绍 Docker 是一个开源的容器化引擎,可以轻松地实现应用程序隔离和打包,并且可以快速迁移。Tomcat 是一个非常流行的 Java Web 应用程序服务器,支持 Servlet 和 JSP 技术。在实际开发中,使用 Docker 搭建 Tomcat 运行环境非常便…

    Java 2023年5月19日
    00
  • Java日常练习题,每天进步一点点(54)

    针对这篇文章,我将会给出一份完整攻略。 首先,这篇文章是一篇关于Java练习题的题解,主要讲解了两个类型的练习题:数组的相关练习和字符串的相关练习。我们将针对这两个部分进行讲解。 数组部分题目讲解 在这篇文章中,给出了5道数组相关的练习题。其中,第一题要求计算一个数组的平均值,第二题要求找到一个数组中的最大值和最小值,第三题要求找到一个数组中的第二大值和第二…

    Java 2023年5月23日
    00
  • 深入浅出讲解Spring框架中依赖注入与控制反转及应用

    深入浅出讲解Spring框架中依赖注入与控制反转及应用 什么是依赖注入和控制反转 在传统的 Java 应用中,在一个类中如果需要依赖另一个类的对象,我们通常会使用“new”关键字手动创建这个对象。例如: public class UserService { private UserDao userDao = new UserDao(); // 其他方法 //…

    Java 2023年5月19日
    00
  • Spring JDBCTemplate原理及使用实例

    Spring JDBCTemplate原理及使用实例 什么是JDBCTemplate? JDBCTemplate是Spring Framework的核心组件之一。它是一个提供基本JDBC操作的类,它封装了JDBC的许多重复和常见的任务,并且提供了一种更简单和更轻松使用的方式来与数据库进行交互。 JDBCTemplate的工作原理 JDBCTemplate将J…

    Java 2023年5月20日
    00
  • Spring MVC的参数绑定和返回值问题

    Spring MVC的参数绑定和返回值问题 在Spring MVC框架中,控制器的方法是用来处理请求的,而参数绑定和返回值则是掌握Spring MVC的关键所在。在这篇文章中,我们将详细讨论Spring MVC的参数绑定和返回值问题。 参数绑定 Spring MVC框架中的参数绑定是指将HTTP请求中的参数自动地绑定到控制器方法的参数中。具体而言,就是将HT…

    Java 2023年6月15日
    00
合作推广
合作推广
分享本页
返回顶部