spring cloud gateway系列教程2——GatewayFilter_下篇

spring cloud gateway系列教程目錄

  1. spring cloud gateway系列教程1—Route Predicate
  2. spring cloud gateway系列教程2——GatewayFilter_上篇
  3. spring cloud gateway系列教程2——GatewayFilter_下篇
  4. spring cloud gateway系列教程3—Global Filters
  5. spring cloud gateway系列教程4—其他配置

上篇

8. RequestRateLimiter GatewayFilter Factory

RequestRateLimiter GatewayFilter Factory使用RateLimiter來決定當前請求是否允許通過,如果不允許,則默認返回狀態碼HTTP 429 - Too Many Requests

RequestRateLimiter GatewayFilter可以使用一個可選參數keyResolver來做速率限制。

keyResolverKeyResolver接口的一個實現bean,在配置里面,通過SpEL表達式#{@myKeyResolver}來管理bean的名字myKeyResolver

KeyResolver.java.

public interface KeyResolver {
    Mono<String> resolve(ServerWebExchange exchange);
}

KeyResolver接口允許你使用不同的策略來得出限制請求的key,未來,官方也會推出一些KeyResolver的不同實現。

KeyResolver默認實現是PrincipalNameKeyResolver,通過ServerWebExchange中獲取Principal,并以Principal.getName()作為限流的key。

如果KeyResolver拿不到key,請求默認都會被限制,你也可以自己配置spring.cloud.gateway.filter.request-rate-limiter.deny-empty-key:是否允許空key,spring.cloud.gateway.filter.request-rate-limiter.empty-key-status-code :空key時返回的狀態碼。

RequestRateLimiter不支持捷徑配置,如下面的配置是非法的

application.properties.

# INVALID SHORTCUT CONFIGURATION
spring.cloud.gateway.routes[0].filters[0]=RequestRateLimiter=2, 2, #{@userkeyresolver}
8.1 Redis RateLimiter

基于 Stripe的redis實現方案,依賴spring-boot-starter-data-redis-reactiveSpring Boot starter,使用的是令牌桶算法。

redis-rate-limiter.replenishRate配置的是每秒允許通過的請求數,其實就是令牌桶的填充速率。

redis-rate-limiter.burstCapacity配置的是一秒內最大的請求數,其實就是令牌桶的最大容量,如果設置為0,則會阻塞所有請求。

所以可以通過設置相同的replenishRateburstCapacity來實現勻速的速率控制,通過設置burstCapacity大于replenishRate來允許系統流量瞬間突發,但是對于這種情況,突發周期為burstCapacity / replenishRate秒,如果周期內有兩次請求突發的情況,則第二次會有部分請求丟失,返回HTTP 429 - Too Many Requests

application.yml.

spring:
  cloud:
    gateway:
      routes:
      - id: requestratelimiter_route
        uri: http://www.google.com
        filters:
        - name: RequestRateLimiter
          args:
            redis-rate-limiter.replenishRate: 10
            redis-rate-limiter.burstCapacity: 20

Config.java.

@Bean
KeyResolver userKeyResolver() {
    return exchange -> Mono.just(exchange.getRequest().getQueryParams().getFirst("user"));
}

上面定義了每個用戶每秒10個請求的速率限制,允許20的突發流量,突發完,下一秒只允許10個請求通過了,KeyResolver定義了通過請求獲取請求參數user作為key。

你也可以實現RateLimiter接口自定義自己的請求速率限制器,在配置文件中使用SpEL表達式配置對應的bean的名字即可。

application.yml.

spring:
  cloud:
    gateway:
      routes:
      - id: requestratelimiter_route
        uri: http://www.google.com
        filters:
        - name: RequestRateLimiter
          args:
            rate-limiter: "#{@myRateLimiter}"
            key-resolver: "#{@userKeyResolver}"

9. RedirectTo GatewayFilter Factory

RedirectTo GatewayFilter Factory使用statusurl兩個參數,其中status必須是300系列的HTTP狀態碼,url則是跳轉的地址,會放在響應的Location的header中(http協議中轉跳的header)。

application.yml.

spring:
  cloud:
    gateway:
      routes:
      - id: prefixpath_route
        uri: http://www.google.cn
        filters:
        - RedirectTo=302, http://www.edjdhbb.com

上面路由會執行302重定向到http://www.edjdhbb.com

10. RemoveNonProxyHeaders GatewayFilter Factory

RemoveNonProxyHeaders GatewayFilter Factory轉發請求是會根據IETF的定義,默認會移除下列的http頭信息:

  • Connection
  • Keep-Alive
  • Proxy-Authenticate
  • Proxy-Authorization
  • TE
  • Trailer
  • Transfer-Encoding
  • Upgrade

你也可以通過配置spring.cloud.gateway.filter.remove-non-proxy-headers.headers來更改需要移除的header列表。

11. RemoveRequestHeader GatewayFilter Factory

RemoveRequestHeader GatewayFilter Factory配置header的name,即可以移除請求的header。

application.yml.

spring:
  cloud:
    gateway:
      routes:
      - id: removerequestheader_route
        uri: http://www.google.com
        filters:
        - RemoveRequestHeader=X-Request-Foo

上面路由在發送請求給下游時,會將請求中的X-Request-Foo頭信息去掉。

12. RemoveResponseHeader GatewayFilter Factory

RemoveResponseHeader GatewayFilter Factory通過配置header的name,會在響應返回時移除header。

application.yml.

spring:
  cloud:
    gateway:
      routes:
      - id: removeresponseheader_route
        uri: http://www.google.com
        filters:
        - RemoveResponseHeader=X-Response-Foo

上面路由會在響應返回給gateway的客戶端時,將X-Response-Foo響應頭信息去掉。

13. RewritePath GatewayFilter Factory

RewritePath GatewayFilter Factory使用路徑regexp和替換路徑replacement兩個參數做路徑重寫,兩個都可以靈活地使用java的正則表達式。

application.yml.

spring:
  cloud:
    gateway:
      routes:
      - id: rewritepath_route
        uri: http://www.google.com
        predicates:
        - Path=/foo/**
        filters:
        - RewritePath=/foo/(?<segment>.*), /$\{segment}

對于上面的例子,如果請求的路徑是/foo/bar,則gateway會將請求路徑改為/bar發送給下游。

注:在YAML 的格式中使用$\來代替$

14. RewriteResponseHeader GatewayFilter Factory

RewriteResponseHeader GatewayFilter Factory的作用是修改響應返回的header內容,需要配置響應返回的header的name,匹配規則regexp和替換詞replacement,也是支持java的正則表達式。

application.yml.

spring:
  cloud:
    gateway:
      routes:
      - id: rewriteresponseheader_route
        uri: http://www.google.com
        filters:
        - RewriteResponseHeader=X-Response-Foo, , password=[^&]+, password=***

舉個例子,對于上面的filter,如果響應的headerX-Response-Foo的內容是/42?user=ford&password=omg!what&flag=true,這個內容會修改為/42?user=ford&password=***&flag=true

15. SaveSession GatewayFilter Factory

SaveSession GatewayFilter Factory會在請求下游時強制執行WebSession::save方法,用在那種像Spring Session延遲數據存儲的,并在請求轉發前確保session狀態保存情況。

application.yml.

spring:
  cloud:
    gateway:
      routes:
      - id: save_session
        uri: http://www.google.com
        predicates:
        - Path=/foo/**
        filters:
        - SaveSession

如果你將Spring SecutirySpring Session集成使用,并想確保安全信息都傳到下游機器,你就需要配置這個filter。

16. SecureHeaders GatewayFilter Factory

SecureHeaders GatewayFilter Factory會添加在返回響應中一系列安全作用的header,至于為什么,英文好的可以看一下這篇博客

默認會添加這些頭信息和默認內容:

  • X-Xss-Protection:1; mode=block
  • Strict-Transport-Security:max-age=631138519
  • X-Frame-Options:DENY
  • X-Content-Type-Options:nosniff
  • Referrer-Policy:no-referrer
  • Content-Security-Policy:default-src 'self' https:; font-src 'self' https: data:; img-src 'self' https: data:; object-src 'none'; script-src https:; style-src 'self' https: 'unsafe-inline'
  • X-Download-Options:noopen
  • X-Permitted-Cross-Domain-Policies:none

如果你想修改這些頭信息的默認內容,可以在配置文件中添加下面的配置:

前綴:spring.cloud.gateway.filter.secure-headers

上面的header對應的后綴:

  • xss-protection-header
  • strict-transport-security
  • frame-options
  • content-type-options
  • referrer-policy
  • content-security-policy
  • download-options
  • permitted-cross-domain-policies

前后綴接起來即可,如:spring.cloud.gateway.filter.secure-headers.xss-protection-header

17. SetPath GatewayFilter Factory

SetPath GatewayFilter Factory采用路徑template參數,通過請求路徑的片段的模板化,來達到操作修改路徑的母的,運行多個路徑片段模板化。

application.yml.

spring:
  cloud:
    gateway:
      routes:
      - id: setpath_route
        uri: http://www.google.com
        predicates:
        - Path=/foo/{segment}
        filters:
        - SetPath=/{segment}

對于上面的例子,如果路徑是/foo/bar,則對于下游的請求路徑會修改為/bar

18. SetResponseHeader GatewayFilter Factory

SetResponseHeader GatewayFilter Factory通過設置namevalue來替換響應對于的header。

application.yml.

spring:
  cloud:
    gateway:
      routes:
      - id: setresponseheader_route
        uri: http://www.google.com
        filters:
        - SetResponseHeader=X-Response-Foo, Bar

對于上面的例子,如果下游的返回帶有頭信息為X-Response-Foo:1234,則會gateway會替換為X-Response-Foo:Bar,在返回給客戶端。

19. SetStatus GatewayFilter Factory

SetStatus GatewayFilter Factory通過配置有效的Spring HttpStatus枚舉參數,可以是類似于404的這些數字,也可以是枚舉的name字符串,來修改響應的返回碼。

application.yml.

spring:
  cloud:
    gateway:
      routes:
      - id: setstatusstring_route
        uri: http://www.google.com
        filters:
        - SetStatus=BAD_REQUEST
      - id: setstatusint_route
        uri: http://www.google.com
        filters:
        - SetStatus=401

上面例子中,兩種路由都會將響應的狀態碼設置為401。

20. StripPrefix GatewayFilter Factory

StripPrefix GatewayFilter Factory通過配置parts來表示截斷路徑前綴的數量。

application.yml.

spring:
  cloud:
    gateway:
      routes:
      - id: nameRoot
        uri: http://nameservice
        predicates:
        - Path=/name/**
        filters:
        - StripPrefix=2

如上面例子中,如果請求的路徑為/name/bar/foo,則路徑會修改為/foo,即將路徑的兩個前綴去掉了。

21. Retry GatewayFilter Factory

Retry GatewayFilter Factory可以配置針對不同的響應做請求重試,可以配置如下參數:

  • retries: 重試次數
  • statuses: 需要重試的狀態碼,需要根據枚舉 org.springframework.http.HttpStatus來配置
  • methods: 需要重試的請求方法,需要根據枚舉org.springframework.http.HttpMethod來配置
  • series: HTTP狀態碼系列,詳情見枚舉org.springframework.http.HttpStatus.Series

application.yml.

spring:
  cloud:
    gateway:
      routes:
      - id: retry_test
        uri: http://localhost:8080/flakey
        predicates:
        - Host=*.retry.com
        filters:
        - name: Retry
          args:
            retries: 3
            statuses: BAD_GATEWAY

上面例子,當下游服務返回502狀態碼時,gateway會重試3次。

22. RequestSize GatewayFilter Factory

RequestSize GatewayFilter Factory會限制客戶端請求包的大小,通過參數RequestSize來配置最大上傳大小,單位字節。

application.yml.

spring:
  cloud:
    gateway:
      routes:
      - id: request_size_route
      uri: http://localhost:8080/upload
      predicates:
      - Path=/upload
      filters:
      - name: RequestSize
        args:
          maxSize: 5000000

如果請求大小超過5000kb限制,則會返回狀態碼413 Payload Too Large

如果不設置這個filter,默認限制5M的請求大小。

23. Modify Request Body GatewayFilter Factory

官方說這個filter目前只是beta版本,API以后可能會修改。

Modify Request Body GatewayFilter Factory可以修改請求體內容,這個只能通過java來配置。

@Bean
public RouteLocator routes(RouteLocatorBuilder builder) {
    return builder.routes()
        .route("rewrite_request_obj", r -> r.host("*.rewriterequestobj.org")
            .filters(f -> f.prefixPath("/httpbin")
                .modifyRequestBody(String.class, Hello.class, MediaType.APPLICATION_JSON_VALUE,
                    (exchange, s) -> return Mono.just(new Hello(s.toUpperCase())))).uri(uri))
        .build();
}

static class Hello {
    String message;

    public Hello() { }

    public Hello(String message) {
        this.message = message;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }
}

24. Modify Response Body GatewayFilter Factory

官方說這個filter目前只是beta版本,API以后可能會修改。

Modify Response Body GatewayFilter Factory用于修改響應返回的內容,同樣只能通過java配置。

@Bean
public RouteLocator routes(RouteLocatorBuilder builder) {
    return builder.routes()
        .route("rewrite_response_upper", r -> r.host("*.rewriteresponseupper.org")
            .filters(f -> f.prefixPath("/httpbin")
                .modifyResponseBody(String.class, String.class,
                    (exchange, s) -> Mono.just(s.toUpperCase()))).uri(uri)
        .build();
}

這一章接著上一章介紹了Spring Cloud Gateway官方的Gateway Filter使用場景,下一章講Global Filters的使用

如果想查看其他spring cloud gateway的案例和使用,可以點擊查看

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,908評論 6 541
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,324評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,018評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,675評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,417評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,783評論 1 329
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,779評論 3 446
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,960評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,522評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,267評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,471評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,009評論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,698評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,099評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,386評論 1 294
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,204評論 3 398
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,436評論 2 378

推薦閱讀更多精彩內容