SpringCloud Gateway 服務閘道器的快速入門

語言: CN / TW / HK

前言

  Spring Cloud Gateway 旨在提供一種簡單而有效的方式來路由到 API,併為它們提供橫切關注點,例如:安全性、監控/指標和彈性。 閘道器作為系統的唯一流量入口,封裝內部系統的架構,所有請求都先經過閘道器,由閘道器將請求路由到合適的微服務。文字僅僅簡單的介紹了對 Spring Cloud Gateway 的認識及使用。

1、Gateway 簡介

Gateway 閘道器官網連結: http://spring.io/projects/spring-cloud-gateway

1、閘道器的 核心功能特性

  • 請求路由:一切請求都必須先經過 gateway,但閘道器不處理業務,而是根據某種規則,把請求轉發到某個微服務,這個過程叫做路由。當然路由的目標服務有多個時,還需要做負載均衡。

  • 許可權控制:閘道器作為微服務入口,需要校驗使用者是是否有請求資格,如果沒有則進行攔截。

  • 限流:當請求流量過高時,在閘道器中按照下流的微服務能夠接受的速度來放行請求,避免服務壓力過大。

2、架構圖:

2、Gateway 特點

  • 基於 Spring Framework 5、Project Reactor 和 Spring Boot 2.0 構建

  • 能夠匹配任何請求屬性的路由。

  • 謂詞和過濾器特定於路由。

  • 斷路器整合。

  • Spring Cloud Discovery 客戶端整合

  • 易於編寫謂詞和過濾器

  • 請求速率限制

  • 路徑重寫

3、Gateway 快速入門

1、建立 gateway 服務

建立 SpringBoot 工程 gatewaway

2、引入依賴

引入依賴,nacos 和閘道器 gateway 的依賴。

<!--閘道器--><dependency>    <groupId>org.springframework.cloud</groupId>    <artifactId>spring-cloud-starter-gateway</artifactId></dependency><!--nacos服務發現依賴--><dependency>    <groupId>com.alibaba.cloud</groupId>    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency>

複製程式碼

3、編寫啟動類

import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplicationpublic class GatewayApplication {
public static void main(String[] args) { SpringApplication.run(GatewayApplication.class, args); }}

複製程式碼

4、編寫配置檔案

編寫基礎配置和路由規則,建立 application.yml 檔案,內容如下:

server:  port: 10086 # 閘道器埠spring:  application:    name: gateway # 服務名稱  cloud:    nacos:      server-addr: localhost:8848 # nacos地址    gateway:      routes: # 閘道器路由配置        - id: user-service # 路由id,自定義,只要唯一即可          # uri: http://127.0.0.1:8081 # 路由的目標地址 http就是固定地址          uri: lb://userservice # 路由的目標地址 lb就是負載均衡,後面跟服務名稱          predicates: # 路由斷言,也就是判斷請求是否符合路由規則的條件            - Path=/user/** # 這個是按照路徑匹配,只要以/user/開頭就符合要求

複製程式碼

我們將符合 Path 規則的一切請求,都代理到 uri 引數指定的地址。

本例中,我們將 /user/** 開頭的請求,代理到 lb://userservice ,lb 是負載均衡,根據服務名拉取服務列表,實現負載均衡。

5、測試

當訪問 http://localhost:10086/user/1 時,符合 /user/** 規則,請求轉發到 uri:http://user-service/user/1,得到了結果:

簡單來說,當來了一個請求時,都會經過閘道器判斷是否符合規則,如果符合規則則跳轉到相應地址。

4、斷言工廠

我們在配置檔案中寫的斷言規則只是字串,這些字串會被 Predicate Factory 讀取並處理,轉變為路由判斷的條件

例如 Path=/user/**是按照路徑匹配,這個規則是由

org.springframework.cloud.gateway.handler.predicate.PathRoutePredicateFactory 類來

SpringCloudGateway 的斷言工廠在還有下面十幾個:

5、過濾器工廠

GatewayFilter 是閘道器中提供的一種過濾器,可以對進入閘道器的請求和微服務返回的響應做處理。

1、路由過濾器的種類

Spring 提供了很多種不同的路由過濾器工廠。例如:

2、請求頭過濾器

只需要修改 gateway 服務的 application.yml 檔案,新增路由過濾即可。配置如下:

spring:  cloud:    gateway:      routes:      - id: user-service         uri: lb://user-service         predicates:         - Path=/user/**         filters: # 過濾器        - AddRequestHeader= ***      # 新增請求頭

複製程式碼

3、預設過濾器

如果要對所有的路由都生效,則可以將過濾器工廠寫到 default 下。配置如下:

spring:  cloud:    gateway:      routes:      - id: user-service         uri: lb://user-service         predicates:         - Path=/user/**      default-filters: # 預設過濾項      - AddRequestHeader=  *** 

複製程式碼

6、全域性過濾器

1、全域性過濾器作用

全域性過濾器的作用也是處理一切進入閘道器的請求和微服務響應,與 GatewayFilter 的作用一樣。

區別在於 GatewayFilter 通過配置定義,處理邏輯是固定的;而 GlobalFilter 的邏輯需要自己寫程式碼實現。

定義方式是實現 GlobalFilter 介面。

public interface GlobalFilter {    /**     *  處理當前請求,有必要的話通過{@link GatewayFilterChain}將請求交給下一個過濾器處理     *     * @param exchange 請求上下文,裡面可以獲取Request、Response等資訊     * @param chain 用來把請求委託給下一個過濾器      * @return {@code Mono<Void>} 返回標示當前過濾器業務結束     */    Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain);}

複製程式碼

在 filter 中編寫自定義邏輯,可以實現下列功能:

  • 登入狀態判斷

  • 許可權校驗

  • 請求限流等

2、自定義全域性過濾器

  定義全域性過濾器,攔截請求,判斷請求的引數是否滿足條件,引數中是否有 authorization,authorization 引數值是否為 admin,如果同時滿足則放行,否則攔截。

在 gateway 中定義一個過濾器,程式碼如下。

@Order(-1)@Componentpublic class AuthorizeFilter implements GlobalFilter {    @Override    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {        // 1.獲取請求引數        MultiValueMap<String, String> params = exchange.getRequest().getQueryParams();        // 2.獲取authorization引數        String auth = params.getFirst("authorization");        // 3.校驗        if ("admin".equals(auth)) {            // 放行            return chain.filter(exchange);        }        // 4.攔截        // 4.1.禁止訪問,設定狀態碼        exchange.getResponse().setStatusCode(HttpStatus.FORBIDDEN);        // 4.2.結束處理        return exchange.getResponse().setComplete();    }}

複製程式碼

3、過濾器執行順序

請求進入閘道器會碰到三類過濾器:

  • 當前路由的過濾器

  • DefaultFilter

  • GlobalFilter

請求路由後,會將當前路由過濾器和 DefaultFilter、GlobalFilter,合併到一個過濾器鏈(集合)中,排序後依次執行每個過濾器。

排序的規則如下:

  • 每一個過濾器都必須指定一個 int 型別的 order 值, order 值越小,優先順序越高,執行順序越靠前

  • GlobalFilter 通過實現 Ordered 介面,或者新增 @Order 註解來指定 order 值,由我們自己指定

  • 路由過濾器和 defaultFilter 的 order 由 Spring 指定,預設是按照宣告順序從 1 遞增。

  • 當過濾器的 order 值一樣時,會按照 defaultFilter > 路由過濾器 > GlobalFilter 的順序執行。

7、跨域問題

在 gateway 服務的 application.yml 檔案中,根據需求新增下面的配置。

spring:  cloud:    gateway:      globalcors:                 # 全域性的跨域處理        add-to-simple-url-handler-mapping: true # 解決options請求被攔截問題        corsConfigurations:          '[/**]':            allowedOrigins:             # 允許哪些網站的跨域請求               - "http://localhost:8090"            allowedMethods:             # 允許的跨域ajax的請求方式              - "GET"              - "POST"              - "DELETE"              - "PUT"              - "OPTIONS"            allowedHeaders: "*"         # 允許在請求中攜帶的頭資訊            allowCredentials: true         # 是否允許攜帶cookie            maxAge: 360000           # 這次跨域檢測的有效期

複製程式碼

總結

 API Gateway(APIGW / API 閘道器),是出現在系統邊界上的一個面向 API 的、序列集中式的強管控服務,這裡的邊界是企業 IT 系統的邊界,可以理解為 企業級應用防火牆,主要起到 隔離外部訪問與內部系統的作用。簡單來說,當來了一個請求時,都會經過閘道器,進行把關。在微服務概念的流行之前,API 閘道器就已經誕生了,例如銀行、證券等領悅常見的前置機系統,它也是解決訪問認證、報文轉換、訪問統計等問題的。
 最後,每日毒雞湯:"三人省力,四人更簡單,眾人團結緊,百事能成功。"