欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

基于gateway网关实现限流

程序员文章站 2022-03-03 09:41:23
前言在前面的限流方案介绍中,我们谈到了网关在微服务体系架构中的重要作用,网关不经具备大家熟知的动态路由,请求拦截等功能外,还可以基于网关实现分布式环境下的限流,下面我们以gatway为例,用代码进行实现一下实现原理所有经过网关代理的请求会被网关进行拦截基于拦截到的请求,可以以IP、请求参数、方法名等作为限流的维度既然是限流,必然存在一个存储请求信息的地方,我们这里选用redis,简单高效,只需配置一定的策略即可代码实现逻辑1、添加pom依赖...

前言

在前面的限流方案介绍中,我们谈到了网关在微服务体系架构中的重要作用,网关不经具备大家熟知的动态路由,请求拦截等功能外,还可以基于网关实现分布式环境下的限流,下面我们以gatway为例,用代码进行实现一下

实现原理

  • 所有经过网关代理的请求会被网关进行拦截
  • 基于拦截到的请求,可以以IP、请求参数、方法名等作为限流的维度
  • 既然是限流,必然存在一个存储请求信息的地方,我们这里选用redis,简单高效,只需配置一定的策略即可

代码实现逻辑

1、添加pom依赖

		<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>

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

这里只引入了关键的依赖,简单说明下,这里沿用之前的使用gateway整合时的框架demo进行演示,注册中心使用eureka,整个环境包括3个工程,eureka-server,gateway工程和一个被gateway代理的微服务模块

2、限流策略配置类

import org.springframework.cloud.gateway.filter.ratelimit.KeyResolver;
import org.springframework.cloud.gateway.filter.ratelimit.RedisRateLimiter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import reactor.core.publisher.Mono;

@Configuration
public class HostAddrKeyResolver {

    //限流策略数据存储在redis中
    @Bean("redisRateLimiter")
    @Primary
    public RedisRateLimiter redisRateLimiter(){
        return new RedisRateLimiter(1,1);
    }

    //基于IP地址进行限流
    @Bean("remoteAddrKeyResolver")
    @Primary
    public KeyResolver remoteAddrKeyResolver() {
        return exchange -> Mono.just(exchange.getRequest().getRemoteAddress().getAddress().getHostAddress());
    }

    //基于hostName地址进行限流
    @Bean("remoteHostNameKeyResolver")
    @Primary
    public KeyResolver remoteHostNameKeyResolver() {
        return exchange -> Mono.just(exchange.getRequest().getRemoteAddress().getAddress().getHostName());
    }

    //根据请求参数进行限流
    @Bean("remoteUserKeyResolver")
    @Primary
    public KeyResolver remoteUserKeyResolver() {
        return exchange -> Mono.just(exchange.getRequest().getQueryParams().getFirst("user"));
    }

}

使用gateway进行限流,其配置主要包括2部分,一个是配置KeyResolver,可以将这个KeyResolver理解为不同类型的限流策略配置,比如是针对IP进行限流,还是基于请求参数进行限流,这样的话你就需要在spring容器中提供不同的bean

第二是RateLimiter,即限流算法的配置,前面我们聊到了常用 的请求算法,像令牌桶算法,比如你允许每秒有多少个请求通过,某一时刻桶中有多少个请求等,参照上面的配置类

3、限流配置类

这里我们采用了配置的方式,替代了在yml里面进行配置,在之前我们有过介绍,最后只需要将上面的限流策略配置类配置到filter里面即可生效


import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.ratelimit.KeyResolver;
import org.springframework.cloud.gateway.filter.ratelimit.RateLimiter;
import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpStatus;

@Configuration
public class GatewayConfiguration {

    //@Autowired
    //private AuthFilter authFilter;

    @Autowired
    private KeyResolver remoteAddrKeyResolver;

    @Autowired
    private RateLimiter redisRateLimiter;

    @Bean
    @Order
    public RouteLocator routeLocator(RouteLocatorBuilder builder) {
        return builder.routes()
                //多个路由规则就添加多个route
                .route(r ->
                        r.path("/pay/payment/**")
                                .filters(f ->
                                        f.stripPrefix(1).
                                        //添加自定义的filter
                                        requestRateLimiter(c -> {
                                            c.setKeyResolver(remoteAddrKeyResolver);
                                            c.setRateLimiter(redisRateLimiter);
                                            c.setStatusCode(HttpStatus.BAD_GATEWAY);
                                        })
                                )
                                .uri("lb://cloud-payment-service")
                ).build();
    }

}

4、效果测试

分别启动相关的微服务模块,浏览器输入:
http://localhost:8721/pay/payment/get/11

基于gateway网关实现限流
每秒一次,可以正常访问得到响应结果,如果我们快速刷新页面,
基于gateway网关实现限流

从这里可以看到被限流了

当然我们在使用的时候,针对同一个路由,可以组合多种限流策略,有兴趣的同学可以继续研究,本篇到此结束,最后感谢观看!

本文地址:https://blog.csdn.net/zhangcongyi420/article/details/108874233