Spring Cloud Gateway接口限流处理
添加依赖#
<!-- 令牌桶限流 --> <dependency> <groupId>com.github.vladimir-bukhtoyarov</groupId> <artifactId>bucket4j-core</artifactId> <version>7.5.0</version> </dependency>
过滤器#
import com.alibaba.fastjson.JSON; import io.github.bucket4j.Bandwidth; import io.github.bucket4j.Bucket; import io.github.bucket4j.Refill; import org.springframework.cloud.gateway.filter.GatewayFilterChain; import org.springframework.cloud.gateway.filter.GlobalFilter; import org.springframework.core.annotation.Order; import org.springframework.core.io.buffer.DataBuffer; import org.springframework.http.HttpStatus; import org.springframework.http.server.reactive.ServerHttpRequest; import org.springframework.stereotype.Component; import org.springframework.web.server.ServerWebExchange; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; import java.net.InetSocketAddress; import java.time.Duration; import java.util.HashMap; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; /** * 限流处理 */ @Component @Order(-200) public class RateLimitFilter implements GlobalFilter { /** * key=url * value=Map<String, Bucket> * key=ip * value=Bucket */ private static final ConcurrentHashMap<String, ConcurrentHashMap<String, Bucket>> BUCKET_CACHE_MAP = new ConcurrentHashMap<>(); private static final String HEADER_IP = "X-Forwarded-For"; // 每秒钟允许的请求次数 private static final int REQUEST_PER_SECOND = 10; @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { ServerHttpRequest request = exchange.getRequest(); String ip = getIpAddress(request); //模拟不同ip请求 // String ip = request.getHeaders().getFirst("ip"); String url = request.getURI().getPath(); Bucket bucket; ConcurrentHashMap<String, Bucket> bucketMap = BUCKET_CACHE_MAP.get(url); if (bucketMap == null) { ConcurrentHashMap<String, Bucket> valueMap = new ConcurrentHashMap<>(); bucket = valueMap.computeIfAbsent(ip, k -> { // 每秒钟可以处理的请求数量 Bandwidth limit = Bandwidth.classic(REQUEST_PER_SECOND, Refill.intervally(REQUEST_PER_SECOND, Duration.ofSeconds(1))); // 创建Bucket4j桶 return Bucket.builder().addLimit(limit).build(); }); BUCKET_CACHE_MAP.put(url, valueMap); } else { bucket = bucketMap.computeIfAbsent(ip, k -> { // 1、每秒钟可以处理的请求数量 // 2、桶每秒补充多少个 Bandwidth limit = Bandwidth.classic(REQUEST_PER_SECOND, Refill.intervally(REQUEST_PER_SECOND, Duration.ofSeconds(1))); // 创建Bucket4j桶 return Bucket.builder().addLimit(limit).build(); }); } if (bucket.tryConsume(1)) { //放行 return chain.filter(exchange); } exchange.getResponse().setStatusCode(HttpStatus.TOO_MANY_REQUESTS); Map<String, Object> resultMap = new HashMap<>(); resultMap.put("code", 110); resultMap.put("msg", "请求过于频繁,请稍后重试"); DataBuffer buffer = exchange.getResponse() .bufferFactory().wrap(JSON.toJSONString(resultMap).getBytes()); return exchange.getResponse().writeWith(Flux.just(buffer)); } private String getIpAddress(ServerHttpRequest request) { String ipAddress = request.getHeaders().getFirst(HEADER_IP); if (ipAddress == null || ipAddress.isEmpty() || "unknown".equalsIgnoreCase(ipAddress)) { InetSocketAddress remoteAddress = request.getRemoteAddress(); if (remoteAddress != null) { ipAddress = remoteAddress.getAddress().getHostAddress(); } } return ipAddress; } }
注:根据不同url下的ip进行限流
效果#
分类:
Spring Boot
, Spring Cloud
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?