Spring Cloud Alibaba系列(四)使用gateway作為服務網關

什麼是網關

在微服務架構里,服務的粒度被進一步細分,各個業務服務可以被獨立的設計、開發、測試、部署和管理。這時,各個獨立部署單元可以用不同的開發測試團隊維護,可以使用不同的編程語言和技術平台進行設計,這就要求必須使用一種語言和平台無關的服務協議作為各個單元間的通訊方式。

換句話說就是網關為所有的請求提供了統一的入口,方便我們對服務請求和響應做統一管理。

為什麼要用網關

API 網關是一個處於應用程序或服務(提供 REST API 接口服務)之前的系統,用來管理授權、訪問控制和流量限制等,這樣 REST API 接口服務就被 API 網關保護起來,對所有的調用者透明。

什麼是gateway

Spring Cloud Gateway是Spring官方基於Spring 5.0,Spring Boot 2.0和Project Reactor等技術開發的網關,Spring Cloud Gateway旨在為微服務架構提供一種簡單而有效的統一的API路由管理方式。Spring Cloud Gateway作為Spring Cloud生態系中的網關,目標是替代ZUUL,其不僅提供統一的路由方式,並且基於Filter鏈的方式提供了網關基本的功能,例如:安全,監控/埋點,和限流等。

gateway工作原理

客戶端向Spring Cloud網關發出請求。如果網關處理程序映射確定請求與路由匹配,則將其發送到網關Web處理程序。該處理程序運行通過特定於請求的過濾器鏈發送請求。過濾器由虛線分隔的原因是,過濾器可以在發送代理請求之前或之後執行邏輯。執行所有“前置”過濾器邏輯,然後發出代理請求。發出代理請求后,將執行“后”過濾器邏輯。

路由規則

路由和過濾器是gateway中非常重要的兩個概念,gateway本身提供了非常豐富的路由規則和多種過濾器來適配我們的需求。gateway提供了11種路由規則,分別是:

  • 後置路由謂詞工廠

    該謂詞匹配在當前日期時間之後發生的請求。參數名為 After

  • 前置路由謂詞工廠

    該謂詞匹配當前日期時間之前發生的請求。參數名為 Before

  • 時間段路由謂詞工廠

    該謂詞匹配在datetime1之後和datetime2之前發生的請求。參數名為 Between

  • cookie路由謂詞工廠

    該謂詞匹配具有給定名稱的cookie,並且值匹配正則表達式。參數名為 Cookie

  • 標頭路由謂詞工廠

    該謂詞與具有給定名稱的標頭匹配,並且值與正則表達式匹配。參數名為 Header

  • 主機路由謂詞工廠

    該謂詞是指由路由進行匹配,匹配多個路由時用,隔開。參數名為 Host

  • 方法路由謂詞工廠

    該參數是一個或多個要匹配的HTTP方法。參數名為 Method

  • 路徑路由謂詞工廠

    該謂詞是指在請求路徑上加一個前綴,以此來匹配。參數名為 Path

  • 查詢路由謂詞工廠

  • RemoteAddr路由謂詞工廠

  • 重量路線謂詞工廠

其中,我們比較常用的就是路徑路由謂詞工廠,配合StripPrefix GatewayFilter工廠,實現我們的路由匹配轉發。

路徑路由謂詞工廠配置如下:

spring:
  cloud:
    gateway:
	  discovery:
          locator:
          	enabled: true # 開啟從註冊中心動態創建路由的功能,利用微服務名稱進行路由
      routes:
          # 路由id,建議配合服務名
        - id: demo_route 
          #匹配路由名
          uri: lb://demo-provider 
          predicates:
	  # 斷言,路徑相匹配的進行路由
          - Path=/demo/** 

配置的含義就是,如果請求路徑中是/demo/**,則轉發到demo-provider服務。

網關過濾器

在spring cloud gateway 2.2.2.RELEASE版本中,已經默認實現了30種過濾器。

序號 過濾器工廠 作用 參數
1 AddRequestHeader 為原始請求添加Header Header的名稱及值
2 AddRequestParameter 為原始請求添加請求參數 參數名稱及值
3 AddResponseHeader 為原始響應添加Header Header的名稱及值
4 DedupeResponseHeader 剔除響應頭中重複的值 需要去重的Header名稱及去重策略
5 Hystrix 為路由引入Hystrix的斷路器保護 HystrixCommand的名稱
6 CircuitBreaker 為路由引入Resilience4J斷路器保護 CircuitBreaker的名稱
7 FallbackHeaders 為fallbackUri的請求頭中添加具體的異常信息 Header的名稱
MapRequestHeader 更新原始請求中的Header Header的值
9 PrefixPath 為原始請求頭添加前綴 前綴路徑
10 PreserveHostHeader 為請求添加preserverHostHeader=true的屬性,路由過濾器會檢查該屬性以決定是否要發送原始的host
11 RequestRateLimiter 用於對請求限流,限流算法為令牌桶 keyResolver、rateLimiter、statusCode、denyEmptyKey、emptyKeyStatus
12 RedirectTo 將原始請求重定向到指定的url http狀態碼及重定向的url
13 RemoveHopByHopHeadersFilter 為原始請求刪除IETF組織規定的一系列Header 默認就會啟用,可以通過配置指定僅刪除哪些Header
14 RemoveRequestHeader 為原始請求刪除某個Header Header名稱
15 RemoveResponseHeader 為原始響應刪除某個Header Header名稱
16 RewritePath 重寫原始的請求路徑 原始路徑正則表達式以及重寫後路徑的正則表達式
RewriteLocationResponseHeader 重寫響應頭的Location 的值
18 RewriteResponseHeader 重寫原始響應中的某個Header Header名稱,值的正則表達式,重寫后的值
19 SaveSession 在轉發請求之前,強制執行WebSession::save操作
20 SecureHeaders 為原始響應添加一系列起安全作用的響應頭 無,支持修改這些安全響應頭的值
21 SetPath 修改原始的請求路徑 修改后的值
22 SetRequestHeader 修改原始請求中的某個Header的值 Header名稱,修改后的值
23 SetResponseHeader 修改原始響應中某個Header的值 Header名稱,修改后的值
24 SetStatus 修改原始響應的狀態碼 HTTP 狀態碼,可以是数字,也可以是字符串
25 StripPrefix 用於截斷原始請求的路徑 使用數字錶示要截斷的路徑的數量
26 Retry 針對不同的響應進行重試 retries、statuses、methods、series
27 RequestSize 設置允許接收最大請求包的大小。如果請求包大小超過設置的值,則返回 413 Payload Too Large設置允許接收最大請求包的大小。如果請求包大小超過設置的值,則返回 413 Payload Too Large 請求包大小,單位為字節,默認值為5M
28 ModifyRequestBody 在轉發請求之前修改原始請求體內容 修改后的請求體內容
29 ModifyResponseBody 修改原始響應體的內容 修改后的響應體內容
30 Default 為所有路由添加過濾器 過濾器工廠名稱及值

這裏比較常用的如第25種,配置如下:

spring:
  cloud:
    gateway:
	  discovery:
          locator:
          	enabled: true # 開啟從註冊中心動態創建路由的功能,利用微服務名稱進行路由
      routes:
		  # 路由id,建議配合服務名
        - id: demo_route 
          #匹配路由名
          uri: lb://demo-provider 
          predicates:
		  # 斷言,路徑相匹配的進行路由
          - Path=/demo/** 
          filters:
          - StripPrefix=1

一般情況下我們配合path路由使用,這裏的意思是假如,我們的demo-provider服務種有一個/test的接口,實際上我們的請求路徑經過網關時應該時/demo/test,這樣就能把這個路由分發到demo-provider服務中,但是分發過去的路由是/demo/test,和我們實際的/test接口不一樣。這時候我們用StripPrefix=1,來截取掉一級路由,這樣轉發過去的路由就是/test了。

自定義網關過濾器

除了上面提供的30種過濾器外,我們還可以實現自定義的過濾器。

1. 實現GatewayFilter接口和Ordered接口

gatewayFilter接口是為了實現請求過濾,ordered接口是為了給過濾器設定優先級,值越大級別越低。

想要實現一個自定義的過濾器,無非就是兩個步驟:1.實現過濾器,2.將過濾器添加到具體路由上。

public class TokenGatewayFilter implements GatewayFilter, Ordered {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {

        System.out.println("這裏處理自身邏輯");

        return chain.filter(exchange);
    }

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

@Configuration
class RouteConfiguration{

    @Bean
    public RouteLocator routeLocator(RouteLocatorBuilder builder){

        return builder.routes().route( r->
                r.path("/demo/**")
                .uri("lb://demo-provider ")
                .filter(new TokenGatewayFilter())
                .id("demo_route "))
                .build();
    }
}

2.繼承AbstractGatewayFilterFactory類

@Component
public class TokenCheckGatewayFilterFactory extends AbstractGatewayFilterFactory<TokenCheckGatewayFilterFactory.Config> {
    public TokenCheckGatewayFilterFactory() {
        super(Config.class);
    }

    @Override
    public List<String> shortcutFieldOrder() {
        return Arrays.asList("enabled");
    }
    @Override
    public GatewayFilter apply(Config config) {
        return (exchange, chain) -> {
        	system.out.println("這裏處理自身邏輯")
            return chain.filter(exchange);
        };

    }

    public static class Config {
        // 控制是否開啟認證
        private boolean enabled = true;

        public Config() {}

        public boolean isEnabled() {
            return enabled;
        }

        public void setEnabled(boolean enabled) {
            this.enabled = enabled;
        }
    }
}

這裏我們可以直接在application.yml中為需要過濾的路由添加這個過濾器。

spring:
  cloud:
    gateway:
      routes:
        - id: demo_route # 路由id,建議配合服務名
          uri: lb://demo-provider #匹配路由名
          predicates:
          - Path=/demo/** # 斷言,路徑相匹配的進行路由
          filters:
          - TokenCheck=true

需要注意的是,這個地方自定義的過濾器名稱必須是XXGatewayFilterFactory,並且配置文件中配置過濾器時名字必須時這個XX

當然,我們也可以為每個路由都添加這個過濾器,可以直接這樣寫配置,而不用在每個路由上都去寫。

spring:
  cloud:
    gateway:
      default-filters:
        - TokenCheck=true

3.實現GlobalFilter和ordered

這個GlobalFilter從名字中就可以看出,是一個全局過濾器,也就是說實現這個接口后,所有的請求都會被過濾,我們就不需要在去找往某個路由中加過濾器了。

@Component
public class TokenGlobalFilter implements GlobalFilter, Ordered {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        System.out.println("這裏處理自身邏輯");
        return chain.filter(exchange);
    }

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

以上就是實現自定義網關過濾器的三種方式了。實際開發中根據需求來實現合適的過濾器就可以了。

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

USB CONNECTOR掌控什麼技術要點? 帶您認識其相關發展及效能

台北網頁設計公司這麼多該如何選擇?

※智慧手機時代的來臨,RWD網頁設計為架站首選

※評比南投搬家公司費用收費行情懶人包大公開

※回頭車貨運收費標準

您可能也會喜歡…