前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Spring Cloud Gateway限流(一)

Spring Cloud Gateway限流(一)

原创
作者头像
堕落飞鸟
发布2023-04-11 09:56:23
7100
发布2023-04-11 09:56:23
举报
文章被收录于专栏:飞鸟的专栏飞鸟的专栏

Spring Cloud Gateway是一个基于Spring Boot的API网关,提供了统一的访问入口,可以通过网关层面实现诸如限流、熔断等功能,从而保护后端服务。在本篇文章中,我们将重点介绍Spring Cloud Gateway中的限流功能。

限流(Rate limiting)是一种保护服务免受过度使用或滥用的方法,它可以控制请求的数量和速率,以防止超出服务能力的范围。Spring Cloud Gateway提供了多种限流方式,包括基于Redis、基于令牌桶和基于漏桶算法等。

下面我们将详细介绍如何在Spring Cloud Gateway中实现限流。

基于Redis的限流

Redis是一种内存键值数据库,可以用来存储缓存、计数器等。在Spring Cloud Gateway中,我们可以使用Redis来实现限流功能。

步骤一:添加依赖

在pom.xml文件中添加如下依赖:

代码语言:javascript
复制
xmlCopy code<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

步骤二:配置Redis

在application.yml文件中添加Redis配置:

代码语言:javascript
复制
spring:
  redis:
    host: localhost
    port: 6379

步骤三:编写限流过滤器

我们需要编写一个限流过滤器来实现基于Redis的限流。代码如下:

代码语言:javascript
复制
public class RedisRateLimiterGatewayFilterFactory extends AbstractGatewayFilterFactory<RedisRateLimiterGatewayFilterFactory.Config> {

    private final RedisTemplate<String, String> redisTemplate;

    public RedisRateLimiterGatewayFilterFactory(RedisTemplate<String, String> redisTemplate) {
        super(Config.class);
        this.redisTemplate = redisTemplate;
    }

    @Override
    public GatewayFilter apply(Config config) {
        return (exchange, chain) -> {
            String key = exchange.getRequest().getHeaders().getFirst(config.getHeader());
            if (key == null) {
                throw new IllegalArgumentException("Header " + config.getHeader() + " not found");
            }
            String redisKey = config.getKeyResolver().apply(exchange);
            String permits = redisTemplate.opsForValue().get(redisKey);
            if (permits == null) {
                redisTemplate.opsForValue().set(redisKey, String.valueOf(config.getPermits()));
                redisTemplate.expire(redisKey, config.getDuration());
            } else {
                int remaining = Integer.parseInt(permits) - 1;
                if (remaining < 0) {
                    throw new RateLimiterException();
                }
                redisTemplate.opsForValue().set(redisKey, String.valueOf(remaining));
            }
            return chain.filter(exchange);
        };
    }

    public static class Config {
        private String header = "X-RateLimit-Header";
        private int permits = 10;
        private Duration duration = Duration.ofSeconds(1);
        private Function<ServerWebExchange, String> keyResolver = exchange -> exchange.getRequest().getPath().toString();

        public String getHeader() {
            return header;
        }

        public void setHeader(String header) {
            this.header = header;
        }

        public int getPermits() {
            return permits;
        }

        public void setPermits(int permits) {
            this.permits = permits;
        }

        public Duration getDuration() {
            return duration;
        }

        public void setDuration(Duration duration) {
            this.duration = duration;
        }

        public Function<ServerWebExchange, String> getKeyResolver() {
            return keyResolver;
        }

        public void setKeyResolver(Function<ServerWebExchange, String> keyResolver) {
            this.keyResolver = keyResolver;
        }
    }

    public static class RateLimiterException extends RuntimeException {
        public RateLimiterException() {
            super("Rate limit exceeded");
        }
    }
}

该过滤器的核心逻辑是:首先从请求头中获取一个标识符,然后使用这个标识符构造一个Redis键,使用Redis对这个键进行计数。如果当前计数小于等于允许的请求数量,则将计数减1,并继续执行后续过滤器和请求处理程序。否则,抛出一个限流异常。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 基于Redis的限流
    • 步骤一:添加依赖
      • 步骤二:配置Redis
        • 步骤三:编写限流过滤器
        相关产品与服务
        云数据库 Redis
        腾讯云数据库 Redis(TencentDB for Redis)是腾讯云打造的兼容 Redis 协议的缓存和存储服务。丰富的数据结构能帮助您完成不同类型的业务场景开发。支持主从热备,提供自动容灾切换、数据备份、故障迁移、实例监控、在线扩容、数据回档等全套的数据库服务。
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档