gataway 组件的健权、限流、过滤等功能分析(三十一)

gateway 处了除了网关和路由功能外 还有 健权、限流、过滤等功能,如图。

如图所示:现有断言、映射,而过滤功能在最后;

一、过滤器分为全局的和局部的,官网有简介:

 1、

spring:
  cloud:
    gateway:
      routes:
      - id: query_route
        uri: http://localhost:8001
        predicates:
        - Query=green

2、全局过滤器的核心代码(8001服务中 gateway 服务):

import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.http.HttpCookie;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.util.MultiValueMap;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

//实现了全局过滤器的 filter 接口,做服务过滤转发
public class ShadowGlobaFilter implements GlobalFilter , Ordered {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest();
        MultiValueMap<String, HttpCookie> cookies = request.getCookies();

        for (String s : cookies.keySet()) {
            if(s.equals("x")){
                System.out.println("----------------------");
                return chain.filter(exchange);
            }
        }
        ServerHttpResponse response = exchange.getResponse();
        response.setStatusCode(HttpStatus.UNAUTHORIZED);
        return response.setComplete();
    }

    //过滤器的执行顺序,值越小,执行优先级越高
    @Override
    public int getOrder() {
        return 0;
    }
}

如果8000是gateway 服务,核心配置如下:首先保证所有请求都能进来;如果非gateway 服务,则无需这样配置。

server:
  port: 8001
spring:
  application:
    name: register-gateway-8001

  cloud:
    gateway:
      #gateway的服务发现
      discovery:
        locator:
          # 根据注册中心自动注册路由,默认false 重启生效
          enabled: true
          #开始小写转换,重启生效
          lowerCaseServiceId: true
      # 跨域配置
      globalcors:
        corsConfigurations:
          '[/**]':
            allowedHeaders: "*"
            allowedOrigins: "*"
            allowedMethods:
              - GET
              - POST
              - DELETE
              - PUT
              - OPTION

 

3、访问url:http://localhost:8000/?green=c  ,如果你Cookie 有是 x 的,则通过,否则返回错误;

4、局部过滤器配置:

     - id: test_query_route
       uri: lb://register-server
       predicates:
       - Query=shadow
       filters:
     # 下面类 AvGatewayFilterFactory 中 的AV 对应 此配置 AV (AvGatewayFilterFactory中GatewayFilterFactory之前的部分)
       - Av=true

核心代码 必须继承 AbstractGatewayFilterFactory<AvGatewayFilterFactory.Config> 类:


import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.http.HttpCookie;
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 org.springframework.util.MultiValueMap;

import java.util.Arrays;
import java.util.List;

@Component
public class AvGatewayFilterFactory extends AbstractGatewayFilterFactory<AvGatewayFilterFactory.Config> {

    public AvGatewayFilterFactory(){
        super(Config.class);
    }

    @Override
    public GatewayFilter apply(Config config) {
        return (exchange, chain) -> {
            if(!config.enable){
               return chain.filter(exchange);
            }
            /**
             * validate 验证
             */
            ServerHttpRequest request = exchange.getRequest();
            MultiValueMap<String, HttpCookie> cookies = request.getCookies();

            for (String s : cookies.keySet()) {
                if(s.equals("e")){
                    System.out.println("--------AbstractGatewayFilterFactory--------------");
                    return chain.filter(exchange);
                }
            }
            ServerHttpResponse response = exchange.getResponse();
            response.setStatusCode(HttpStatus.UNAUTHORIZED);
            return response.setComplete();
        };
    }

    @Override
    public List<String> shortcutFieldOrder() {
        //对应Config 类当中的变量
        return Arrays.asList("enable");
    }

    public static class  Config{
        private boolean enable;

        public boolean isEnable() {
            return enable;
        }

        public void setEnable(boolean enable) {
            System.out.println(enable);
            this.enable = enable;
        }
    }
}

然后访问思路和全局配置一样,结果ok;

二,原生限流 redis 集成

官方文档在这里:

1、引入jar

<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-reactive</artifactId>
        </dependency>

2、核心配置如下:

server:
  port: 8000
spring:
  application:
    name: register-gateway-8000

  redis:
    database: 3
    host: 10.130.16.26
    password: redispwd
    port: 289
    jedis:
      pool:
        max-active: 500
        max-wait: -1
        max-idle: 8
        min-idle: 0
    timeout: 0

cloud:
    gateway:
      routes:
        - id: requestratelimiter_route
          uri: https://www.baidu.com
          order: 10000
          predicates:
#            - Query=green
#            - Path=/uas/{segment}
            - Before=2021-05-07T19:52:47.789+08:00
#            - Path=/admin/**
          filters:
            - name: RequestRateLimiter
              args:
                redis-rate-limiter.replenishRate: 1  # 令牌桶的容积
                redis-rate-limiter.burstCapacity: 1  # 流速 每秒
                key-resolver: "#{@userKeyResolver}" #SPEL表达式去的对应的bean
            - StripPrefix=1  #表示二级url路径转发

3、核心代码:


@EnableDiscoveryClient
@SpringBootApplication
@RestController
public class Application_8000 {
    public static void main(String[] args) {
        SpringApplication.run(Application_8000.class,args);
    }

    @Bean
   public KeyResolver userKeyResolver(){
            return new KeyResolver() {
            @Override
            public Mono<String> resolve(ServerWebExchange exchange) {
                HttpCookie httpCookie=null;
                ServerHttpRequest request = exchange.getRequest();
                MultiValueMap<String, HttpCookie> cookies = request.getCookies();
                for (Map.Entry<String, List<HttpCookie>> stringListEntry : cookies.entrySet()) {
                    if(stringListEntry.getKey().equals("c")){
                         httpCookie = stringListEntry.getValue().get(0);
                    }
                }
                return Mono.just(httpCookie.getValue());
            }
        };
    }
}

 4、存session的代码:

@RestController
public class LoginController {

   //先登录此接口 存session ,
    @GetMapping("/validate")
    public void validate(ServerHttpResponse response){
        System.out.println("OK!!!!!");
        response.addCookie(ResponseCookie.from("c","nandao").build()
        );
    }
}

5、启动后先访问:http://localhost:8000/validate      成功后首次访问 http://localhost:8000  进入百度页面:

6、如果点击刷新非常快(一秒内多次访问),则会进入错误页面:

 

7、到此说明限流成功。 

8、也可以多维度限流设置:

/**
* 自定义限流标志的key,多个维度可以从这里入手
* exchange对象中获取服务ID、请求信息,用户信息等
*/
@Bean
KeyResolver remoteAddrKeyResolver() {
    return exchange -> Mono.just(exchange.getRequest().getRemoteAddress().getHostName());
}

到此gateway 路由功能分析完毕,以后有机会我们共同学习其源码,敬请期待!

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

寅灯

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值