Spring Cloud構(gòu)建微服務(wù)架構(gòu)(五)服務(wù)網(wǎng)關(guān)

由于Zuul 2.x的不斷跳票矿辽,Spring Cloud自行研發(fā)了另外一款服務(wù)網(wǎng)關(guān)產(chǎn)品:Spring Cloud Gateway骏全,并且在最新版本中推薦使用枪芒,所以Gateway出現(xiàn)的原因就是為了代替Zuul掷邦。相比Zuul猪狈,Gateway是Spring體系內(nèi)的產(chǎn)物抛蚁,和Spring融合更好陈醒。同時(shí)相比于Zuul 1.x的阻塞和多線程方式,Gateway采用了Netty異步非阻塞模型篮绿,占用資源更小孵延,性能更有優(yōu)勢(shì)。同時(shí)增加了Predicate和限流等功能亲配。

1 傳統(tǒng)路由方式

創(chuàng)建一個(gè)Spring Boot項(xiàng)目尘应,命名為api-gateway。

1.1 pom.xml

<?xml version="1.0" encoding="UTF-8"?>4.0.0org.springframework.bootspring-boot-starter-parent2.1.7.RELEASE<!-- lookup parent from repository -->com.hysapi-gateway0.0.1-SNAPSHOTapi-gatewayDemo project for Spring Cloud 1.8Greenwich.SR2 org.springframework.cloudspring-cloud-starter-gatewayorg.springframework.bootspring-boot-starter-testtest org.springframework.cloudspring-cloud-dependencies${spring-cloud.version}pomimport org.springframework.bootspring-boot-maven-plugin

1.2 啟動(dòng)類(lèi)

packagecom.hys.apigateway; importorg.springframework.boot.SpringApplication;importorg.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplicationpublicclassApiGatewayApplication{ publicstaticvoidmain(String[] args){? ? ? ? SpringApplication.run(ApiGatewayApplication.class, args);? ? } }

1.3 路由方式

Gateway的路由方式有兩種吼虎,分別為編碼方式和配置方式犬钢。

1.3.1 編碼方式

在上面的啟動(dòng)類(lèi)中加入下面的自定義RouteLocator的方法即可:

@BeanpublicRouteLocatorcustomRouteLocator(RouteLocatorBuilder builder){returnbuilder.routes().route("route_a", r -> r.path("/hello").uri("http://localhost:8081/"))? ? ? ? ? ? ? ? .build();? ? }

1.3.2 配置方式

將上面自定義RouteLocator的方法注釋掉,在application.properties文件中輸入下面的內(nèi)容:

spring.application.name=api-gatewayserver.port=5555spring.cloud.gateway.routes[0].id=route_aspring.cloud.gateway.routes[0].uri=http://localhost:8081/spring.cloud.gateway.routes[0].predicates[0]=Path=/hello

其中后三行的內(nèi)容和上述編碼配置的方式實(shí)現(xiàn)的效果是一樣的思灰。

1.4 運(yùn)行及結(jié)果

這里采用配置文件的方式來(lái)運(yùn)行玷犹,確保之前搭建的eureka-server、hello-service和feign-consumer項(xiàng)目都運(yùn)行起來(lái)洒疚,啟動(dòng)本項(xiàng)目歹颓,頁(yè)面輸入http://localhost:5555/hello,結(jié)果如下所示:

訪問(wèn)http://localhost:5555/hello會(huì)被自動(dòng)路由到http://localhost:8081/hello油湖,這樣就驗(yàn)證了路由轉(zhuǎn)發(fā)的成功巍扛。

2 面向服務(wù)的方式

顯而易見(jiàn)的是,傳統(tǒng)路由的配置方式比較繁瑣乏德,如果路由特別多的情況下撤奸,維護(hù)起來(lái)會(huì)很麻煩。為此喊括,可以將Gateway與Eureka整合起來(lái)胧瓜,這樣不用再寫(xiě)具體的url映射,url交給Eureka的服務(wù)發(fā)現(xiàn)機(jī)制去自動(dòng)維護(hù)郑什。

2.1 pom.xml

pom沿用上面的配置府喳,只需要再加入下面的Eureka依賴(lài)即可:

org.springframework.cloudspring-cloud-starter-netflix-eureka-client

2.2 application.properties

spring.application.name=api-gatewayserver.port=5555spring.cloud.gateway.discovery.locator.enabled=truespring.cloud.gateway.discovery.locator.lowerCaseServiceId=trueeureka.client.service-url.defaultZone=http://peer1:1111/eureka/,http://peer2:1112/eureka/,http://peer3:1113/eureka/

其中spring.cloud.gateway.discovery.locator.enabled設(shè)置為true表示開(kāi)啟通過(guò)注冊(cè)中心進(jìn)行路由轉(zhuǎn)發(fā)的功能,spring.cloud.gateway.discovery.locator.lowerCaseServiceId設(shè)置為true表示通過(guò)小寫(xiě)形式來(lái)訪問(wèn)服務(wù)名稱(chēng)蘑拯。

2.3 運(yùn)行及結(jié)果

重啟本項(xiàng)目劫拢,頁(yè)面分別訪問(wèn)http://localhost:5555/feign-consumer/feign-consumer肉津、http://localhost:5555/feign-consumer/feign-consumer2和http://localhost:5555/feign-consumer/feign-consumer3,結(jié)果如下所示:

可以看到舱沧,和之前通過(guò)OpenFeign的消費(fèi)者訪問(wèn)的結(jié)果是一樣的,路由轉(zhuǎn)發(fā)是成功的偶洋。

3 Predicate和Filter

Predicate和Filter是Gateway中的核心熟吏,Predicate是選擇哪些請(qǐng)求需要處理,而Filter給選擇出來(lái)的請(qǐng)求做一些改動(dòng)玄窝,比如參數(shù)處理和安全校驗(yàn)等等牵寺。

3.1 Predicate

新建一個(gè)Spring Boot項(xiàng)目,命名為test-gateway恩脂,pom文件依賴(lài)和上述第1.1節(jié)中的pom依賴(lài)一致帽氓。這里我們用Postman來(lái)查看運(yùn)行結(jié)果。

3.1.1 時(shí)間匹配

spring.application.name=gateway-testserver.port=5556spring.cloud.gateway.routes[0].id=route_testspring.cloud.gateway.routes[0].uri=https://www.baidu.com/spring.cloud.gateway.routes[0].predicates[0]=After=2019-08-12T12:00:00+08:00[Asia/Shanghai]

上述After表示在2019年8月12日12點(diǎn)之后的請(qǐng)求可以被路由俩块,而B(niǎo)efore代表在指定時(shí)間之前可以被路由黎休,Between則代表在指定的時(shí)間區(qū)隔之內(nèi)可以被路由:

After=2019-08-12T12:00:00+08:00[Asia/Shanghai]Before=2019-08-12T12:00:00+08:00[Asia/Shanghai]Between=2019-08-12T12:00:00+08:00[Asia/Shanghai],2019-08-13T12:00:00+08:00[Asia/Shanghai]

3.1.2 請(qǐng)求方式匹配

spring.application.name=gateway-testserver.port=5556spring.cloud.gateway.routes[0].id=route_testspring.cloud.gateway.routes[0].uri=https://www.baidu.com/spring.cloud.gateway.routes[0].predicates[0]=Method=GET

上述表示只有GET請(qǐng)求才能被成功路由,訪問(wèn)Postman得到如下結(jié)果:

狀態(tài)碼為200玉凯,說(shuō)明成功訪問(wèn)势腮,這時(shí)我們改成POST請(qǐng)求,再來(lái)訪問(wèn):

狀態(tài)碼為404漫仆,說(shuō)明訪問(wèn)失敗捎拯。

3.1.3 請(qǐng)求路徑匹配

spring.application.name=gateway-testserver.port=5556spring.cloud.gateway.routes[0].id=route_testspring.cloud.gateway.routes[0].uri=https://www.baidu.com/spring.cloud.gateway.routes[0].predicates[0]=Path=/foo/{segment}

由上配置了匹配的請(qǐng)求路徑,Postman訪問(wèn)http://localhost:5556/foo/1盲厌,訪問(wèn)成功:

訪問(wèn)http://localhost:5556/foo/1/2署照,訪問(wèn)失敗:

3.1.4 請(qǐng)求參數(shù)匹配

spring.application.name=gateway-testserver.port=5556spring.cloud.gateway.routes[0].id=route_testspring.cloud.gateway.routes[0].uri=https://www.baidu.com/spring.cloud.gateway.routes[0].predicates[0]=Query=p1

上述配置了請(qǐng)求參數(shù)中必須含有p1參數(shù)才能路由成功吗浩,Postman訪問(wèn)http://localhost:5556/?p1=1建芙,路由成功:

訪問(wèn)http://localhost:5556/?p2=2,路由失斖孛取:

Query的值還可以使用正則表達(dá)式來(lái)進(jìn)行匹配岁钓,如下面的例子:

spring.application.name=gateway-testserver.port=5556spring.cloud.gateway.routes[0].id=route_testspring.cloud.gateway.routes[0].uri=https://www.baidu.com/spring.cloud.gateway.routes[0].predicates[0]=Query=p1,1.

上面配置了參數(shù)中的鍵必須含有p1,同時(shí)它所對(duì)應(yīng)的值是以1開(kāi)頭的兩個(gè)字符微王,Postman訪問(wèn)http://localhost:5556/?p1=1s屡限,路由成功:

Postman訪問(wèn)http://localhost:5556/?p1=1,路由失斂惶取:

3.2 Filter

這里只演示AddRequestParameter的用法钧大,更多的用法詳見(jiàn)Spring官網(wǎng)。

AddRequestParameter是在請(qǐng)求的路徑中添加相應(yīng)的參數(shù)罩旋,我們繼續(xù)使用上述的api-gateway項(xiàng)目啊央。

3.2.1 hello-service

首先需要對(duì)之前的hello-service項(xiàng)目做些更改眶诈,在其中的HelloController中添加一個(gè)foo方法如下所示:

@RequestMapping("/foo")publicStringfoo(Stringfoo) {returnfoo;? ? }

3.2.2 feign-consumer

然后在feign-consumer項(xiàng)目中的ConsumerController中添加下面的方法:

@RequestMapping("/foo")publicStringfoo(Stringfoo) {returnhelloService.foo(foo);? ? }

在IHelloService中添加下面的方法:

@RequestMapping("/foo")Stringfoo(@RequestParam("foo")Stringfoo);

在相應(yīng)的HelloServiceImplFallback降級(jí)類(lèi)中填入下面的降級(jí)方法:

@OverridepublicStringfoo(Stringfoo) {return"訪問(wèn)超時(shí),請(qǐng)重新再試瓜饥!";? ? }

3.2.3 application.properties

api-gateway網(wǎng)關(guān)的配置文件需要做些修改:

spring.application.name=api-gatewayserver.port=5555spring.cloud.gateway.discovery.locator.enabled=truespring.cloud.gateway.discovery.locator.lower-case-service-id=truespring.cloud.gateway.routes[0].id=add_request_parameter_routespring.cloud.gateway.routes[0].uri=lb://hello-servicespring.cloud.gateway.routes[0].predicates[0]=Method=GETspring.cloud.gateway.routes[0].filters[0]=AddRequestParameter=foo, bareureka.client.service-url.defaultZone=http://peer2:1112/eureka/,http://peer3:1113/eureka/

其中逝撬,uri表示配置路由轉(zhuǎn)發(fā)到hello-service的服務(wù)提供者。filters表示給匹配的請(qǐng)求中添加了一個(gè)foo=bar的參數(shù)乓土。需要注意的是宪潮,filters必須和predicates聯(lián)用,否則項(xiàng)目啟動(dòng)會(huì)失敗趣苏。

3.2.4 運(yùn)行及結(jié)果

隨后分別啟動(dòng)eureka-server狡相、hello-service和feign-consumer項(xiàng)目,然后啟動(dòng)api-gateway網(wǎng)關(guān)項(xiàng)目食磕,首先頁(yè)面訪問(wèn)http://localhost:9001/foo尽棕,以O(shè)penFeign消費(fèi)者的方式來(lái)訪問(wèn)服務(wù):

由上可以看到,當(dāng)沒(méi)有使用網(wǎng)關(guān)來(lái)訪問(wèn)服務(wù)的時(shí)候彬伦,頁(yè)面上沒(méi)有結(jié)果滔悉,也就是說(shuō)服務(wù)提供者沒(méi)有接收到foo參數(shù)。然后我們?cè)L問(wèn)http://localhost:5555/foo媚朦,以網(wǎng)關(guān)的方式來(lái)訪問(wèn)服務(wù):

以上可知氧敢,頁(yè)面上顯示了bar,foo參數(shù)被成功接收询张,在請(qǐng)求中會(huì)添加一個(gè)foo=bar的參數(shù)孙乖。

參考:http://blog.didispace.com/springcloud2/https://blog.csdn.net/weixin_30342639/article/details/99303710

https://mp.weixin.qq.com/s/WAQkqRAYo50ddRp5CbGuvw

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市份氧,隨后出現(xiàn)的幾起案子唯袄,更是在濱河造成了極大的恐慌,老刑警劉巖蜗帜,帶你破解...
    沈念sama閱讀 217,406評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件恋拷,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡厅缺,警方通過(guò)查閱死者的電腦和手機(jī)蔬顾,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,732評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)湘捎,“玉大人诀豁,你說(shuō)我怎么就攤上這事】荆” “怎么了舷胜?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,711評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)活翩。 經(jīng)常有香客問(wèn)我烹骨,道長(zhǎng)翻伺,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,380評(píng)論 1 293
  • 正文 為了忘掉前任沮焕,我火速辦了婚禮吨岭,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘峦树。我一直安慰自己未妹,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,432評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布空入。 她就那樣靜靜地躺著,像睡著了一般族檬。 火紅的嫁衣襯著肌膚如雪歪赢。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,301評(píng)論 1 301
  • 那天单料,我揣著相機(jī)與錄音埋凯,去河邊找鬼。 笑死扫尖,一個(gè)胖子當(dāng)著我的面吹牛白对,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播换怖,決...
    沈念sama閱讀 40,145評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼甩恼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了沉颂?” 一聲冷哼從身側(cè)響起条摸,我...
    開(kāi)封第一講書(shū)人閱讀 39,008評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎铸屉,沒(méi)想到半個(gè)月后钉蒲,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,443評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡彻坛,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,649評(píng)論 3 334
  • 正文 我和宋清朗相戀三年顷啼,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片昌屉。...
    茶點(diǎn)故事閱讀 39,795評(píng)論 1 347
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡钙蒙,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出怠益,到底是詐尸還是另有隱情仪搔,我是刑警寧澤,帶...
    沈念sama閱讀 35,501評(píng)論 5 345
  • 正文 年R本政府宣布蜻牢,位于F島的核電站烤咧,受9級(jí)特大地震影響偏陪,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜煮嫌,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,119評(píng)論 3 328
  • 文/蒙蒙 一笛谦、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧昌阿,春花似錦饥脑、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,731評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至刷钢,卻和暖如春笋颤,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背内地。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,865評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工伴澄, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人阱缓。 一個(gè)月前我還...
    沈念sama閱讀 47,899評(píng)論 2 370
  • 正文 我出身青樓非凌,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親荆针。 傳聞我的和親對(duì)象是個(gè)殘疾皇子敞嗡,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,724評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容