Spring Cloud GateWay 路由轉(zhuǎn)發(fā)規(guī)則介紹

Spring在因Netflix開源流產(chǎn)事件后潭辈,在不斷的更換Netflix相關(guān)的組件,比如:Eureka止潮、ZuulFeign钞楼、Ribbon等喇闸,Zuul的替代產(chǎn)品就是SpringCloud Gateway,這是Spring團(tuán)隊研發(fā)的網(wǎng)關(guān)組件询件,可以實現(xiàn)限流燃乍、安全認(rèn)證、支持長連接等新特性宛琅。

Spring Cloud Gateway

Spring Cloud GatewaySpringCloud的全新子項目刻蟹,該項目基于Spring5.xSpringBoot2.x技術(shù)版本進(jìn)行編寫嘿辟,意在提供簡單方便舆瘪、可擴(kuò)展的統(tǒng)一API路由管理方式片效。
概念解釋:

  • Route(路由):路由是網(wǎng)關(guān)的基本單元,由ID英古、URI淀衣、一組Predicate、一組Filter組成召调,根據(jù)Predicate進(jìn)行匹配轉(zhuǎn)發(fā)膨桥。
  • Predicate(謂語、斷言):路由轉(zhuǎn)發(fā)的判斷條件唠叛,目前SpringCloud Gateway支持多種方式只嚣,常見如:PathQuery艺沼、Method册舞、Header等。
  • Filter(過濾器):過濾器是路由轉(zhuǎn)發(fā)請求時所經(jīng)過的過濾邏輯澳厢,可用于修改請求环础、響應(yīng)內(nèi)容。

Spring Cloud GateWay 工作流程如下所示

spring-cloud-gateway-work.png

客戶端向Spring Cloud Gateway發(fā)出請求剩拢。如果網(wǎng)關(guān)處理程序映射確定請求與路由匹配线得,則將其發(fā)送到網(wǎng)關(guān)Web處理程序。此處理程序運行時通過特定于請求的篩選鏈發(fā)送請求徐伐。過濾器被虛線分隔的原因是過濾器可以在發(fā)送代理請求之前或之后執(zhí)行邏輯贯钩。執(zhí)行所有“預(yù)”過濾邏輯,然后發(fā)出代理請求办素。在發(fā)出代理請求后角雷,將執(zhí)行“post”過濾器邏輯。

開始使用

Spring Cloud Gateway目前有兩種方式進(jìn)行配置:

  • application.yml配置文件方式
  • 通過@Bean注解RouteLocator方法返回值

在本章會側(cè)重針對配置文件方式進(jìn)行講解性穿,當(dāng)然RouteLocator方式也會簡單的告訴大家的使用方式勺三。

添加依賴

添加Spring Cloud Gateway相關(guān)依賴,pom.xml如下所示:

//...省略部分內(nèi)容
<properties>
        <java.version>1.8</java.version>
        <spring-cloud.version>Greenwich.SR1</spring-cloud.version>
    </properties>

    <dependencies>
        <!--Spring Cloud Gateway-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
//...省略部分內(nèi)容

Spring Cloud Gateway Predicates

在我們開始本章內(nèi)容之前我們要來先了解下Spring Cloud Gateway內(nèi)部提供的所有謂語需曾、斷言吗坚,這樣我們才能目標(biāo)性的進(jìn)行學(xué)習(xí),我整理出來了一個腦圖呆万,如下所示:

SpringCloud-Gateway-Predicates.png

每一個Predicate的使用商源,你可以理解為:當(dāng)滿足這種條件后才會被轉(zhuǎn)發(fā),如果是多個谋减,那就是都滿足的情況下被轉(zhuǎn)發(fā)牡彻。

Path 方式匹配轉(zhuǎn)發(fā)

通過Path轉(zhuǎn)發(fā)示例,我們講解下上面的兩種配置出爹,分別是application.yml以及RouteLocator庄吼。

配置文件匹配地址轉(zhuǎn)發(fā)

我們在application.yml配置文件內(nèi)添加對應(yīng)的路由配置缎除,如下所示:

spring:
  application:
    name: spring-cloud-gateway-sample
  cloud:
    gateway:
      routes:
        - id: blog
          uri: http://blog.yuqiyu.com
          predicates:
            # 匹配路徑轉(zhuǎn)發(fā)
            - Path=/api-boot-datasource-switch.html
# 端口號
server:
  port: 9090

先來解釋下route的組成部分:

  • id:路由的ID
  • uri:匹配路由的轉(zhuǎn)發(fā)地址
  • predicates:配置該路由的斷言,通過PredicateDefinition類進(jìn)行接收配置总寻。

在上面的配置中伴找,當(dāng)訪問http://localhost:9090/api-boot-datasource-switch.html時就會被自動轉(zhuǎn)發(fā)到http://blog.yuqiyu.com/api-boot-datasource-switch.html,這里要注意完全匹配Path的值時才會進(jìn)行路由轉(zhuǎn)發(fā)废菱。

訪問效果如下所示:

spring-cloud-gateway-path-predicate.png

RouteLocator 匹配路徑轉(zhuǎn)發(fā)

在上面的配置中,如果使用RouteLocator方式該怎么進(jìn)行配置呢抖誉?

如下所示:

@Bean
public RouteLocator routeLocator(RouteLocatorBuilder builder) {
  return builder.routes()
    .route("blog", r -> 
           r.path("/api-boot-datasource-switch.html").uri("http://blog.yuqiyu.com"))
    .build();
}

Before 方式匹配轉(zhuǎn)發(fā)

當(dāng)部署有訪問時間限制的接口時殊轴,我們可以通過Before Predicate來完成某一個時間點之前允許訪問,過時后則不允許轉(zhuǎn)發(fā)請求到具體的服務(wù)袒炉,配置如下所示:

spring:
  cloud:
    gateway:
      routes:
        - id: blog
          uri: http://blog.yuqiyu.com
          predicates:
            - Before=2019-05-01T00:00:00+08:00[Asia/Shanghai]

在上面配置中旁理,我們允許2019-05-01日凌晨之前通過路由轉(zhuǎn)發(fā)到http://blog.yuqiyu.com,通過查看org.springframework.cloud.gateway.handler.predicate.BeforeRoutePredicateFactory源碼我們發(fā)現(xiàn)我磁,Spring Cloud GatewayBefore斷言采用的ZonedDateTime進(jìn)行匹配時間孽文,這里要注意存在時區(qū)的問題,需要配置[Asia/Shanghai]作為中國時區(qū)夺艰。

After 方式匹配轉(zhuǎn)發(fā)

After PredicateBefore配置使用一致芋哭,匹配某一個時間點之后允許路由轉(zhuǎn)發(fā),如下所示配置:

spring:
  cloud:
    gateway:
      routes:
        - id: blog
          uri: http://blog.yuqiyu.com
          predicates:
            - After=2019-04-29T00:00:00+08:00[Asia/Shanghai]

在上面配置中允許2019-04-29凌晨之后進(jìn)行轉(zhuǎn)發(fā)到http://blog.yuqiyu.com郁副。

Between 方式匹配轉(zhuǎn)發(fā)

那如果是一個時間段內(nèi)允許請求轉(zhuǎn)發(fā)减牺,通過BeforeAfter組合配置也可以完成存谎,不過Spring Cloud Gateway還是提供了Between方式拔疚,如下所示:

spring:
  cloud:
    gateway:
      routes:
        - id: blog
          uri: http://blog.yuqiyu.com
          predicates:
            - Between=2019-04-29T00:00:00+08:00[Asia/Shanghai], 2019-05-01T00:00:00+08:00[Asia/Shanghai]

在上面配置中,允許在2019-04-29日凌晨后 & 2019-05-01凌晨之前請求轉(zhuǎn)發(fā)到http://blog.yuqiyu.com既荚。

Cookie 方式匹配轉(zhuǎn)發(fā)

Spring Cloud Gateway 還提供了根據(jù)Cookie值的方式匹配轉(zhuǎn)發(fā)請求稚失,如果請求中所攜帶的Cookie值與配置的Predicate匹配,那么就可以被允許轉(zhuǎn)發(fā)到指定地址恰聘,如下所示:

spring:
  cloud:
    gateway:
      routes:
        - id: blog
          uri: http://blog.yuqiyu.com
          predicates:
            - Cookie=hengboy, yuqiyu

在上面配置中句各,如果客戶端發(fā)送請求時攜帶了"hengboy=yuqiyu"的Cookie信息,則允許請求轉(zhuǎn)發(fā)憨琳。

測試Cookie方式轉(zhuǎn)發(fā):

curl http://localhost:9090 --cookie "hengboy=yuqiyu"

通過上面方式我們是可以成功轉(zhuǎn)發(fā)請求的诫钓,如果我們修改Cookie的值,就會導(dǎo)致無法轉(zhuǎn)發(fā)篙螟,出現(xiàn)404菌湃。

Header 方式匹配轉(zhuǎn)發(fā)

Spring Cloud Gateway可以根據(jù)發(fā)送請求的Header信息進(jìn)行匹配轉(zhuǎn)發(fā),加入我們可以根據(jù)X-Request-Id的值進(jìn)行匹配遍略,如下所示:

spring:
  cloud:
    gateway:
      routes:
        - id: blog
          uri: http://blog.yuqiyu.com
          predicates:
            - Header=X-Request-Id, \d+

在上面配置中惧所,如果X-Request-Id的值為數(shù)字骤坐,那么就可以轉(zhuǎn)發(fā)到http://blog.yuqiyu.com,我們通過如下方式進(jìn)行測試:

curl http://localhost:9090 -H "X-Request-Id:123456"

如果頭信息為X-Request-Id:abc時下愈,就會轉(zhuǎn)發(fā)失敗纽绍,出現(xiàn)404。

Host 方式匹配轉(zhuǎn)發(fā)

Spring Cloud Gateway可以根據(jù)Host主機(jī)名進(jìn)行匹配轉(zhuǎn)發(fā)势似,如果我們的接口只允許**.yuqiyu.com域名進(jìn)行訪問拌夏,那么配置如下所示:

spring:
  cloud:
    gateway:
      routes:
        - id: blog
          uri: http://blog.yuqiyu.com
          predicates:
            - Host=**.yuqiyu.com

測試如下所示:

 1. curl http://localhost:9090 -H "Host: yuqiyu.com"        // 匹配
 2. curl http://localhost:9090 -H "Host: api.yuqiyu.com"        // 匹配
 3. curl http://localhost:9090 -H "Host: admin.yuqiyu.com"  // 匹配
 3. curl http://localhost:9090 -H "Host: hengboy.com"       // 不匹配

請求方式 方式匹配轉(zhuǎn)發(fā)

Rest請求風(fēng)格的接口內(nèi)往往會存在多種請求方式的接口,如果我們的接口只允許POST請求訪問履因,那么配置如下所示:

spring:
  cloud:
    gateway:
      routes:
        - id: blog
          uri: http://blog.yuqiyu.com
          predicates:
            - Method=POST

發(fā)送GET請求測試:

~ curl http://localhost:9090
{"timestamp":"2019-04-29T06:27:41.121+0000","path":"/","status":404,"error":"Not Found","message":null}

我們的請求并未被Spring Cloud Gateway進(jìn)行轉(zhuǎn)發(fā)障簿,那么我們再來通過POST請求進(jìn)行測試:

curl -X POST http://localhost:9090

是可以被轉(zhuǎn)發(fā)到目標(biāo)地址uri的,不過我的這個博客是OSS部署的栅迄,阿里云限制了POST訪問站故,盡管如此我們也證明了可以轉(zhuǎn)發(fā)。

請求參數(shù) 方式匹配轉(zhuǎn)發(fā)

Spring Cloud GateWay還支持根據(jù)指定的參數(shù)進(jìn)行匹配毅舆,Query方式的Predicate也有兩種方式匹配情況西篓,如下所示:

  • 請求中存在xxx參數(shù)

    spring:
      cloud:
        gateway:
          routes:
            - id: blog
              uri: http://blog.yuqiyu.com
              predicates:
                - Query=xxx
    

    我們通過curl http://localhost:9090\?xxx\=123是可以被成功轉(zhuǎn)發(fā)的,只要參數(shù)存在xxx就會被成功轉(zhuǎn)發(fā)憋活,否則出現(xiàn)404轉(zhuǎn)發(fā)失敗岂津。

  • 請求中存在xxx參數(shù)且值為zzz

    spring:
      cloud:
        gateway:
          routes:
            - id: blog
              uri: http://blog.yuqiyu.com
              predicates:
                - Query=xxx, zzz
    

    根據(jù)上面配置,我們限定了參數(shù)xxx必須為zzz時才會被成功轉(zhuǎn)發(fā)余掖,否則同樣會出現(xiàn)404抓發(fā)失敗寸爆。

請求路徑 方式匹配轉(zhuǎn)發(fā)

Spring Cloud Gateway提供了請求路徑變量方式匹配轉(zhuǎn)發(fā),如下所示:

spring:
  cloud:
    gateway:
      routes:
        - id: blog
          uri: http://blog.yuqiyu.com
          predicates:
            - Path=/article/{articleId}

在上面配置中{articleId}是一個路徑變量盐欺,可以是任意值赁豆,匹配/article/1/article/abc等冗美,測試如下所示:

~ curl http://localhost:9090/article/1          // 匹配
~ curl http://localhost:9090/article/abc        // 匹配
~ curl http://localhost:9090/article/1/1        // 不匹配

請求IP 方式匹配轉(zhuǎn)發(fā)

Spring Cloud Gateway可以限制允許訪問接口的客戶端IP地址魔种,配置后只對指定IP地址的客戶端進(jìn)行請求轉(zhuǎn)發(fā),配置如下所示:

spring:
  cloud:
    gateway:
      routes:
        - id: blog
          uri: http://blog.yuqiyu.com
          predicates:
            - RemoteAddr=192.168.1.56/24

在上面我們配置了192.168.1.56/24粉洼,其中192.168.1.56是客戶端的IP地址节预,而24則是子網(wǎng)掩碼。

組合示例

相同的Predicate也可以配置多個属韧,請求的轉(zhuǎn)發(fā)是必須滿足所有的Predicate后才可以進(jìn)行路由轉(zhuǎn)發(fā)安拟,組合使用示例如下所示:

spring:
  cloud:
    gateway:
      routes:
        - id: blog
          uri: http://blog.yuqiyu.com
          predicates:
            - Query=author, hengboy
            - Query=yuqiyu
            - Method=GET
            - Cookie=hengboy, yuqiyu
            - Header=X-Request-Id, \d+
            - RemoteAddr=192.168.1.56/24

總結(jié)

本章節(jié)講解了Spring Cloud Gateway的相關(guān)謂詞、斷言基本使用方式宵喂,GateWay內(nèi)部提供了很多種靈活的路由轉(zhuǎn)發(fā)規(guī)則糠赦,在同一個路由內(nèi)存在多個Predicate時,同時滿足規(guī)則后請求才會被路由轉(zhuǎn)發(fā)。

源碼位置

Giteehttps://gitee.com/hengboy/spring-cloud-chapter/tree/master/SpringCloud/spring-cloud-gateway

作者個人 博客
使用開源框架 ApiBoot 助你成為Api接口服務(wù)架構(gòu)師

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末拙泽,一起剝皮案震驚了整個濱河市淌山,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌顾瞻,老刑警劉巖泼疑,帶你破解...
    沈念sama閱讀 216,372評論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異荷荤,居然都是意外死亡退渗,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評論 3 392
  • 文/潘曉璐 我一進(jìn)店門蕴纳,熙熙樓的掌柜王于貴愁眉苦臉地迎上來氓辣,“玉大人,你說我怎么就攤上這事袱蚓。” “怎么了几蜻?”我有些...
    開封第一講書人閱讀 162,415評論 0 353
  • 文/不壞的土叔 我叫張陵喇潘,是天一觀的道長。 經(jīng)常有香客問我梭稚,道長颖低,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,157評論 1 292
  • 正文 為了忘掉前任弧烤,我火速辦了婚禮忱屑,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘暇昂。我一直安慰自己莺戒,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,171評論 6 388
  • 文/花漫 我一把揭開白布急波。 她就那樣靜靜地躺著从铲,像睡著了一般。 火紅的嫁衣襯著肌膚如雪澄暮。 梳的紋絲不亂的頭發(fā)上名段,一...
    開封第一講書人閱讀 51,125評論 1 297
  • 那天,我揣著相機(jī)與錄音泣懊,去河邊找鬼伸辟。 笑死,一個胖子當(dāng)著我的面吹牛馍刮,可吹牛的內(nèi)容都是我干的信夫。 我是一名探鬼主播,決...
    沈念sama閱讀 40,028評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼忙迁!你這毒婦竟也來了脐彩?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,887評論 0 274
  • 序言:老撾萬榮一對情侶失蹤姊扔,失蹤者是張志新(化名)和其女友劉穎惠奸,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體恰梢,經(jīng)...
    沈念sama閱讀 45,310評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡佛南,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,533評論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了嵌言。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片嗅回。...
    茶點故事閱讀 39,690評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖摧茴,靈堂內(nèi)的尸體忽然破棺而出绵载,到底是詐尸還是另有隱情,我是刑警寧澤苛白,帶...
    沈念sama閱讀 35,411評論 5 343
  • 正文 年R本政府宣布娃豹,位于F島的核電站,受9級特大地震影響购裙,放射性物質(zhì)發(fā)生泄漏懂版。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,004評論 3 325
  • 文/蒙蒙 一躏率、第九天 我趴在偏房一處隱蔽的房頂上張望躯畴。 院中可真熱鬧,春花似錦薇芝、人聲如沸蓬抄。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽倡鲸。三九已至,卻和暖如春黄娘,著一層夾襖步出監(jiān)牢的瞬間峭状,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,812評論 1 268
  • 我被黑心中介騙來泰國打工逼争, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留优床,地道東北人。 一個月前我還...
    沈念sama閱讀 47,693評論 2 368
  • 正文 我出身青樓誓焦,卻偏偏與公主長得像胆敞,于是被迫代替她去往敵國和親着帽。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,577評論 2 353