From 2d82571303c8425ea73f3c2ef7f8cadd03cc6ac0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=A8=8B=E5=BA=8F=E5=91=98=E5=B0=8F=E5=A2=A8?= <2291200076@qq.com> Date: Mon, 24 Apr 2023 19:01:57 +0800 Subject: [PATCH] =?UTF-8?q?Gateway=E6=B7=BB=E5=8A=A0=E9=80=9A=E8=BF=87IP?= =?UTF-8?q?=E9=99=90=E6=B5=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../RateLimitByIpGatewayFilterFactory.java | 79 +++++++++++++++++++ .../src/main/resources/application.yml | 18 +++++ 2 files changed, 97 insertions(+) create mode 100644 backend/microservice-gateway/src/main/java/com/cxyxiaomo/epp/gateway/Factory/RateLimitByIpGatewayFilterFactory.java diff --git a/backend/microservice-gateway/src/main/java/com/cxyxiaomo/epp/gateway/Factory/RateLimitByIpGatewayFilterFactory.java b/backend/microservice-gateway/src/main/java/com/cxyxiaomo/epp/gateway/Factory/RateLimitByIpGatewayFilterFactory.java new file mode 100644 index 0000000..b15892c --- /dev/null +++ b/backend/microservice-gateway/src/main/java/com/cxyxiaomo/epp/gateway/Factory/RateLimitByIpGatewayFilterFactory.java @@ -0,0 +1,79 @@ +package com.cxyxiaomo.epp.gateway.Factory; + +import com.google.common.util.concurrent.RateLimiter; +import org.springframework.cloud.gateway.filter.GatewayFilter; +import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory; +import org.springframework.http.HttpStatus; +import org.springframework.http.server.reactive.ServerHttpRequest; +import org.springframework.http.server.reactive.ServerHttpResponse; +import org.springframework.stereotype.Component; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +@Component +// 一个自定义的限流过滤器工厂 +public class RateLimitByIpGatewayFilterFactory extends AbstractGatewayFilterFactory { + + // 用于存储IP地址和对应的计数器 + private static final Map RATE_LIMITER_CACHE = new ConcurrentHashMap<>(); + + public RateLimitByIpGatewayFilterFactory() { + super(Config.class); + } + + @Override + public GatewayFilter apply(Config config) { + return (exchange, chain) -> { + // 获取请求的IP地址 + ServerHttpRequest request = exchange.getRequest(); + String ip = request.getRemoteAddress().getAddress().getHostAddress(); + + // 根据IP地址获取对应的限流器 + RateLimiter rateLimiter = RATE_LIMITER_CACHE.get(ip); + if (rateLimiter == null) { + // 如果不存在,则创建一个新的限流器,并放入缓存中 + rateLimiter = RateLimiter.create(config.getRate()); + RATE_LIMITER_CACHE.put(ip, rateLimiter); + } + + // 判断请求是否被限流 + if (rateLimiter.tryAcquire(config.getPermits())) { + // 如果没有被限流,则放行 + return chain.filter(exchange); + } else { + System.out.println("限流!ip: " + ip); + // 如果被限流,则返回429状态码(Too Many Requests) + ServerHttpResponse response = exchange.getResponse(); + response.setStatusCode(HttpStatus.TOO_MANY_REQUESTS); + return response.setComplete(); + } + }; + } + + // 配置类,用于接收配置参数 + public static class Config { + + // 每秒允许的请求数 + private double rate; + + // 每次请求需要的令牌数 + private int permits; + + public double getRate() { + return rate; + } + + public void setRate(double rate) { + this.rate = rate; + } + + public int getPermits() { + return permits; + } + + public void setPermits(int permits) { + this.permits = permits; + } + } +} diff --git a/backend/microservice-gateway/src/main/resources/application.yml b/backend/microservice-gateway/src/main/resources/application.yml index 7e547b3..a863048 100644 --- a/backend/microservice-gateway/src/main/resources/application.yml +++ b/backend/microservice-gateway/src/main/resources/application.yml @@ -40,20 +40,38 @@ spring: predicates: - Path=/user/** - Method=GET,POST + filters: # 路由过滤器,使用自定义的限流过滤器工厂 + - name: RateLimitByIp # 设置每秒允许5个请求,每次请求需要1个令牌 + args: + rate: 5.0 + permits: 1 + - id: access uri: lb://microservice-provider-access predicates: - Path=/access/** - Method=GET,POST + filters: # 路由过滤器,使用自定义的限流过滤器工厂 + - name: RateLimitByIp # 设置每秒允许5个请求,每次请求需要1个令牌 + args: + rate: 5.0 + permits: 1 + - id: access-websocket uri: lb:ws://microservice-provider-access predicates: - Path=/access/websocket/** + - id: shop uri: lb://microservice-provider-shop predicates: - Path=/shop/** - Method=GET,POST + filters: # 路由过滤器,使用自定义的限流过滤器工厂 + - name: RateLimitByIp # 设置每秒允许5个请求,每次请求需要1个令牌 + args: + rate: 5.0 + permits: 1 - id: test1 uri: lb://microservice-provider-test