Spring Cloud:Gateway基礎知識


簡介

SpringCloud Gateway是SpringCloud的一個全新項目,基於Spring5+springboot2+project Reactor等技術開發的網關,它旨在為微服務架構提供一中簡單有效的統一的Api路由管理方式,且基於Filter鏈的方式提供了網關基本的功能,如安全,監控,指標,限流。
Spring Cloud Gateway使用的webflux中的reactor-netty響應式編程組件,底層使用了Netty通訊框架。
GateWay具有如下特性:

  • 基於Spring5+springboot2+project Reactor等技術構建。
  • 可以對路由指定Predicate(斷言)和filter(過濾器)。
  • 集成Hystrix的斷路器功能。
  • 集成SpringCloud服務發現功能。
  • 易於編寫的Predicate(斷言)和filter(過濾器);
  • 請求限流功能。
  • 支持路徑重寫。

三大核心概念

路由(Route)是構建網關的基本模塊,它由ID,目標URI,一系列斷言和過濾器組成,如果斷言為true則匹配該路由。
斷言(Predicate),開發人員可以匹配HTTP請求中的所有內容,例如請求頭或請求參數,如果請求與斷言相匹配則進行路由
過濾(Filter),指的是Spring框架中的GatewayFilter的實例,使用過濾器,可以在請求被路由前或者后對請求進行修改
官網截圖:

核心邏輯:路由轉發+執行過濾器鏈

Gateway環境搭建

yml配置方式

pom依賴:需要移除springboot的web場景啟動器,否則會報錯,無法啟動

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>

配置文件yml,在配置文件中配置了網關

server:
  port: 9527

spring:
  application:
    name: cloud-gateway
  cloud:
    gateway:
      routes:
        - id:  payment_routh
          uri: http://localhost:8001
          predicates:
            - Path=/payment/get/**
        - id:  payment_routh2
          uri: http://localhost:8001
          predicates:
            - Path=/payment/create

eureka:
  client:
    #是否將自己注冊到Eureka Server 默認為true
    register-with-eureka: true
    #是否從EurekaServer抓取已有的注冊信息,默認為true,單節點無所謂,集群必須設置true才能配合ribbon做負載均衡
    fetch-registry: true
    service-url:
      #設置eureka server交互的地址查詢服務和注冊服務都需要依賴這個地址
      defaultZone: http://localhost:7001/eureka
  instance:
    hostname: cloud-gateway-service

然后我們通過9527端口就可以訪問服務了:

編碼方式配置

新寫一個Gateway配置類:

@Configuration
public class GatewayConfig {

    @Bean
    public RouteLocator customRouteLocator(RouteLocatorBuilder routeLocatorBuilder){
        RouteLocatorBuilder.Builder routes = routeLocatorBuilder.routes();
        routes.route("path_route_wj",r->{
            //意思是訪問localhost:9527/guonei,將會轉發到http://news.baidu.com/guonei
                    return r.path("/guonei").uri("http://news.baidu.com/guonei");
        }).build();
        return routes.build();
    }
}

我們在瀏覽器輸入localhost:9527/guonei並訪問,觀察效果:

Gateway實現動態路由

yml配置
需要注意的是:uri的協議為lb,表示啟用Gateway的負載均衡功能.
lb://serverName是Spring cloud Gateway在微服務中自動為我們創建的負載均衡uri

spring:
  application:
    name: cloud-gateway
  cloud:
    gateway:
      routes:
        - id:  payment_routh
          #uri: http://localhost:8001
          uri: lb://CLOUD-PAYMENT-SERVICE
          predicates:
            - Path=/payment/get/**
        - id:  payment_routh2
          #uri: http://localhost:8001
          uri: lb://CLOUD-PAYMENT-SERVICE
          predicates:
            - Path=/payment/create
      discovery:
        locator:
          #開啟從注冊中心動態創建路由的功能,利用微服務名進行路由
          enabled: true

常用的斷言

當我們啟動Gateway服務時,發現控制台打印了一串Predicate

官方文檔有詳細說明:https://docs.spring.io/spring-cloud-gateway/docs/2.2.5.RELEASE/reference/html/#gateway-request-predicates-factories
這里不做過多介紹。

filter

filter分為兩種,一個是GatewayFilter,一種是GlobalFilter。

GatewayFilter

沒啥好說的,官網寫的很清楚。https://docs.spring.io/spring-cloud-gateway/docs/2.2.5.RELEASE/reference/html/#gatewayfilter-factories
舉例:

spring:
  application:
    name: cloud-gateway
  cloud:
    gateway:
      routes:
        - id:  payment_routh
          #uri: http://localhost:8001
          uri: lb://CLOUD-PAYMENT-SERVICE
          predicates:
            - Path=/payment/get/**
            #- After=2020-09-06T21:57:48.289+08:00[Asia/Shanghai]
          filters:
            #過濾器工廠會在匹配的請求頭上加上一對請求頭,名稱為X-Request-red值是blue
            - AddRequestHeader=X-Request-red, blue

自定義全局GlobalFilter:

需要實現兩個接口,GlobalFilter和Ordered。

@Slf4j
@Component
public class MyGlobalFilter implements GlobalFilter, Ordered {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        String name = exchange.getRequest().getQueryParams().getFirst("name");
        if(StringUtils.isBlank(name)){
            log.info("非法用戶");
            exchange.getResponse().setStatusCode(HttpStatus.BAD_REQUEST);
            return exchange.getResponse().setComplete();
        }
        return chain.filter(exchange);
    }

    @Override
    public int getOrder() {
        return 0;
    }
}

運行效果:


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM