SpringCloud——Gateway(使用redis做限流、跨域)

限流

介绍

限流就是限制一段时间内,用户访问资源的次数,减轻服务器压力,限流大致分为 两种: 1. IP 限流(5s 内同一个 ip 访问超过 3 次,则限制不让访问,过一段时间才可继续访问)
2. 请求量限流(只要在一段时间内(窗口期),请求次数达到阀值,就直接拒绝后面来的访问了, 过一段时间才可以继续访问)(粒度可以细化到一个 api(url),一个服务)

限流模型

漏斗算法 ,令牌桶算法,窗口滑动算法 计数器算法,本次使用令牌桶算法
SpringCloud——Gateway(使用redis做限流、跨域)_第1张图片

Gateway结合redis实现请求量限流

pringCloudGateway已经内置了一个RequestRateLimiterGatewayFilterFactory,我们可以直接使用。注意不是全局过滤,是针对某一个gateway。
目前RequestRateLimiterGatewayFilterFactory的实现依赖于Redis,所以我们还要引入spring-boot-starter-data-redis-reactive。

1.添加依赖(在之前gateway项目基础上)

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

2.写配置类

package com.dcits.gatewayserver.config;

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

/**
 * 自定义请求限制
 */
@Configuration
public class RequestLimitConfig {
    //针对某一个接口ip /doLogin 每一个ip 10s只能访问3次
    @Bean
    public KeyResolver ipKeyResolver(){
        return exchange -> Mono.just(exchange.getRequest().getHeaders().getHost().getHostName());
    }
    //针对路径限制 /doLogin
    //api就是接口 一般将gateway叫api网关
    @Bean
    public KeyResolver apiKeyResolver(){
        return exchange -> Mono.just(exchange.getRequest().getPath().value());
    }
}

3.修改yml文件

spring:
  application:
    name: gateway-server
  cloud:
    gateway:
      enabled: true # 只要加了依赖默认开启
      routes:
        - id: login-service-route # 路由id,保持唯一
          uri: http://localhost:8081 # uri同一资源定位符
          predicates:
            - Path=/doLogin # 匹配规则,只要路径匹配上/doLogin,就往uri转发,并且将路径带上
          filters:
            - name: RequestRateLimiter # 过滤器名称
              args: # 过滤器参数
                key-resolver: '#{@ipKeyResolver}' # 通过spel表达式取IOC容器中Bean的值
                redis-rate-limiter.replenishRate: 1 # 生成令牌的速度
                redis-rate-limiter.burstCapacity: 3 # 桶容量

4.启动测试

此时启动会报错找到两个Bean
在这里插入图片描述解决:
在配置类中加@Primary注解

@Configuration
public class RequestLimitConfig {
    //针对某一个接口ip /doLogin 每一个ip 10s只能访问3次
    @Bean
    @Primary
    public KeyResolver ipKeyResolver(){
        return exchange -> Mono.just(exchange.getRequest().getHeaders().getHost().getHostName());
    }
    //针对路径限制 /doLogin
    //api就是接口 一般将gateway叫api网关
    @Bean
    public KeyResolver apiKeyResolver(){
        return exchange -> Mono.just(exchange.getRequest().getPath().value());
    }
}

可以在postman中测试,但是较慢,也可以在浏览器中狂按F5
正常:
SpringCloud——Gateway(使用redis做限流、跨域)_第2张图片
狂按F5被限流:

SpringCloud——Gateway(使用redis做限流、跨域)_第3张图片
可以看到是按照ip进行限制
在这里插入图片描述

换成API限流进行测试

修改ym文件:

spring:
  application:
    name: gateway-server
  cloud:
    gateway:
      enabled: true # 只要加了依赖默认开启
      routes:
        - id: login-service-route # 路由id,保持唯一
          uri: http://localhost:8081 # uri同一资源定位符
          predicates:
            - Path=/doLogin # 匹配规则,只要路径匹配上/doLogin,就往uri转发,并且将路径带上
          filters:
            - name: RequestRateLimiter # 过滤器名称
              args: # 过滤器参数
                key-resolver: '#{@apiKeyResolver}' # 通过spel表达式取IOC容器中Bean的值
                redis-rate-limiter.replenishRate: 1 # 生成令牌的速度
                redis-rate-limiter.burstCapacity: 3 # 桶容量

可以看到按照路径限制
在这里插入图片描述

Gateway跨域

可以克服Ajax只能同源访问

1.在代码中添加@CrossOrigin

SpringCloud——Gateway(使用redis做限流、跨域)_第4张图片

2.写成配置文件

package com.dcits.gatewayserver.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.reactive.CorsWebFilter;
import org.springframework.web.cors.reactive.UrlBasedCorsConfigurationSource;
import org.springframework.web.util.pattern.PathPatternParser;

@Configuration 
public class CorsConfig { 
    @Bean
    public CorsWebFilter corsFilter() { 
        CorsConfiguration config = new CorsConfiguration(); 
        config.addAllowedMethod("*"); 
        config.addAllowedOrigin("*"); 
        config.addAllowedHeader("*"); 
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(new PathPatternParser()); 
        source.registerCorsConfiguration("/**", config); return new CorsWebFilter(source); 
    } 
}

3.yml进行配置

spring:
  application:
    name: gateway-server
  cloud:
    gateway:
      globalcors:
        corsConfigurations:
          '[/**]': #针对哪些路径
            allowCredentials: true # 这个是可以携带 cookie
            allowedHeaders: '*'
            allowedMethods: '*'
            allowedOrigins: '*'

你可能感兴趣的:(redis,spring,cloud,gateway)