Spring Cloud gateway 網關服務二 斷言、過濾器


微服務當前這么火爆的程度,如果不能學會一種微服務框架技術。怎么能升職加薪,增加簡歷的籌碼?spring cloud 和 Dubbo 需要單獨學習。說沒有時間?沒有精力?要學倆個框架?而Spring Cloud alibaba只需要你學會一個就會擁有倆種微服務治理框架技術。何樂而不為呢?加油吧!騷猿年

上一篇我們講述了gateway 的路由功能其實也類似與zuul服務的路由轉發。
今天主要講一下斷言機制。

內置的斷言工廠

介紹 Spring Cloud Gateway將路由作為Spring WebFlux HandlerMapping基礎架構的一部分進行匹配。Spring Cloud Gateway包括許多內置的Route Predicate工廠。所有這些斷言都與HTTP請求的不同屬性匹配。多個Route Predicate工廠可以合並,也可以通過邏輯合並

file

可以看到gateway 提供如此之多豐富的斷言,方式。

  • 比如說時間控住的,我們能想到秒殺場景。
  • ip 的我們能想到金絲雀測試
  • 權重我們可以使用灰度等等場景的應用

具體使用還得參照業務場景來選擇更適合我們的業務場景。

gateway 過濾器 分為全局過濾器,個性化過濾器

gateway 已經給我們提供了非常豐富的過濾器

  • AddRequestHeader GatewayFilter工廠采用名稱和值參數。

      這會將X-Request-Foo:Bar標頭添加到所有匹配請求的下游請求的標頭中。
    
      spring:
      	cloud:
      		gateway:
      			routes:
      			- id: add_request_header_route
      				uri: https://example.org
      				filters:
      				- AddRequestHeader=X-Request-Foo, Bar
      
      AddRequestHeader知道用於匹配路徑或主機的URI變量。URI變量可用於該值,並將在運行時擴展。
    
      spring:
      	cloud:
      		gateway:
      			routes:
      			- id: add_request_header_route
      				uri: https://example.org
      				predicates:
      				- Path=/foo/{segment}
      				filters:
      				- AddRequestHeader=X-Request-Foo, Bar-{segment}
    

-AddResponseHeader GatewayFilter工廠采用名稱和值參數。

spring:
	cloud:
		gateway:
			routes:
			- id: add_request_parameter_route
				uri: https://example.org
				filters:
				- AddRequestParameter=foo, bar

這將添加foo=bar到所有匹配請求的下游請求的查詢字符串中。

AddRequestParameter知道用於匹配路徑或主機的URI變量。URI變量可用於該值,並將在運行時擴展。

spring:
	cloud:
		gateway:
			routes:
			- id: add_request_parameter_route
				uri: https://example.org
				predicates:
				- Host: {segment}.myhost.org
				filters:
				- AddRequestParameter=foo, bar-{segment}
  • AddResponseHeader GatewayFilter工廠采用名稱和值參數。

    spring:
    cloud:
    gateway:
    routes:
    - id: add_response_header_route
    uri: https://example.org
    filters:
    - AddResponseHeader=X-Response-Foo, Bar

    這會將X-Response-Foo:Bar標頭添加到所有匹配請求的下游響應的標頭中。

    AddResponseHeader知道用於匹配路徑或主機的URI變量。URI變量可用於該值,並將在運行時擴展。
    spring:
    cloud:
    gateway:
    routes:
    - id: add_response_header_route
    uri: https://example.org
    predicates:
    - Host: {segment}.myhost.org
    filters:
    - AddResponseHeader=foo, bar-{segment}

  • DedupeResponseHeader GatewayFilter工廠采用一個name參數和一個可選strategy參數。name可以包含標題名稱列表,以空格分隔。
    spring:
    cloud:
    gateway:
    routes:
    - id: dedupe_response_header_route
    uri: https://example.org
    filters:
    - DedupeResponseHeader=Access-Control-Allow-Credentials Access-Control-Allow-Origin

    如果網關CORS邏輯和下游邏輯都添加了重復的值Access-Control-Allow-Credentials和Access-Control-Allow-Origin響應標頭,則這將刪除它們。

    DedupeResponseHeader過濾器還接受可選strategy參數。可接受的值為RETAIN_FIRST(默認值)RETAIN_LAST,和RETAIN_UNIQUE

  • Hystrix是Netflix的一個庫,用於實現斷路器模式。Hystrix GatewayFilter允許您將斷路器引入網關路由,保護您的服務免受級聯故障的影響,並允許您在下游故障的情況下提供后備響應
    要在項目中啟用Hystrix GatewayFilters,請spring-cloud-starter-netflix-hystrix從Spring Cloud Netflix添加依賴項。

    Hystrix GatewayFilter工廠需要一個name參數,它是的名稱HystrixCommand。
    spring:
    cloud:
    gateway:
    routes:
    - id: hystrix_route
    uri: https://example.org
    filters:
    - Hystrix=myCommandName

這會將其余的過濾器包裝在HystrixCommand帶有命令名的中myCommandName。

Hystrix過濾器還可以接受可選fallbackUri參數。當前,僅forward:支持計划的URI。如果調用了后備,則請求將被轉發到與URI相匹配的控制器。

	spring:
		cloud:
			gateway:
				routes:
				- id: hystrix_route
					uri: lb://backing-service:8088
					predicates:
					- Path=/consumingserviceendpoint
					filters:
					- name: Hystrix
						args:
							name: fallbackcmd
							fallbackUri: forward:/incaseoffailureusethis
					- RewritePath=/consumingserviceendpoint, /backingserviceendpoint

/incaseoffailureusethis調用Hystrix后備時,它將轉發到URI。請注意,此示例還通過lb目標URI 上的前綴演示了(可選)Spring Cloud Netflix Ribbon負載平衡。

主要方案是對fallbackUri網關應用程序中的內部控制器或處理程序使用。但是,也可以將請求重新路由到外部應用程序中的控制器或處理程序,如下所示:

	spring:
		cloud:
			gateway:
				routes:
				- id: ingredients
					uri: lb://ingredients
					predicates:
					- Path=//ingredients/**
					filters:
					- name: Hystrix
						args:
							name: fetchIngredients
							fallbackUri: forward:/fallback
				- id: ingredients-fallback
					uri: http://localhost:9994
					predicates:
					- Path=/fallback

在此示例中,fallback網關應用程序中沒有終結點或處理程序,但是另一個應用程序中有一個終結點或處理程序,在下注冊localhost:9994。

如果將請求轉發給后備,則Hystrix網關過濾器還會提供Throwable引起請求的。它已ServerWebExchange作為 ServerWebExchangeUtils.HYSTRIX_EXECUTION_EXCEPTION_ATTR屬性添加到,可以在網關應用程序中處理后備時使用。

對於外部控制器/處理程序方案,可以添加帶有異常詳細信息的標頭。您可以在FallbackHeaders GatewayFilter Factory部分中找到有關它的更多信息。

Hystrix設置(例如超時)可以使用全局默認值配置,也可以使用Hystrix Wiki上說明的應用程序屬性在逐條路由的基礎上進行配置。

要為上述示例路由設置5秒超時,將使用以下配置:

hystrix.command.fallbackcmd.execution.isolation.thread.timeoutInMilliseconds: 5000
  • 該FallbackHeaders工廠可以讓你在轉發到請求的頭部添加蝟執行異常的詳細信息fallbackUri在以下情況下在外部應用程序
    spring:
    cloud:
    gateway:
    routes:
    - id: ingredients
    uri: lb://ingredients
    predicates:
    - Path=//ingredients/**
    filters:
    - name: Hystrix
    args:
    name: fetchIngredients
    fallbackUri: forward:/fallback
    - id: ingredients-fallback
    uri: http://localhost:9994
    predicates:
    - Path=/fallback
    filters:
    - name: FallbackHeaders
    args:
    executionExceptionTypeHeaderName: Test-Header

在此示例中,在運行時發生執行異常后HystrixCommand,該請求將轉發到在上fallback運行的應用中的端點或處理程序localhost:9994。具有異常類型,消息和-if available-根本原因異常類型和消息的標頭將由FallbackHeaders過濾器添加到該請求。

通過設置下面列出的參數的值及其默認值,可以在配置中覆蓋標頭的名稱:

- executionExceptionTypeHeaderName("Execution-Exception-Type")

- executionExceptionMessageHeaderName("Execution-Exception-Message")

- rootCauseExceptionTypeHeaderName("Root-Cause-Exception-Type")

- rootCauseExceptionMessageHeaderName("Root-Cause-Exception-Message")

您可以在Hystrix GatewayFilter Factory部分中找到有關Hystrix如何與Gateway一起工作的更多信息。

  • MapRequestHeader GatewayFilter工廠采用'fromHeader'和'toHeader'參數。它創建一個新的命名標頭(toHeader),並從傳入的HTTP請求中從現有的命名標頭(fromHeader)中提取值。如果輸入標頭不存在,則過濾器不起作用。如果新的命名標頭已經存在,則其值將使用新值進行擴充。

      spring:
      	cloud:
      		gateway:
      			routes:
      			- id: map_request_header_route
      				uri: https://example.org
      				filters:
      				- MapRequestHeader=Bar, X-Request-Foo
    

這會將X-Request-Foo: 標頭添加到下游請求的標頭中,其中包含來自傳入的HTTP請求Bar標頭的更新值。

  • PrefixPath GatewayFilter工廠采用單個prefix參數。
    spring:
    cloud:
    gateway:
    routes:
    - id: prefixpath_route
    uri: https://example.org
    filters:
    - PrefixPath=/mypath

這將/mypath作為所有匹配請求的路徑的前綴。因此,對的請求/hello將發送給/mypath/hello。

  • PreserveHostHeader GatewayFilter工廠沒有參數。此過濾器設置請求屬性,路由過濾器將檢查該請求屬性,以確定是否應發送原始主機頭,而不是由HTTP客戶端確定的主機頭。

      spring:
      	cloud:
      		gateway:
      			routes:
      			- id: preserve_host_route
      				uri: https://example.org
      				filters:
      				- PreserveHostHeader
    
  • RequestRateLimiter GatewayFilter Factory使用一種RateLimiter實現來確定是否允許繼續當前請求。如果不是,HTTP 429 - Too Many Requests則返回狀態(默認)。此過濾器采用一個可選keyResolver參數和特定於速率限制器的參數。

  • Redis RateLimiter GatewayFilter工廠 redis實現基於Stripe所做的工作。它需要使用spring-boot-starter-data-redis-reactiveSpring Boot啟動器。

  • RedirectTo GatewayFilter工廠采用status和url參數。狀態應該是300系列重定向http代碼,例如301。URL應該是有效的URL。這將是Location標題的值

  • RemoveHopByHopHeadersFilter GatewayFilter工廠從轉發的請求中刪除標頭。被刪除的頭的默認列表來自IETF。

  • RemoveRequestHeader GatewayFilter工廠采用一個name參數。它是要刪除的標題的名稱。

  • RemoveResponseHeader GatewayFilter工廠采用一個name參數。它是要刪除的標題的名稱。

  • RemoveRequestParameter GatewayFilter工廠采用一個name參數。它是要刪除的查詢參數的名稱。

  • RewritePath GatewayFilter工廠采用路徑regexp參數和replacement參數。這使用Java正則表達式提供了一種靈活的方式來重寫請求路徑。

  • RewriteLocationResponseHeader GatewayFilter工廠Location通常會修改響應標頭的值,以擺脫后端特定的詳細信息。這需要stripVersionMode,locationHeaderName,hostValue,和protocolsRegex參數。

  • 該RewriteResponseHeader GatewayFilter廠需要name,regexp和replacement參數。它使用Java正則表達式以靈活的方式重寫響應標頭值。

  • SaveSession GatewayFilter Factory 在向下游轉發呼叫之前強制執行WebSession::save操作。這在將Spring Session之類的東西與惰性數據存儲一起使用時特別有用,並且需要確保在進行轉發呼叫之前已保存會話狀態。

  • SetPath GatewayFilter工廠采用路徑template參數。通過允許路徑的模板段,它提供了一種操作請求路徑的簡單方法。這使用了Spring Framework中的uri模板。允許多個匹配段。

  • SetRequestHeader GatewayFilter工廠采用name和value參數。

  • SetResponseHeader GatewayFilter工廠采用name和value參數

  • SetStatus GatewayFilter工廠采用單個status參數。它必須是有效的Spring HttpStatus。它可以是整數值404或枚舉的字符串表示形式NOT_FOUND

  • StripPrefix GatewayFilter工廠采用一個參數parts。該parts參數指示在向下游發送請求之前,要從請求中剝離的路徑中的零件數

  • 重試GatewayFilter工廠

  • RequestSize GatewayFilter工廠 當請求大小大於允許的限制時,RequestSize GatewayFilter Factory可以限制請求到達下游服務。過濾器將RequestSize參數作為請求的允許大小限制(以字節為單位

  • 修改請求正文GatewayFilter工廠 該過濾器被認為是BETA,API將來可能會更改 此過濾器可用於在網關將請求主體發送到下游之前修改請求主體。

  • 默認過濾器 如果您想添加過濾器並將其應用於所有路由,則可以使用spring.cloud.gateway.default-filters。該屬性采用過濾器列表

  • 全局過濾器 該GlobalFilter接口具有與相同的簽名GatewayFilter。這些是特殊過濾器,有條件地應用於所有路由。(此界面和用法可能會在將來的里程碑中更改)。

  • 全局過濾器和GatewayFilter的組合訂購

因為spring cloud gateway 提供的內置過濾器太多了。不在這里一一介紹
可以查看官方的文檔 進行了解學習

gateway官方文檔

https://cloud.spring.io/spring-cloud-gateway/reference/html/

接下來講一下,全局過濾器GlobalFilter接口。

  • GlobalFilter 和 GatewayFilter 的 #filter(ServerWebExchange, GatewayFilterChain) 方法簽名一致;
  • GlobalFilter會作用於所有的路由上;
  • 在未來的里程碑版本中可能作一些調整;

可以看一下默認的實現的全局過濾器 ,除去AuthorizeFilter過濾器都是默認的過濾器

file

具體的里面的作用,其實上面的已經有了簡單的描述不在復述。有興趣的同學可以看看里面的實現,都是利用過濾器做轉發或者一些對流量請求的修改、鑒權、等操作

可以通過actuator 模塊監控查詢 GlobalFilter實現類

1、pom引入spring-boot-starter-actuator 。因為之前就直接在parent pom 進行了引入操作。不再次引入

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

2、配置文件bootstrap.yml中開啟監控管理端點


management:
  endpoints:
    web:
      exposure:
        include: "*"
  endpoint:
    health:
      show-details: ALWAYS

3、請求瀏覽器 http://localhost:9000/actuator/gateway/globalfilters

{
org.springframework.cloud.gateway.filter.AdaptCachedBodyGlobalFilter@4b957db0: -2147482648,
org.springframework.cloud.gateway.filter.WebsocketRoutingFilter@273fa9e: 2147483646,
com.xian.cloud.filter.AuthorizeFilter@4b03cbad: 0,
org.springframework.cloud.gateway.filter.ForwardRoutingFilter@8840c98: 2147483647,
org.springframework.cloud.gateway.filter.NettyRoutingFilter@5c313224: 2147483647,
org.springframework.cloud.gateway.filter.NettyWriteResponseFilter@1e1e837d: -1,
org.springframework.cloud.gateway.filter.RouteToRequestUrlFilter@5d71b500: 10000,
org.springframework.cloud.gateway.filter.LoadBalancerClientFilter@5b29ab61: 10100,
org.springframework.cloud.gateway.filter.GatewayMetricsFilter@527a8665: -2147473648,
org.springframework.cloud.gateway.filter.ForwardPathFilter@626b639e: 0
}

觀察這些實現類。都是實現 GlobalFilter、Ordered倆個接口
實現自己的全局過濾器

創建 AuthorizeFilter

package com.xian.cloud.filter;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.HttpHeaders;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

/**
 * <Description>
 *
 * @author xianliru@100tal.com
 * @version 1.0
 * @createDate 2019/11/04 18:06
 */
@Component
@Slf4j
public class AuthorizeFilter implements GlobalFilter, Ordered {


    private static final String AUTHORIZE_TOKEN = "Authorization";
    private static final String AUTHORIZE_UID = "uid";

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {

        ServerHttpRequest request = exchange.getRequest();
        HttpHeaders headers = request.getHeaders();

        ServerHttpRequest.Builder mutate = request.mutate();

        String token = headers.getFirst( AUTHORIZE_TOKEN );
        String uid = headers.getFirst( AUTHORIZE_UID );
        String method = request.getMethodValue();

        log.info( "AuthorizeFilter token 全局過濾器 token:{},uid:{}",token,uid );
        if (token == null) {
            token = request.getQueryParams().getFirst( AUTHORIZE_TOKEN );
        }
        if(StringUtils.isNotBlank(token)){
						//TODO 權限驗證
        }

        return chain.filter( exchange );
    }

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

然后啟動服務。

curl http://localhost:9000/client/client/test
日志打印

[2019-11-05 19:30:52.802] [INFO ] com.xian.cloud.filter.AuthorizeFilter - AuthorizeFilter token 全局過濾器 token:null,uid:null

下一篇我們將介紹定制的過濾器,針對下游服務對應過濾器

摘自參考 spring cloud 官方文檔

示例代碼地址

服務器nacos 地址 http://47.99.209.72:8848/nacos

往期地址 spring cloud alibaba 地址

spring cloud alibaba 簡介

Spring Cloud Alibaba (nacos 注冊中心搭建)

Spring Cloud Alibaba 使用nacos 注冊中心

Spring Cloud Alibaba nacos 配置中心使用

spring cloud 網關服務

Spring Cloud zuul網關服務 一

Spring Cloud 網關服務 zuul 二

Spring Cloud 網關服務 zuul 三 動態路由

Spring Cloud alibaba網關 sentinel zuul 四 限流熔斷

Spring Cloud gateway 網關服務 一

如何喜歡可以關注分享本公眾號。
file

版權聲明:本文為博主原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接和本聲明。轉載請附帶公眾號二維碼


免責聲明!

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



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