• Spring Cloud Gateway实现API访问频率限制


    微服务架构中,API网关扮演着至关重要的角色,它不仅负责路由请求,还能提供诸如安全性、监控和限流等功能。Spring Cloud Gateway作为Spring Cloud生态系统中的一员,提供了强大的路由和过滤功能。本文将详细介绍如何使用Spring Cloud Gateway的全局过滤器(Global Filters)或特定路由的过滤器(Gateway Filters)来实现对外部接口的访问频率限制。

    一、为什么需要访问频率限制?

    访问频率限制(Rate Limiting)是保护后端服务免受恶意或异常流量攻击的重要手段。通过限制客户端在一定时间窗口内的请求次数,可以有效防止服务过载,保障系统的稳定性和可用性。

    二、使用全局过滤器实现访问频率限制

    全局过滤器适用于对所有路由进行统一的访问频率限制。以下是实现这一功能的详细步骤和示例代码。

    步骤:

    1. 创建一个自定义的全局过滤器: 实现GlobalFilter接口,并在过滤器中实现访问频率限制逻辑。

    2. 配置过滤器: 将自定义的全局过滤器注册到Spring Cloud Gateway中。

    示例代码:

        import org.springframework.cloud.gateway.filter.GatewayFilterChain;
        import org.springframework.cloud.gateway.filter.GlobalFilter;
        import org.springframework.core.Ordered;
        import org.springframework.http.HttpStatus;
        import org.springframework.stereotype.Component;
        import org.springframework.web.server.ServerWebExchange;
        import reactor.core.publisher.Mono;
        
        import java.util.concurrent.ConcurrentHashMap;
        import java.util.concurrent.atomic.AtomicInteger;
        
        @Component
        public class RateLimitGlobalFilter implements GlobalFilter, Ordered {
        
            private final ConcurrentHashMap requestCounts = new ConcurrentHashMap<>();
        
            @Override
            public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) {
                String ipAddress = exchange.getRequest().getRemoteAddress().getAddress().getHostAddress();
                AtomicInteger count = requestCounts.computeIfAbsent(ipAddress, k -> new AtomicInteger(0));
        
                if (count.incrementAndGet() > 10) { // 每秒最多10次请求
                    exchange.getResponse().setStatusCode(HttpStatus.TOO_MANY_REQUESTS);
                    return exchange.getResponse().setComplete();
                }
        
                return chain.filter(exchange).then(Mono.fromRunnable(() -> {
                    if (count.decrementAndGet() == 0) {
                        requestCounts.remove(ipAddress);
                    }
                }));
            }
        
            @Override
            public int getOrder() {
                return Ordered.LOWEST_PRECEDENCE;
            }
        }
        
    

    三、使用特定路由的过滤器实现访问频率限制

    特定路由的过滤器适用于对特定路由进行访问频率限制。

    步骤:

    1. 创建一个自定义的GatewayFilter工厂: 实现GatewayFilterFactory接口,并在工厂中实现访问频率限制逻辑。

    2. 配置路由过滤器: 在路由配置中使用自定义的GatewayFilter工厂。

    示例代码:

        import org.springframework.cloud.gateway.filter.GatewayFilter;
        import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
        import org.springframework.http.HttpStatus;
        import org.springframework.stereotype.Component;
        import reactor.core.publisher.Mono;
        
        import java.util.concurrent.ConcurrentHashMap;
        import java.util.concurrent.atomic.AtomicInteger;
        
        @Component
        public class RateLimitGatewayFilterFactory extends AbstractGatewayFilterFactory {
        
            private final ConcurrentHashMap requestCounts = new ConcurrentHashMap<>();
        
            public RateLimitGatewayFilterFactory() {
                super(Config.class);
            }
        
            @Override
            public GatewayFilter apply(Config config) {
                return (exchange, chain) -> {
                    String routeId = exchange.getRequest().getPath().toString();
                    AtomicInteger count = requestCounts.computeIfAbsent(routeId, k -> new AtomicInteger(0));
        
                    if (count.incrementAndGet() > config.getMaxRequestsPerSecond()) { // 每秒最多config.getMaxRequestsPerSecond()次请求
                        exchange.getResponse().setStatusCode(HttpStatus.TOO_MANY_REQUESTS);
                        return exchange.getResponse().setComplete();
                    }
        
                    return chain.filter(exchange).then(Mono.fromRunnable(() -> {
                        if (count.decrementAndGet() == 0) {
                            requestCounts.remove(routeId);
                        }
                    }));
                };
            }
        
            public static class Config {
                private int maxRequestsPerSecond;
        
                public int getMaxRequestsPerSecond() {
                    return maxRequestsPerSecond;
                }
        
                public void setMaxRequestsPerSecond(int maxRequestsPerSecond) {
                    this.maxRequestsPerSecond = maxRequestsPerSecond;
                }
            }
        }
    

    application.yml中配置路由过滤器:

          cloud:
            gateway:
              routes:
                - id: rate_limited_route
                  uri: http://example.com
                  predicates:
                    - Path=/rate_limited_path
                  filters:
                    - name: RateLimit
                      args:
                        maxRequestsPerSecond: 10
    

    四、总结

    通过以上步骤和示例代码,可以在Spring Cloud Gateway中实现对外部接口的访问频率限制。根据具体需求选择使用全局过滤器或特定路由的过滤器,可以有效保护后端服务免受异常流量攻击,提升系统的稳定性和可用性。

  • 相关阅读:
    分布式.CAP理论
    第六章:java ==与equals
    Kratos战神微服务框架(二)
    【C++进阶之路】C++11(上)
    Aspose.Words使用教程之如何重命名合并字段
    rar格式转换zip格式,如何做?
    vulnhub刷题记录(Hack Me Please: 1)
    销售运营管理
    OceanBase 金融项目优化案例
    [阅读笔记18][CITING]LARGE LANGUAGE MODELS CREATE CURRICULUM FOR INSTRUCTION TUNING
  • 原文地址:https://blog.csdn.net/weixin_42564451/article/details/140959207