Java项目不使用框架如何实现限流?

简介: Java项目不使用框架如何实现限流?

在Java项目中,如果不使用任何框架来实现限流,可以通过手动编写代码来控制请求的速率。以下是一个简单的示例,展示了如何使用令牌桶算法实现限流:

import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;

public class RateLimiter {
   
    private final long maxTokens; // 最大令牌数
    private final long refillTokens; // 每次补充的令牌数
    private final long refillPeriod; // 补充令牌的时间间隔(毫秒)
    private long lastRefillTimestamp; // 上次补充令牌的时间戳
    private long currentTokens; // 当前令牌数
    private final LinkedBlockingQueue<Long> tokenBucket; // 存放令牌的队列

    public RateLimiter(long maxTokens, long refillTokens, long refillPeriod) {
   
        this.maxTokens = maxTokens;
        this.refillTokens = refillTokens;
        this.refillPeriod = refillPeriod;
        this.lastRefillTimestamp = System.currentTimeMillis();
        this.currentTokens = maxTokens;
        this.tokenBucket = new LinkedBlockingQueue<>(maxTokens);

        // 初始化令牌桶
        for (int i = 0; i < maxTokens; i++) {
   
            tokenBucket.offer(System.currentTimeMillis());
        }

        // 启动一个定时任务,定期补充令牌
        new Thread(() -> {
   
            while (!Thread.interrupted()) {
   
                try {
   
                    TimeUnit.MILLISECONDS.sleep(refillPeriod);
                    refill();
                } catch (InterruptedException e) {
   
                    Thread.currentThread().interrupt();
                }
            }
        }).start();
    }

    public boolean tryAcquire() {
   
        long now = System.currentTimeMillis();
        if (now - lastRefillTimestamp >= refillPeriod) {
   
            refill();
        }

        if (tokenBucket.isEmpty()) {
   
            return false; // 没有可用的令牌
        } else {
   
            Long token = tokenBucket.poll();
            if (token != null && token <= now) {
   
                return true; // 令牌有效
            } else {
   
                tokenBucket.offer(token); // 放回无效的令牌
                return false; // 没有可用的令牌
            }
        }
    }

    private void refill() {
   
        long now = System.currentTimeMillis();
        long tokensToAdd = (now - lastRefillTimestamp + refillPeriod - 1) / refillPeriod * refillTokens;
        lastRefillTimestamp = now;
        currentTokens = Math.min(maxTokens, currentTokens + tokensToAdd);

        for (int i = 0; i < tokensToAdd; i++) {
   
            tokenBucket.offer(now);
        }
    }
}

使用这个RateLimiter类,可以在需要限流的地方调用tryAcquire()方法,如果返回true,则表示有可用的令牌,可以继续处理请求;如果返回false,则表示没有可用的令牌,可以选择拒绝请求或者排队等待。
Java限流算法主要包括以下几种:

  1. 固定窗口算法:这种算法通过一个支持原子操作的计数器来累计一定时间窗口内的请求次数。当请求次数达到设定的阈值时,触发拒绝策略。每过一个时间窗口,计数器重置为0重新开始计数[^2^]。

  2. 滑动窗口算法:这是对固定窗口算法的改进。在滑动窗口算法中,窗口的大小是固定的,但起止时间是动态的。它将一个大的时间窗口分割成多个小的子窗口,每个子窗口单独计数,所有子窗口的计数之和不超过整体阈值。当新请求的时间点超过时间窗口的右边界时,窗口向右移动一个小窗口的距离,最左边的小窗口的计数值被舍弃[^3^][^4^]。

  3. 漏桶算法:漏桶算法将请求看作是流入的水,水桶容量有限,水以恒定的速率流出。如果水桶满了,新的请求(水)就会被丢弃。这种方法可以平滑突发流量,保证流量以相对稳定的速率处理[^5^]。

  4. 令牌桶算法:令牌桶算法通过一个令牌桶来控制请求的速率。系统以一定的速率向桶中添加令牌,当有请求到达时,需要从桶中取出一个令牌才能继续处理。如果桶中没有令牌,请求要么排队等待,要么被直接拒绝。这种方法既可以控制请求的突发流量,又可以允许一定程度的突发请求处理[^5^]。

总的来说,这些算法各有优缺点,适用于不同的场景。选择合适的限流算法取决于具体的应用需求、系统性能要求以及预期的流量模式。

目录
相关文章
|
15天前
|
算法 Java 数据处理
从HashSet到TreeSet,Java集合框架中的Set接口及其实现类以其“不重复性”要求,彻底改变了处理唯一性数据的方式。
从HashSet到TreeSet,Java集合框架中的Set接口及其实现类以其“不重复性”要求,彻底改变了处理唯一性数据的方式。HashSet基于哈希表实现,提供高效的元素操作;TreeSet则通过红黑树实现元素的自然排序,适合需要有序访问的场景。本文通过示例代码详细介绍了两者的特性和应用场景。
33 6
|
15天前
|
存储 Java
深入探讨了Java集合框架中的HashSet和TreeSet,解析了两者在元素存储上的无序与有序特性。
【10月更文挑战第16天】本文深入探讨了Java集合框架中的HashSet和TreeSet,解析了两者在元素存储上的无序与有序特性。HashSet基于哈希表实现,添加元素时根据哈希值分布,遍历时顺序不可预测;而TreeSet利用红黑树结构,按自然顺序或自定义顺序存储元素,确保遍历时有序输出。文章还提供了示例代码,帮助读者更好地理解这两种集合类型的使用场景和内部机制。
33 3
|
15天前
|
存储 Java 数据处理
Java Set接口凭借其独特的“不重复”特性,在集合框架中占据重要地位
【10月更文挑战第16天】Java Set接口凭借其独特的“不重复”特性,在集合框架中占据重要地位。本文通过快速去重和高效查找两个案例,展示了Set如何简化数据处理流程,提升代码效率。使用HashSet可轻松实现数据去重,而contains方法则提供了快速查找的功能,彰显了Set在处理大量数据时的优势。
26 2
|
17天前
|
存储 算法 Java
Java Set因其“无重复”特性在集合框架中独树一帜
【10月更文挑战第14天】Java Set因其“无重复”特性在集合框架中独树一帜。本文深入解析Set接口及其主要实现类(如HashSet、TreeSet)如何通过特定的数据结构(哈希表、红黑树)确保元素唯一性,并提供最佳实践建议,包括选择合适的Set实现类和正确实现自定义对象的`hashCode()`与`equals()`方法。
25 3
|
3天前
|
人工智能 前端开发 Java
基于开源框架Spring AI Alibaba快速构建Java应用
本文旨在帮助开发者快速掌握并应用 Spring AI Alibaba,提升基于 Java 的大模型应用开发效率和安全性。
基于开源框架Spring AI Alibaba快速构建Java应用
|
4天前
|
消息中间件 Java 数据库连接
Java 反射最全详解 ,框架设计必掌握!
本文详细解析Java反射机制,包括反射的概念、用途、实现原理及应用场景。关注【mikechen的互联网架构】,10年+BAT架构经验倾囊相授。
Java 反射最全详解 ,框架设计必掌握!
|
11天前
|
前端开发 Java 数据库连接
Spring 框架:Java 开发者的春天
Spring 框架是一个功能强大的开源框架,主要用于简化 Java 企业级应用的开发,由被称为“Spring 之父”的 Rod Johnson 于 2002 年提出并创立,并由Pivotal团队维护。
34 1
Spring 框架:Java 开发者的春天
|
10天前
|
SQL Java 关系型数据库
java连接mysql查询数据(基础版,无框架)
【10月更文挑战第12天】该示例展示了如何使用Java通过JDBC连接MySQL数据库并查询数据。首先在项目中引入`mysql-connector-java`依赖,然后通过`JdbcUtil`类中的`main`方法实现数据库连接、执行SQL查询及结果处理,最后关闭相关资源。
|
6天前
|
缓存 Java 数据库连接
Hibernate:Java持久层框架的高效应用
通过上述步骤,可以在Java项目中高效应用Hibernate框架,实现对关系数据库的透明持久化管理。Hibernate提供的强大功能和灵活配置,使得开发者能够专注于业务逻辑的实现,而不必过多关注底层数据库操作。
8 1
|
11天前
|
Java 数据库连接 开发者
Spring 框架:Java 开发者的春天
【10月更文挑战第27天】Spring 框架由 Rod Johnson 在 2002 年创建,旨在解决 Java 企业级开发中的复杂性问题。它通过控制反转(IOC)和面向切面的编程(AOP)等核心机制,提供了轻量级的容器和丰富的功能,支持 Web 开发、数据访问等领域,显著提高了开发效率和应用的可维护性。Spring 拥有强大的社区支持和丰富的生态系统,是 Java 开发不可或缺的工具。