溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

怎么理解Spring Cloud Gateway Filters的執(zhí)行順序

發(fā)布時(shí)間:2021-10-20 09:38:09 來(lái)源:億速云 閱讀:393 作者:柒染 欄目:大數(shù)據(jù)

這篇文章給大家介紹怎么理解Spring Cloud Gateway Filters的執(zhí)行順序,內(nèi)容非常詳細(xì),感興趣的小伙伴們可以參考借鑒,希望對(duì)大家能有所幫助。

基于Spring Cloud Gateway 2.1.1.RELEASE。

在講SCG的Filter的排序問(wèn)題之前得先比較一下Spring Cloud Gateway在對(duì)待Filter的方面與Zuul2有著哪些不同。

Filter的Scope

  • SCG采用的是Global Filter和Route Filter相結(jié)合的方式

  • Zuul2則都是Global Filter

SCG所謂Route Filter就是像下面這樣的:

spring:
  cloud:
    gateway:
      routes:
        - id: tomcat_route
          uri: http://tomcat:8080
          predicates:
            - Path=/tomcat/docs
          filters:
            - StripPrefix=1
            - RemoveRequestHeader=X-Request-Foo

上面的StripPrefixRemoveRequestHeader就是Route Filter,而SCG的Global Filter則是隱式的,無(wú)需顯式配置,它們會(huì)在請(qǐng)求過(guò)來(lái)的時(shí)候被SCG調(diào)用。

也就是說(shuō)你可以配置不同的Route,然后為每個(gè)Route配置不同的Route Filter,這一切都是在配置階段就決定下來(lái)的。

而Zuul2則都是Global Filter,因此你得運(yùn)行時(shí)在每個(gè)Filter內(nèi)部自己決定是否要干活,除此之外,發(fā)送到Origin(被代理的服務(wù))的url也得你自己設(shè)置,下面是一個(gè)例子(來(lái)自Zuul2 Sample):

public class Routes extends HttpInboundSyncFilter {
  @Override
  public boolean shouldFilter(HttpRequestMessage httpRequestMessage) {
    // ...
    return true;
  }
  @Override
  public HttpRequestMessage apply(HttpRequestMessage request) {
    // ...
    // Route healthchecks to the healthcheck endpoint.;
    context.setEndpoint(ZuulEndPointRunner.PROXY_ENDPOINT_FILTER_NAME);
    context.setRouteVIP("tomcat");

    return request;
  }
}

Filter的角色

  • 在SCG概念中只有一種Filter(撇開(kāi)Global和Route的區(qū)別),它用代碼來(lái)區(qū)分Pre Filter、Post Filter。在文檔中還提到了Routing Filter,其實(shí)也是Pre Filter。

  • Zuul2在代碼中顯示得提供了InboundFilter(負(fù)責(zé)進(jìn)來(lái)的請(qǐng)求)、OutboundFilter(負(fù)責(zé)出去的響應(yīng))、ProxyEndpoint(負(fù)責(zé)請(qǐng)求到Origin,串起Inbound和Outbound)。

下面是SCG的Pre Filter(裁剪自官方例子12.2 Writing Custom GatewayFilter Factories):

public class PreGatewayFilterFactory extends AbstractGatewayFilterFactory {
    @Override
    public GatewayFilter apply(Config config) {
        return (exchange, chain) -> {
            // business logic
            return chain.filter();
        };
    }
}

Post Filter的例子:

public class PostGatewayFilterFactory extends AbstractGatewayFilterFactory {
    @Override
    public GatewayFilter apply(Config config) {
        return (exchange, chain) -> {
            return chain.filter(exchange).then(/* business logic */);
        };
    }
}

在Zuul2里,你則得分別實(shí)現(xiàn)HttpInboundSyncFilterHttpOutboundSyncFilterProxyEndpoint不需要你自己實(shí)現(xiàn)。

SCG Filter的問(wèn)題

SCG的優(yōu)點(diǎn)很明顯,它做了Zuul2不做的事情:

  1. 替你決定進(jìn)來(lái)的請(qǐng)求轉(zhuǎn)發(fā)到哪個(gè)Origin。在Zuul2里這個(gè)交給你自己來(lái)實(shí)現(xiàn)。

  2. 在配置上就決定了這個(gè)Route會(huì)應(yīng)用哪些Filter。在Zuul2里這個(gè)交給你自己來(lái)判斷。

但是隨著對(duì)SCG的深入了解,發(fā)現(xiàn)了關(guān)于Filter的執(zhí)行順序存在一些坑,如果不了解清楚會(huì)容易出錯(cuò)。

Filter的排序

前面講了,SCG在執(zhí)行過(guò)程中Global Filter和Route Filter是一起執(zhí)行的,那么它們的order是怎樣的?

先來(lái)看看Global Filter,你可以訪問(wèn)/actuator/gateway/globalfilters(見(jiàn)文檔)得到Global Filter的排序:

怎么理解Spring Cloud Gateway Filters的執(zhí)行順序

那么如果你寫(xiě)了一個(gè)自定義 Global Filter,那么它的order是什么呢?這個(gè)要看情況:

  • 如果你的自定義Global Filter實(shí)現(xiàn)了Ordered接口或者寫(xiě)了@Order注解,那么它的order就是它自己設(shè)定的值

  • 否則,它就沒(méi)有order

關(guān)于這點(diǎn)可以看FilteringWebHandler.java的源代碼。

再來(lái)看看Route Filter,這也分兩種情況:

  • 如果RouteFilter實(shí)現(xiàn)了Ordered接口或者寫(xiě)了@Order注解,那么它的order就是它自己設(shè)定的值。

  • 否則,它的order則是從1開(kāi)始,按照Route中定義的順序依次排序。

關(guān)于這點(diǎn)可以看RouteDefinitionRouteLocator.java的源代碼。

最后SCG把它們兩個(gè)結(jié)合起來(lái),做一個(gè)排序,對(duì)于沒(méi)有order的Filter,它的order則默認(rèn)為Ordered.LOWEST_PRECEDENCE。關(guān)于這點(diǎn)可以看FilteringWebHandler.java的源代碼。

用一張圖做總結(jié):

怎么理解Spring Cloud Gateway Filters的執(zhí)行順序

Filter的執(zhí)行順序

先看SCG文檔3. How It Works中的這張圖:

怎么理解Spring Cloud Gateway Filters的執(zhí)行順序

這張圖大概告訴你了SCG的調(diào)用過(guò)程,可以看到經(jīng)過(guò)了一堆Filters,但是并沒(méi)有告訴你Filter的執(zhí)行順序。然后在SCG的6.1 Combined Global Filter and GatewayFilter Ordering提到了:

As Spring Cloud Gateway distinguishes between "pre">

也就是說(shuō)意思如果這個(gè)Filter是Pre Filter,那么執(zhí)行順序和排序順序相同,如果這個(gè)Filter是Post Filter則執(zhí)行順序和排序順序相反。我整理了一下SCG自帶GlobalFilter的執(zhí)行順序:

怎么理解Spring Cloud Gateway Filters的執(zhí)行順序

可以看到GatewayMetricsFilter既是Pre Filter也是Post Filter。

總結(jié)

  • 執(zhí)行某個(gè)Route的時(shí)候,SCG會(huì)將Global Filter和Route Filter結(jié)合起來(lái)并排序:

    • 沒(méi)有給order的Global Filter則保持order為null去排序

    • 沒(méi)有給order的Route Filter的order則從1開(kāi)始,根據(jù)Route中定義的順序給值

    • 排序邏輯見(jiàn)AnnotationAwareOrderComparator

  • 對(duì)于Pre Filter,執(zhí)行順序同排序順序

  • 對(duì)于Post Filter,執(zhí)行順序與排序順序相反

  • 如果你要自定義Global Filter,那么一般來(lái)說(shuō):

    • 自定義的Global Pre Filter要在Routing Filter之前執(zhí)行

    • 自定義的Global Post Filter要在Routing Filter之后執(zhí)行或者NettyWriteResponseFilter之后執(zhí)行

  • 如果你要自定義Route Filter,那么一般來(lái)說(shuō):

    • 自定義Route Pre Filter要在ForwardPathFilterRouteToRequestUrlFilter之間,而且不需要實(shí)現(xiàn)Ordered接口或添加@Order注解

    • 自定義的Route Post Filter比較少見(jiàn),放在Routing Filter或者NettyWriteResponseFilter之后執(zhí)行

關(guān)于怎么理解Spring Cloud Gateway Filters的執(zhí)行順序就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,可以學(xué)到更多知識(shí)。如果覺(jué)得文章不錯(cuò),可以把它分享出去讓更多的人看到。

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI