資安

Gateway新一代網關

Gateway新一代網關

zuul路由網關

zuul核心人員走了兩個,zuul2的研發過久,spring公司等不及,自己研發的Gateway網關。


簡介

Cloud全家桶有個狠重要的組件就是網關,在1.x版本中都是採用Zuul網關;但是在2.x版本中,zuul的升級一致跳票,SpringCloud最後自己研發了一個網關替代Zuul, 那就是SpringCloud Gateway

sada

  • Gateway是在Spring生態之上構建的API網關服務,基於Spring 5,Spring Boot 2和Project Reactor 等技術。
  • Gateway旨在提供一種簡單而有效 等方式來對API 進行路由,以及提供一些強大對過濾器,例如:熔斷、限流、重試等
  • Gateway 作為SpringCloud 等目標提供統一等路由方式且基於Filter 鏈的方式提供了網關基本的功能,例如:安全,監控。限流
  • SpringCloud Gateway 使用的Webflux中的 reactor-netty 響應式的編程,底層使用了Netty通訊框架
  • 在這裡插入圖片描述

在這裡插入圖片描述
在這裡插入圖片描述

因為Zuul1.0 進入了維護階段,而且Gateway 是SpringCloud 團隊開發,比Zuul更加的便捷

Gateway 是基於異步非阻塞模型上進行開發的,性能方面不需要擔心

在這裡插入圖片描述


SpringCloud Gateway 與 Zuul 的區別

在這裡插入圖片描述

三大核心概念

Route (路由)
  • 路由是構建網關的基本模塊,它由ID,目標URL,一系列的斷言和過濾器組成,如果斷言為true則匹配該路由
Predicate (斷言)
  • 參考的是Java8的java.util.function.predicate
  • 開發人員可以匹配HTTP請求中的所有內容(例如請求頭或請求參數),如果請求與斷言相匹配則進行路由
Filter (過濾)
  • 指的是Spring框架中的GatewayFilter 的實例,使用過濾器,可以在請求被路由前或者之後請求進行修改。
總體

在這裡插入圖片描述

  • web請求,通過一些匹配條件,定位到真正的服務節點。並在這個妝發過程的前後,進行一些精細化控制。
  • predicate就是我們匹配條件;而filter ,就可以理解為一個無所不能的攔截器,有了這兩個元素,在加上目標uri,就可以實現一個具體的路由了

Gateway工作流程

(官網總結)

在這裡插入圖片描述
在這裡插入圖片描述
在這裡插入圖片描述

Demo

  1. 新建模塊cloud-gateway-gateway9527
  2. 引入pom
<dependencies>
    <!--gateway-->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-gateway</artifactId>
    </dependency>
    <!-- 引用自己定義的api通用包,可以使用Payment支付Entity -->
    <dependency>
        <groupId>com.angenin.springcloud</groupId>
        <artifactId>cloud-api-commons</artifactId>
        <version>${project.version}</version>
    </dependency>
    <!--eureka client(通過微服務名實現動態路由)-->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
    </dependency>
    <!--熱部署-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-devtools</artifactId>
        <scope>runtime</scope>
        <optional>true</optional>
    </dependency>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
</dependencies>
  1. yml文件
server:
  port: 9527

spring:
  application:
    name: cloud-gateway
  cloud:
    gateway:
      routes:
        - id: payment_route # 路由的id,沒有規定規則但要求唯一,建議配合服務名
          uri: http://localhost:8001
          predicates:
            - Path=/payment/get/** # 斷言,路徑相匹配的進行路由
        - id: payment_route2
          uri: http://localhost:8001
          predicates:
             Path=/payment/lb/** #斷言,路徑相匹配的進行路由

eureka:
  instance:
    hostname: cloud-gateway-service
  client:
    fetch-registry: true
    register-with-eureka: true
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka/
  1. 主啟動類
@SpringBootApplication
@EnableEurekaClient
public class GatewayMain9527 {
    public static void main(String[] args) {
        SpringApplication.run(GatewayMain9527.class, args);
    }
}
  1. 啟動微服務 Eureka server 7001 client 8001 + Gateway 9527

在這裡插入圖片描述
在這裡插入圖片描述
通過我們 9527 網關訪問 8001的接口

在這裡插入圖片描述
這裡起到了作用

Gateway網關路由的兩種配置方式

  1. 在配置文件中配置
    在配置文件yml中配置
  2. 在配置類中配置
    代碼中注入RouteLocator的Bean

案例(訪問百度)

新建config.GatewayConfig

package com.yxl.cloud.config;

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 customRouteLocator(RouteLocatorBuilder routeLocatorBuilder){
        RouteLocatorBuilder.Builder routes = routeLocatorBuilder.routes();

        routes.route("path_route_angenin",  //id
                r -> r.path("/guonei")  //訪問 http://localhost:9527/guonei
                        .uri("http://news.baidu.com/guonei"));  //就會轉發到 http://news.baidu.com/guonei
        routes.route("path_route_angenin2",  //id
                r -> r.path("/guoji")  //訪問 http://localhost:9527/guoji
                        .uri("http://news.baidu.com/guoji"));  //就會轉發到 http://news.baidu.com/guonji

        return routes.build();

    }
}

訪問:http://localhost:9527/guonei
在這裡插入圖片描述

通過微服務名實現動態路由

server:
  port: 9527

spring:
  application:
    name: cloud-gateway
  cloud:
    gateway:
      discovery:
        locator:
          enabled: true  #開啟從註冊中心動態創建路由的功能,利用微服務名稱進行路由(默認false)
      routes:
        - id: payment_route #路由的id,沒有規定規則但要求唯一,建議配合服務名
          #          uri: http://localhost:8001  #匹配後提供服務的路由地址
          uri: lb://cloud-provider-hystrix-payment
          predicates:
            - Path=/payment/get/** #斷言,路徑相匹配的進行路由

        - id: payment_route2
          #          uri: http://localhost:8001
          uri: lb://cloud-provider-hystrix-payment
          predicates:
            - Path=/payment/lb/** #斷言,路徑相匹配的進行路由


eureka:
  instance:
    hostname: cloud-gateway-service
  client:
    fetch-registry: true
    register-with-eureka: true
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka/

在這裡插入圖片描述
在這裡插入圖片描述

Predicate的使用

在這裡插入圖片描述
官網:https://cloud.spring.io/spring-cloud-static/spring-cloud-gateway/2.2.1.RELEASE/reference/html/#gateway-request-predicates-factories

在這裡插入圖片描述
SpringCloud Gateway 將路由匹配作為Spring WebFlux HandlerMapping 基礎架構的一部分。

SpringCloud Gateway 包括許多內置的Route Predicate工廠。所有這些Predicate 都與HTTP請求的不同屬性匹配。多個Route Predicate工廠可以進行組合

SpringCloud Gateway 創建Route 對象時,使用RoutePredicateFactory 創建 Predicate,Predicate 對象可以賦值給Route。Springcloud Gateway 包含許多內置的 Route Predicate Factories.

所有這些動詞 都匹配HTTP請求的不同屬性,多種謂詞工廠可以組合,通過邏輯and

在這裡插入圖片描述

簡單使用
public class T2 {

    public static void main(String[] args) {
        //獲取當前時間串
        ZonedDateTime now = ZonedDateTime.now();
        System.out.println(now);
        //2020-06-17T11:53:40.325+08:00[Asia/Shanghai]
    }

}

在這裡插入圖片描述
在這裡插入圖片描述

    #指定時間前才能訪問(Before)
   - Before=2020-06-17T11:53:40.325+08:00[Asia/Shanghai]
    #指定時間內才能訪問(Between)
   - Between=2020-06-17T11:53:40.325+08:00[Asia/Shanghai],2020-06-17T12:53:40.325+08:00[Asia/Shanghai]
Cookie

在這裡插入圖片描述

yml 設置 cookie

         - Cookie=username,angenin   #帶Cookie,並且username的值為angenin

不帶cookie 直接訪問失敗
在這裡插入圖片描述

Header

在這裡插入圖片描述

#            - After=2020-06-17T12:53:40.325+08:00[Asia/Shanghai]
#            - Cookie=username,angenin   #帶Cookie,username的值為angenin
            - Header=X-Request-Id, \d+   #請求頭要有 X-Request-Id屬性並且值為整數的正則表達式

Method

在這裡插入圖片描述

- Method=GET    #只允許get請求訪問
總結

在這裡插入圖片描述

Filter的使用

在這裡插入圖片描述

路由過濾器可用於修改進入的HTTP請求和返回的HTTP響應,路由過濾器只能指定路由進行使用。

SpringCloud Gateway 內置了多種路由過濾器,他們都由GatewayFilter的工廠類來產生

在這裡插入圖片描述
GatewayFilter(31種)
Global Filter(10種)

arameter為代表。

package com.yxl.cloud.config;

import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.util.Date;

@Component
@Slf4j
public class MyLogGateWayFilter implements GlobalFilter, Ordered {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        log.info("**************come in MyLogGateWayFilter:" + new Date());
        String uname = exchange.getRequest().getQueryParams().getFirst("uname");
        if(uname ==null){
            log.info("*******用戶名為null,非法用戶!!");
            //設置響應,不被接受
            exchange.getResponse().setStatusCode(HttpStatus.NO_CONTENT);
            return exchange.getResponse().setComplete();

    }
        //返回chain.filter(exchange),放行
        return chain.filter(exchange);
    }

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

http://localhost:9527/payment/lb?xxx=111
在這裡插入圖片描述


Leave a Reply

Your email address will not be published. Required fields are marked *