1. 程式人生 > 其它 >資料倉庫(6)數倉分層設計

資料倉庫(6)數倉分層設計

簡介

Gateway是在Spring生態系統之上構建的API閘道器服務,基於Spring 5,Spring Boot 2和 Project Reactor等技術。

Gateway旨在提供一種簡單而有效的方式來對API進行路由,以及提供一些強大的過濾器功能, 例如:熔斷、限流、重試等。

SpringCloud Gateway 是 Spring Cloud 的一個全新專案,基於 Spring 5.0 + Spring Boot 2.0 和 Project Reactor 等技術開發的閘道器,它旨在為微服務架構提供一種簡單有效的統一的 API 路由管理方式。

SpringCloud Gateway 作為 Spring Cloud 生態系統中的閘道器,目標是替代 Zuul,在Spring Cloud 2.0以上版本中,沒有對新版本的 Zuul 2.0 以上最新高效能版本進行整合,仍然還是使用的Zuul 1.x非Reactor模式的老版本。而為了提升閘道器的效能,SpringCloud Gateway 是基於 WebFlux 框架實現的,而 WebFlux 框架底層則使用了高效能的 Reactor 模式通訊框架 Netty。

微服務中的閘道器位置

Spring Cloud Gateway 與 Zuul 的區別

在SpringCloud Finchley 正式版之前,Spring Cloud 推薦的閘道器是 Netflix 提供的Zuul:

  • Zuul 1.x,是一個基於阻塞 I/ O 的 API Gateway
  • Zuul 1.x 基於Servlet 2. 5使用阻塞架構它不支援任何長連線(如 WebSocket) Zuul 的設計模式和Nginx較像,每次 I/ O 操作都是從工作執行緒中選擇一個執行,請求執行緒被阻塞到工作執行緒完成,但是差別是Nginx 用C++ 實現,Zuul 用 Java 實現,而 JVM 本身會有第一次載入較慢的情況,使得Zuul 的效能相對較差。
  • Zuul 2.x理念更先進,想基於Netty非阻塞和支援長連線,但SpringCloud目前還沒有整合。 Zuul 2.x的效能較 Zuul 1.x 有較大提升。在效能方面,根據官方提供的基準測試,Spring Cloud Gateway 的 RPS 是 Zuul 的 1.6 倍。
  • Spring Cloud Gateway 建立在 Spring Framework 5,Project Reactor 和 Spring Boot 2 之上,使用非阻塞 API。
  • Spring Cloud Gateway 還支援 WebSocket,並且與 Spring 緊密整合擁有更好的開發體驗。

WebFlux是什麼?

傳統的Web框架,比如說:struts2,springmvc等都是基於Servlet API與Servlet容器基礎之上執行的。

但是在 Servlet3.1 之後有了非同步非阻塞的支援。而 WebFlux 是一個典型非阻塞非同步的框架,它的核心是基於Reactor 的相關 API 實現的。相對於傳統的 web 框架來說,它可以執行在諸如 Netty,Undertow 及支援Servlet3.1 的容器上。非阻塞式+函數語言程式設計( Spring5 必須讓你使用 java8)

Spring WebFlux 是 Spring 5.0 引入的新的響應式框架,區別於 Spring MVC,它不需要依賴 Servlet API,它是完全非同步非阻塞的,並且基於 Reactor 來實現響應式流規範。

Gateway 的核心概念

Route(路由)

路由是構建閘道器的基本模組,它由ID,目標URI,一系列的斷言和過濾器組成,如果斷言為true則匹配該路由;

Predicate(斷言)

參考的是Java8的 java.util.function.Predicate 開發人員可以匹配HTTP請求中的所有內容(例如請求頭或請求引數),如果請求與斷言相匹配則進行路由;

Filter(過濾)

指的是Spring框架中GatewayFilter的例項,使用過濾器,可以在請求被路由前或者之後對請求進行修改。

總結

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

大致流程

客戶端向 Spring Cloud Gateway 發出請求。然後在 Gateway Handler Mapping 中找到與請求相匹配的路由,將其傳送到 Gateway Web Handler。

Handler 再通過指定的過濾器鏈來將請求傳送到我們實際的服務執行業務邏輯,然後返回。

過濾器之間用虛線分開是因為過濾器可能會在傳送代理請求之前(“pre”)或之後(“post”)執行業務邏輯。Filter在“pre”型別的過濾器可以做引數校驗、許可權校驗、流量監控、日誌輸出、協議轉換等,在“post”型別的過濾器中可以做響應內容、響應頭的修改,日誌的輸出,流量監控等有著非常重要的作用。

案例

導包

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

修改配置檔案

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

        - id: payment_routh2 #payment_route    #路由的ID,沒有固定規則但要求唯一,建議配合服務名
          #uri: http://localhost:8001          #匹配後提供服務的路由地址
          uri: lb://cloud-payment-service #匹配後提供服務的路由地址
          predicates:
            - Path=/payment/lb/**         # 斷言,路徑相匹配的進行路由
            #- After=2020-02-21T15:51:37.485+08:00[Asia/Shanghai]
            #- Cookie=username,zzyy
            #- Header=X-Request-Id, \d+  # 請求頭要有X-Request-Id屬性並且值為整數的正則表示式

配置類的方法

@Configuration
public class GatewayConfig {

    @Bean
    public RouteLocator customRouteLocator(RouteLocatorBuilder routeLocatorBuilder) {
        RouteLocatorBuilder.Builder routes = routeLocatorBuilder.routes();
        routes.route("path_route_atguigu",
                r -> r.path("/guonei")
                        .uri("https://news.baidu.com/guonei")).build();

        return routes.build();
    }
}

Predicate 使用

Spring Cloud Gateway將路由匹配作為Spring WebFlux HandlerMapping基礎架構的一部分。Spring Cloud Gateway包括許多內建的Route Predicate工廠。所有這些Predicate都與HTTP請求的不同屬性匹配。多個Route Predicate工廠可以進行組合;

Spring Cloud Gateway 建立 Route 物件時, 使用 RoutePredicateFactory 建立 Predicate 物件,Predicate 物件可以賦值給 Route。 Spring Cloud Gateway 包含許多內建的Route Predicate Factories。

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

常用的Route Predicate

  • 請求時間校驗條件(datetime):

    • After Route Predicate:請求時間滿足在配置時間之後。
    • Before Route Predicate:請求時間滿足在配置時間之前。
    • Between Route Predicate:請求時間滿足在配置時間之間。
  • 請求 Cookie校驗條件(Cookie):

    • Cookie Route Predicate:請求指定 Cookie 正則匹配指定值
      • 需要兩個引數,一個是 Cookie name,一個是正則表示式。
  • 請求 Header 校驗條件(Header):

    • Header Route Predicate:請求指定 Header 正則匹配指定值;

      • 兩個引數:一個是屬性名稱和一個正則表示式,這個屬性值和正則表示式匹配執行。

      • curl http://localhost:9527/payment/lb -H "X-Request-Id:123"
        
    • CloudFoundryRouteServiceRoutePredicateFactory:請求 Headers 是否包含指定的名稱。

  • 請求 Host 校驗條件(Host):

    • Host Route Predicate:請求 Host 匹配指定值;
  • 請求 Method 校驗條件(Method):

    • Method Route Predicate:請求 Method 匹配配置的 method;
  • 請求 Path 校驗條件(Path):

    • Path Route Predicate:請求路徑正則匹配指定值;
  • 請求查詢引數校驗條件(Queryparam):

    • Query Route Predicate:請求查詢引數正則匹配指定值;
  • 請求遠端地址校驗條件(RemoteAddr):

    • RemoteAddrRoutePredicateFactory:請求遠端地址匹配配置指定值;

Filter 的使用

路由過濾器可用於修改進入的HTTP請求和返回的HTTP響應,路由過濾器只能指定路由進行使用。Spring Cloud Gateway 內建了多種路由過濾器,他們都由GatewayFilter的工廠類來產生;

Filter 的分類

生命週期
  • pre
  • post
種類
  • GatewayFilter
  • GlobalFilter

自定義過濾器

主要實現:全域性日誌記錄、統一閘道器鑑權等服務;

案例
@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.NOT_ACCEPTABLE);
            return exchange.getResponse().setComplete();
        }
        return chain.filter(exchange);
    }

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