当前位置: 代码网 > it编程>编程语言>Java > Java实现限流的6种方案详解

Java实现限流的6种方案详解

2025年06月08日 Java 我要评论
在 java 生态中,除了 guava 的ratelimiter,还有多种限流方案可供选择。以下是几种常见的替代方案:1. spring cloud gateway / spring cloud al

在 java 生态中,除了 guava 的 ratelimiter,还有多种限流方案可供选择。以下是几种常见的替代方案:

1. spring cloud gateway / spring cloud alibaba sentinel

适用于: spring cloud 微服务架构

// 在spring cloud gateway中的配置
@bean
public routelocator customroutelocator(routelocatorbuilder builder) {
    return builder.routes()
        .route("qrcode_route", r -> r.path("/api/qrcode/**")
            .filters(f -> f.requestratelimiter()
                .ratelimiter(redisratelimiter.class, config -> {
                    config.setburstcapacity(20);
                    config.setreplenishrate(10);
                }))
            .uri("http://localhost:8080"))
        .build();
}

2. resilience4j ratelimiter

适用于: 需要更丰富熔断限流功能的场景

// 添加依赖
implementation 'io.github.resilience4j:resilience4j-ratelimiter:1.7.1'

// 使用示例
ratelimiterconfig config = ratelimiterconfig.custom()
    .limitrefreshperiod(duration.ofseconds(1))
    .limitforperiod(10)
    .timeoutduration(duration.ofmillis(100))
    .build();

ratelimiter ratelimiter = ratelimiter.of("qrcodelimiter", config);

checkedrunnable restrictedcall = ratelimiter
    .decoratecheckedrunnable(ratelimiter, () -> generateqrcode());

try.run(restrictedcall)
    .onfailure(throwable -> response.senderror(429, "请求过于频繁"));

3. bucket4j

适用于: 需要分布式限流的场景

// 添加依赖
implementation 'com.github.vladimir-bukhtoyarov:bucket4j-core:7.0.0'

// 本地限流示例
bandwidth limit = bandwidth.classic(10, refill.intervally(10, duration.ofseconds(1)));
bucket bucket = bucket.builder().addlimit(limit).build();

if (bucket.tryconsume(1)) {
    // 处理请求
} else {
    response.senderror(429, "请求过于频繁");
}

4. redis + lua 分布式限流

适用于: 分布式环境下的精确限流

// redis限流脚本
private static final string limit_script =
    "local key = keys[1]\n" +
    "local limit = tonumber(argv[1])\n" +
    "local expire = tonumber(argv[2])\n" +
    "local current = tonumber(redis.call('get', key) or 0\n" +
    "if current + 1 > limit then\n" +
    "    return 0\n" +
    "else\n" +
    "    redis.call('incr', key)\n" +
    "    if current == 0 then\n" +
    "        redis.call('expire', key, expire)\n" +
    "    end\n" +
    "    return 1\n" +
    "end";

public boolean tryacquire(string key, int limit, int expiresec) {
    long result = redistemplate.execute(
        new defaultredisscript<>(limit_script, long.class),
        collections.singletonlist(key),
        string.valueof(limit), string.valueof(expiresec));
    return result != null && result == 1;
}

// 使用
if (!redislimiter.tryacquire("qrcode:"+ip, 10, 60)) {
    response.senderror(429, "请求过于频繁");
    return;
}

5. spring aop 实现简单限流

适用于: 简单的单体应用限流

@aspect
@component
public class ratelimitaspect {
    
    private final map<string, atomicinteger> counters = new concurrenthashmap<>();
    private final map<string, long> timestamps = new concurrenthashmap<>();
    
    @around("@annotation(ratelimit)")
    public object limit(proceedingjoinpoint pjp, ratelimit ratelimit) throws throwable {
        string key = ratelimit.key();
        int limit = ratelimit.limit();
        long interval = ratelimit.interval();
        
        long now = system.currenttimemillis();
        if (timestamps.getordefault(key, 0l) + interval < now) {
            timestamps.put(key, now);
            counters.put(key, new atomicinteger(0));
        }
        
        if (counters.getordefault(key, new atomicinteger(0)).incrementandget() > limit) {
            throw new responsestatusexception(httpstatus.too_many_requests, "请求过于频繁");
        }
        
        return pjp.proceed();
    }
}

// 自定义注解
@retention(retentionpolicy.runtime)
@target(elementtype.method)
public @interface ratelimit {
    string key() default "";
    int limit() default 10;
    long interval() default 1000; // ms
}

// 在controller方法上使用
@ratelimit(key = "qrcode", limit = 5, interval = 60000)
@getmapping("/generate")
public void generateqrcode(...) { ... }

6. apache commons pool 对象池限流

适用于: 需要控制资源并发使用的场景

genericobjectpool<object> pool = new genericobjectpool<>(new basepooledobjectfactory<>() {
    @override
    public object create() {
        return new object();
    }
});
pool.setmaxtotal(10); // 最大并发数

try {
    object permit = pool.borrowobject();
    try {
        generateqrcode(...);
    } finally {
        pool.returnobject(permit);
    }
} catch (exception e) {
    response.senderror(429, "系统繁忙,请稍后再试");
}

选择建议

  • 单体应用:spring aop 或 resilience4j
  • 微服务架构:spring cloud gateway 或 sentinel
  • 分布式系统:redis + lua 或 bucket4j
  • 需要丰富特性:resilience4j(支持熔断、限流、重试等)
  • 简单需求:guava ratelimiter 仍然是不错的选择

所有方案都可以与你的二维码生成接口集成,根据你的架构复杂度和具体需求选择合适的限流方案。

到此这篇关于java实现限流的6种方案详解的文章就介绍到这了,更多相关java限流内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com