SpringCloud网关Gateway入门介绍

SpringCloud网关Gateway入门介绍

注意

  • Spring Cloud Gateway构建在SpringBoot 2.0、Spring WebFlux和Project Reactor上。因此,许多熟悉的同步库(例如Spring Data and Spring Security)和模式在使用Spring Cloud网关时可能不适用
  • SpringCloudGateway需要SpringBoot和SpringWebFlux提供的netty运行时。它不能在传统的servlet容器中工作,也不能作为war而构建。
  • 截止今天为止(即Greenwich.SR1版本),gateway和web不能共存,也就是org.springframework.boot:spring-boot-starter-web这个库要移除掉

综述

  • gateway主要有三个概念:Route(路由),Predicate(谓词),Filter(过滤器)
    在这里插入图片描述

  • 以上过滤链的过程可以用以下例子说明(注意日志的打印顺序):

    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.cloud.gateway.filter.GlobalFilter;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.core.annotation.Order;
    import reactor.core.publisher.Mono;
    
    /**
     * 全局过滤器演示,order越低优先级越高
     * 最终输出日志为
     * first pre filter
     * second pre filter
     * third pre filter
     * first post filter
     * second post filter
     * third post filter
     */
    @Configuration
    public class ExampleConfiguration {
    	private Logger log = LoggerFactory.getLogger(ExampleConfiguration.class);
    
    	@Bean
    	@Order(-1)
    	public GlobalFilter a() {
    		return (exchange, chain) -> {
    			log.info("first pre filter");
    			return chain.filter(exchange).then(Mono.fromRunnable(() -> {
    				log.info("third post filter");
    			}));
    		};
    	}
    
    	@Bean
    	@Order(0)
    	public GlobalFilter b() {
    		return (exchange, chain) -> {
    			log.info("second pre filter");
    			return chain.filter(exchange).then(Mono.fromRunnable(() -> {
    				log.info("second post filter");
    			}));
    		};
    	}
    
    	@Bean
    	@Order(1)
    	public GlobalFilter c() {
    		return (exchange, chain) -> {
    			log.info("third pre filter");
    			return chain.filter(exchange).then(Mono.fromRunnable(() -> {
    				log.info("first post filter");
    			}));
    		};
    	}
    }
    
  • 其中predicates主要有以下几种:
    After 可以指定在某个时间之后的请求
    Before 可以指定在某个时间之前的请求
    Between 可以指定在某个时间段之内的请求
    Cookie 可以指定cookie
    Header 可以指定请求头
    Host 可以指定请求的host
    Method 可以指定请求的方式
    Path 可以指定某个路径
    Query 可以指定带有某个参数
    RemoteAddr 可以指定某个远程访问地址

  • 其中filters主要有以下几种:
    AddRequestHeader
    AddRequestParameter
    AddResponseHeader
    DedupeResponseHeader
    PrefixPath

server:
  port: 4120
#  servlet:
#    context-path:  
spring:
  cloud:
    gateway:
      enabled: true # if you do not want the gateway to be enabled ,set false
      routes:
        - id: id-a
          uri: https://www.baidu.com #支持lb 如lb://service
          predicates:
            - Path= /a/**
          filters:
            - StripPrefix= 1 #看名字就知道,这是为了跳过前缀,否则就会前缀也加在路径上,看个人需求
        - id: id-b
          uri: https://hao.360.com
          predicates:
            - Path= /b/**
          filters:
            - StripPrefix= 1
  • 如果context-path不为空,那依然不影响,仍然可以通过 http://localhost:4120/a 访问到 https://www.baidu.com ,这里的context-path不会起作用
  • 上面的StripPrefix这个意思就是跳过前缀,值的意思是跳过几个,举个栗子:假如用户访问 http://localhost:4120/a/b/c ,那么实际访问的是:
    • https://www.baidu.com/b/c (StripPrefix=1)
    • https://www.baidu.com/a/b/c (StripPrefix=0)
    • https://www.baidu.com/c (StripPrefix=2)
  • 这下明白了吧
  • 当然如果想在代码里配置,这也是支持的,上面的配置等价于下面的代码
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;


@Configuration
public class GateWayConfig {
    @Bean
    public RouteLocator routeLocator(RouteLocatorBuilder builder) {
        return builder.routes()
                .route("id-a", r -> r.path("/a/**").filters(f -> f.stripPrefix(1)).uri("https://www.baidu.com"))
                .route("id-b", r -> r.path("/b/c/**").filters(f -> f.stripPrefix(2)).uri("https://hao.360.com"))
                .build();
    }


}

限流

  • 官方说明: https://cloud.spring.io/spring-cloud-gateway/spring-cloud-gateway.html#_requestratelimiter_gatewayfilter_factory

  • 很多时候我们需要对接口进行限流,或者对恶意访问进行防范,这时就需要限制同一ip或同一接口的访问次数

  • 由于限流的实现依赖于redis,因此要引入

    implementation 'org.springframework.boot:spring-boot-starter-data-redis-reactive'
    
  • 当然还得有个redis服务(至于redis服务怎么弄我就不讲了),有了redis服务,在yml中配置一下

    spring:
      redis:
        host: 192.168.25.105
        port: 6379
    
  • 通过以上操作基本环境就搭建好了,下面配置一下要限流的路由

    server:
      port: 4120
    spring:
      cloud:
        gateway:
          enabled: true # if you do not want the gateway to be enabled ,set false
          routes:
            - id: id-c
              uri: http://www.baidu.com
              predicates:
                - Path= /d/**
              filters:
                - StripPrefix= 1
                - name: RequestRateLimiter #名称是固定的,不能修改
                  args:
                    redis-rate-limiter.replenishRate: 1 #允许用户每秒处理多少个请求
                    redis-rate-limiter.burstCapacity: 5 #令牌桶的容量,允许在一秒钟内完成的最大请求数
                    key-resolver: "#{@userKeyResolver}" #跟提供bean类的方法名一致,指定具体要限流的是接口还是ip等
      redis:
        host: 192.168.25.105
        port: 6379
    
    import org.springframework.cloud.gateway.filter.ratelimit.KeyResolver;
    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 reactor.core.publisher.Mono;
    
    
    @Configuration
    public class GateWayConfig {
       
        @Bean
        KeyResolver userKeyResolver() {
            return exchange -> Mono.just(exchange.getRequest().getPath().value());//接口限流
            // return exchange -> Mono.just(exchange.getRequest().getRemoteAddress().getHostName()); //ip限流
            //return exchange -> Mono.just(exchange.getRequest().getQueryParams().getFirst("user")); //用户限流,必须带有user参数才有效
        }
    
    
    }
    
  • 如上配置就实现了对接口的限流,访问接口 http://localhost:4120/d ,可以在redis服务中看到
    在这里插入图片描述

  • 表明限流已经在起作用了

代码示例

  • github-demo: https://github.com/huweijian5/oauth2-demo/tree/master/gateway

参考

Spring Cloud Gateway
https://cloud.spring.io/spring-cloud-gateway/spring-cloud-gateway.html
Spring Cloud Gateway 2.1.0 中文官网文档 - 云+社区 - 腾讯云
https://cloud.tencent.com/developer/article/1403887
SpringCloud Gateway的基本入门和注意点 - zzzgd_666的博客 - CSDN博客
https://blog.csdn.net/zzzgd_666/article/details/86095716
Spring Cloud Gateway 限流操作 - u010889990的专栏 - CSDN博客
https://blog.csdn.net/u010889990/article/details/81169328

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章