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日

相关文章

  • Java Spring 声明式事务详解

    Java Spring 是一个非常流行的开源框架,可以用来构建企业级应用程序。Spring 内置了事务管理器,提供了声明式事务的支持,让我们能够更加方便地管理事务。本篇文章将着重讲解 Java Spring 声明式事务的完整攻略。 什么是声明式事务 声明式事务是基于 Spring AOP 的一种事务管理方式,它通过对业务方法进行拦截和代理,从而实现自动管理事…

    Java 2023年5月20日
    00
  • Java中线程上下文类加载器超详细讲解使用

    Java中线程上下文类加载器超详细讲解使用 前言 在Java多线程中,经常会出现跨类加载器的情况,例如Web容器中的应用程序的类加载器和Java线程在使用的类加载器可以是不同的实例。而在Java中,不同的类加载器对于同一个类的加载得到的Class对象实例是不同的,这样就会导致在不同的类加载器中创建的对象实例无法相互转换,从而引发一系列问题。为此,Java中引…

    Java 2023年5月19日
    00
  • Java异常处理方法汇总

    Java异常处理方法汇总 在Java编程中,异常是一种错误情况或意外情况,它可能会中断程序的正常执行,并且可能会导致程序崩溃。异常处理机制可以帮助我们解决这些问题。本文将介绍Java中的异常处理机制及其各种方法。 异常基础 Java中,所有的异常都是Throwable类的子类。RuntimeException和CheckedException是两种最常用的异…

    Java 2023年5月27日
    00
  • 深入理解约瑟夫环的数学优化方法

    深入理解约瑟夫环的数学优化方法 什么是约瑟夫环问题 约瑟夫环问题是一个数学问题,由公元一世纪末的犹太历史学家弗拉维奥·约瑟夫(Flavius Josephus)所提出,其描述如下: N个人排成一圈,从第1个人开始报数,报到M的人出圈,剩下的人再从1开始报数,报到M的人又出圈……直到剩下最后一个人。 问题的解法 穷举法 穷举法是一种暴力破解的方法,遍历…

    Java 2023年5月26日
    00
  • JAVA中SpringBoot启动流程分析

    以下是详细的Java中SpringBoot启动流程分析。 1. SpringBoot启动流程概述 SpringBoot是一种快速构建Spring应用的工具,其启动过程分为以下几个步骤: 首先,通过maven或gradle的构建工具编译项目代码,并将SpringBoot框架及相关依赖集成进项目中。 接着,在启动类中通过SpringApplication.run…

    Java 2023年5月15日
    00
  • spring设置拦截器代码实例

    下面我将为你详细讲解”Spring设置拦截器代码实例”的完整攻略,包括以下内容: 什么是拦截器 Spring中的拦截器 设置Spring拦截器的步骤 两个代码示例 1. 什么是拦截器 拦截器(Interceptor)是一种AOP(面向切面编程)思想的应用,它是用来处理请求的,类似于Servlet中的过滤器(Filter)。拦截器可以在一个请求时的preHan…

    Java 2023年5月19日
    00
  • 什么是Java持久化?

    Java持久化是指将数据从内存中持久化保存到磁盘文件或者数据库中。它是Java应用程序中一个核心的概念之一,因为在应用程序中处理数据的时候,通常需要将其保存或者读取,而持久化技术就为我们实现这一功能提供了便利。在Java中,通常使用以下几种持久化技术。 文件持久化 通过文件持久化技术,我们可以将程序中的对象数据以文件的形式保存到磁盘上,以便程序启动时,可以直…

    Java 2023年5月11日
    00
  • SpringBoot集成整合JWT与Shiro流程详解

    下面是对于“SpringBoot集成整合JWT与Shiro流程详解”的完整攻略。 概述 在传统的Web应用中,我们通常采用用户名和密码进行身份认证,但这种方式很容易受到各种攻击,例如:暴力破解、钓鱼等。为了解决这些问题,我们可以采用JWT的方式进行身份认证,并使用Shiro进行授权管理。本文将详细介绍SpringBoot集成整合JWT与Shiro的流程。 J…

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