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

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