白話SpringCloud | 第九章:路由網(wǎng)關(guān)(Zuul)的使用

第九章:路由網(wǎng)關(guān)(Zuul)的使用

前言

介紹完分布式配置中心,結(jié)合前面的文章淌友。我們已經(jīng)有了一個微服務(wù)的框架了煌恢,可以對外提供api接口服務(wù)了。但現(xiàn)在試想一下震庭,在微服務(wù)框架中症虑,每個對外服務(wù)都是獨立部署的,對外的api或者服務(wù)地址都不是不盡相同的归薛。對于內(nèi)部而言谍憔,很簡單匪蝙,通過注冊中心自動感知即可。但我們大部分情況下习贫,服務(wù)都是提供給外部系統(tǒng)進(jìn)行調(diào)用的逛球,不可能同享一個注冊中心。同時一般上內(nèi)部的微服務(wù)都是在內(nèi)網(wǎng)的苫昌,和外界是不連通的颤绕。而且,就算我們每個微服務(wù)對外開放祟身,對于調(diào)用者而言奥务,調(diào)用不同的服務(wù)的地址或者參數(shù)也是不盡相同的,這樣就會造成消費者客戶端的復(fù)雜性袜硫,同時想想氯葬,可能微服務(wù)可能是不同的技術(shù)棧實現(xiàn)的,有的是http婉陷、rpc或者websocket等等帚称,也會進(jìn)一步加大客戶端的調(diào)用難度。所以秽澳,一般上都有會有個api網(wǎng)關(guān)闯睹,根據(jù)請求的url不同,路由到不同的服務(wù)上去担神,同時入口統(tǒng)一了楼吃,還能進(jìn)行統(tǒng)一的身份鑒權(quán)、日志記錄妄讯、分流等操作孩锡。接下來,我們就來了解今天要講解的路由服務(wù):zuul捞挥。

一點知識

為什么要使用微服務(wù)網(wǎng)關(guān)

簡單來說,微服務(wù)網(wǎng)關(guān)是微服務(wù)架構(gòu)中一個不可或缺的部分忧吟。通過服務(wù)網(wǎng)關(guān)統(tǒng)一向外系統(tǒng)提供REST API的過程中砌函,除了具備服務(wù)路由、均衡負(fù)載功能之外溜族,它還具備了權(quán)限控制等功能讹俊。

在未加入網(wǎng)關(guān)時,一般上會在服務(wù)外網(wǎng)架設(shè)一個負(fù)載均衡煌抒,如nginx等仍劈。此時,微服務(wù)的組成為:

image

此時寡壮,對于Open Service而言可能需要提供權(quán)限控制等和業(yè)務(wù)無關(guān)的能力贩疙,這樣本身就破壞了微服務(wù)服務(wù)單一的原則讹弯。所以,一般上在Open Service之上这溅,還有一層服務(wù)提供諸如通用的權(quán)限校驗组民、參數(shù)校驗等功能,此服務(wù)就是網(wǎng)關(guān)了悲靴。之后臭胜,對于內(nèi)部微服務(wù)而言,只需要關(guān)系各自微服務(wù)提供的業(yè)務(wù)功能即可癞尚,無需去關(guān)心其他非業(yè)務(wù)相關(guān)的功能耸三。

API網(wǎng)關(guān)是什么

API網(wǎng)關(guān)可以提供一個單獨且統(tǒng)一的API入口用于訪問內(nèi)部一個或多個API。簡單來說嘛就是一個統(tǒng)一入口浇揩,比如現(xiàn)在的支付寶或者微信的相關(guān)api服務(wù)一樣仪壮,都有一個統(tǒng)一的api地址,統(tǒng)一的請求參數(shù)临燃,統(tǒng)一的鑒權(quán)睛驳。

客戶端和服務(wù)端直連的弊端

  • 客戶端會對此請求不同的微服務(wù),增加客戶端復(fù)雜性
  • 存在跨域請求時膜廊,需要進(jìn)行額外處理
  • 認(rèn)證服務(wù)乏沸,每個服務(wù)需要獨立認(rèn)證
  • UI端和微服務(wù)耦合

網(wǎng)關(guān)的優(yōu)缺點

優(yōu)點

  • 減少api請求次數(shù)
  • 限流
  • 緩存
  • 統(tǒng)一認(rèn)證
  • 降低微服務(wù)的復(fù)雜度
  • 支持混合通信協(xié)議(前端只和api通信,其他的由網(wǎng)關(guān)調(diào)用)
  • ……

缺點:

  • 網(wǎng)關(guān)需高可用爪瓜,可能產(chǎn)生單點故障
  • 管理復(fù)雜

網(wǎng)關(guān)的選擇

現(xiàn)在市場上有很多的網(wǎng)關(guān)可供選擇:

  • Spring Cloud Zuul:本身基于Netflix開源的微服務(wù)網(wǎng)關(guān),可以和Eureka,Ribbon,Hystrix等組件配合使用蹬跃。
  • Kong : 基于OpenResty的 API 網(wǎng)關(guān)服務(wù)和網(wǎng)關(guān)服務(wù)管理層。
  • Spring Cloud Gateway:是由spring官方基于Spring5.0,Spring Boot2.0,Project Reactor等技術(shù)開發(fā)的網(wǎng)關(guān)铆铆,提供了一個構(gòu)建在Spring Ecosystem之上的API網(wǎng)關(guān)蝶缀,旨在提供一種簡單而有效的途徑來發(fā)送API,并向他們提供交叉關(guān)注點薄货,例如:安全性翁都,監(jiān)控/指標(biāo)和彈性。目的是為了替換Spring Cloud Netfilx Zuul的谅猾。

Spring cloud體系中柄慰,一般上選擇zuul或者Gateway。當(dāng)然税娜,也可以綜合自己的業(yè)務(wù)復(fù)雜性满粗,自研一套或者改在一套符合自身業(yè)務(wù)發(fā)展的api網(wǎng)關(guān)的颤专,最簡單做法是做個聚合api服務(wù)哼拔,通過SpringBoot構(gòu)建對外的api接口盖呼,實現(xiàn)統(tǒng)一鑒權(quán)、參數(shù)校驗弧岳、權(quán)限控制等功能凳忙,說白了就是一個rest服務(wù)业踏。

Zuul介紹和使用

何為Zuul

ZuulNetflix開源的微服務(wù)網(wǎng)關(guān),可以和Eureka消略、Ribbon堡称、Hystrix等組件配合使用,Spring CloudZuul進(jìn)行了整合與增強艺演,Zuul的主要功能是路由轉(zhuǎn)發(fā)過濾器却紧。

zuul

Zuul基于JVM的路由器和服務(wù)器端負(fù)載均衡器。同時胎撤,Zuul的規(guī)則引擎允許規(guī)則和過濾器基本上用任何JVM語言編寫晓殊,內(nèi)置支持JavaGroovy。這個功能伤提,就可以實現(xiàn)動態(tài)路由的功能了巫俺。當(dāng)需要添加某個新的對外服務(wù)時,一般上不停機更新是通過數(shù)據(jù)緩存配置或者使用Groovy進(jìn)行動態(tài)路由的添加的肿男。

Zuul的核心一系列的過濾器:

  • 身份認(rèn)證與安全:識別每個資源的驗證要求介汹,并拒絕那些與要求不符的請求。
  • 審查與監(jiān)控:在邊緣位置追蹤有意義的數(shù)據(jù)和統(tǒng)計結(jié)果舶沛,從而帶來精確的生產(chǎn)視圖嘹承。
  • 動態(tài)路由:動態(tài)地將請求路由到不同的后端集群。
  • 壓力測試:逐漸增加指向集群的流量如庭,以了解性能叹卷。
  • 負(fù)載分配:為每一種負(fù)載類型分配對應(yīng)容量,并啟用超出限定值的請求坪它。
  • 靜態(tài)響應(yīng)處理:在邊緣位置直接建立部分相應(yīng)骤竹,從而避免其轉(zhuǎn)發(fā)到內(nèi)部集群。

加入Zuul網(wǎng)關(guān)后:

加入Zuul后

Zuul實踐

創(chuàng)建工程:spring-cloud-zuul往毡。
這里直接加入了注冊中心進(jìn)行服務(wù)化模式蒙揣。

0.加入pom依賴。

        <!-- zuul 依賴 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
        </dependency>        
        <!-- eureka client 依賴 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>

注意:這里的Eureka不是必須的开瞭。在沒有注冊中心的情況下懒震,也是可以進(jìn)行zuul使用的。

1.配置文件惩阶,配置注冊中心相關(guān)信息挎狸、路由規(guī)則等扣汪。

spring.application.name=zuul-server
server.port=8888

# 注冊中心地址 -此為單機模式
eureka.client.service-url.defaultZone=http://127.0.0.1:1000/eureka
# 啟用ip配置 這樣在注冊中心列表中看見的是以ip+端口呈現(xiàn)的
eureka.instance.prefer-ip-address=true
# 實例名稱  最后呈現(xiàn)地址:ip:15678
eureka.instance.instance-id=${spring.cloud.client.ip-address}:${server.port}

## 路由規(guī)則
## 傳統(tǒng)路由配置:不依賴服務(wù)發(fā)現(xiàn)断楷。
## 所有以myapi開頭的url路由至http://127.0.0.1:2000/下
## 如http://127.0.0.1:8888/myapi/hello --> http://127.0.0.1:2000/hello
zuul.routes.myApi.path=/myapi/**
zuul.routes.myApi.url=http://127.0.0.1:2000

#forward模式 直接轉(zhuǎn)發(fā)至zuul提供的rest服務(wù)
zuul.routes.myDemo.path=/myDemo/**
zuul.routes.myDemo.url=forward:/demo

## 服務(wù)發(fā)現(xiàn)模式
# 路由地址
zuul.routes.myEureka.path=/eureka/**
#為具體服務(wù)的名稱
zuul.routes.myEureka.service-id=eureka-client

友情提示:
默認(rèn)情況下:Zuul代理所有注冊到EurekaServer的微服務(wù),路由規(guī)則:
http://ZUUL_HOST:ZUUL_PORT/微服務(wù)實例名(serverId)/**
轉(zhuǎn)發(fā)至serviceId對應(yīng)的微服務(wù)崭别。

如:http://127.0.0.1:8888/eureka-client/hello?name=oKong
最后就是轉(zhuǎn)發(fā)至:http://127.0.0.1:2000//hello?name=oKong

2.啟動類加入@EnableZuulProxy注解冬筒,聲明一個Zuul代理恐锣。

/**
 * zuul 示例
 * 
 * @author oKong
 *
 */
@SpringBootApplication
@EnableZuulProxy
@EnableDiscoveryClient
@Slf4j
public class SpringCloudZuulApplication {
    public static void main(String[] args) throws Exception {
        SpringApplication.run(SpringCloudZuulApplication.class, args);
        log.info("spring-cloud-zuul啟動!");
    }

}

3.編寫一個控制類舞痰,測試forward功能。


/**
 * zuul 內(nèi)部提供對外服務(wù)示例
 * @author oKong
 *
 */
@RestController
@RequestMapping("/demo")
public class DemoController {

    @GetMapping("/hello")
    public String hello(String name) {
        return "hi," + name + ",this is zuul api! ";
    }
}

4.啟動spring-cloud-eureka-serverspring-cloud-eureka-client服務(wù)玷禽,之后再啟動spring-cloud-zuul服務(wù)。

此時矢赁,我們來訪問zuul內(nèi)部服務(wù):http://127.0.0.1:8888/demo/hello?name=oKong

zuul內(nèi)部服務(wù)

然后訪問:http://127.0.0.1:8888/myDemo/hello?name=oKong 效果和上面直接方式是一樣的贬丛,最后都是訪問/demo/**api地址的。

訪問:http://127.0.0.1:8888/myapi/hello?name=oKonghttp://127.0.0.1:8888/eureka/hello?name=oKong 最后效果都是一樣的豺憔,都是訪問http://127.0.0.1:2000/hello?name=oKong

eureka服務(wù)
非eureka服務(wù)

直接以默認(rèn)形式訪問:http://127.0.0.1:8888/eureka-client/hello?name=oKong 最后效果也是一樣的恭应。

默認(rèn)形式

其實抄邀,從控制臺輸出日志也是可以一窺究竟的:

控制臺輸出

路由規(guī)則說明

簡單說明下關(guān)于路由規(guī)則的一些說明:

傳統(tǒng)路由配置:不依賴服務(wù)發(fā)現(xiàn),如nginx

  • 單例實例配置:通過zuul.routes.<route>.pathzuul.routes.<route>.url參數(shù)對的方式來配置
# 傳統(tǒng)路由配置
zuul.routes.server-provide.path=/server-provide/**
zuul.routes.server-provide.url=http://127.0.0.1:1001/

  • 多實例配置:通過一組zuul.routes.<route>.pathzuul.routes.<route>.serviceId參數(shù)對的方式配置
# 多實例
zuul.routes.server-provide.path=/user-service/**
zuul.routes.server-provide.serviceId=user-service
ribbon.eureka.enabled=false
server-provide.ribbon.listOfServers=http://127.0.0.1:1001/,http://127.0.0.1:1001/

服務(wù)路由配置:依賴服務(wù)發(fā)現(xiàn)暮屡,結(jié)合Eureka

  • 默認(rèn)規(guī)則:http://ZUUL_HOST:ZUUL_PORT/微服務(wù)實例名(serverId)/** 撤摸,轉(zhuǎn)發(fā)至serviceId對應(yīng)的微服務(wù)。

  • 自定義路由規(guī)則:通過一組zuul.routes.<route>.pathzuul.routes.<route>.serviceId參數(shù)對的方式配置

# 自定義路由
zuul.routes.server-provide.path=/server-api/**
zuul.routes.server-provide.serviceId=server-provide

比如:

例子

而且褒纲,要注意准夷,這些過濾器是path進(jìn)行最佳路徑匹配的,所以莺掠,一般上在一些歷史系統(tǒng)上衫嵌,我們會在最后后面加上一個路徑/**的匹配規(guī)則,以保證歷史api可以使用彻秆,做到最大兼容性,避免類似404的異常楔绞。

zuul.routes.legacy.path=/**

參考資料

  1. https://cloud.spring.io/spring-cloud-static/Finchley.SR1/single/spring-cloud.html#_router_and_filter_zuul

總結(jié)

本章節(jié)主要簡單介紹了關(guān)于Zuul的一些簡單使用以及一些路由規(guī)則的簡單說明。開頭也說過了唇兑,Zuul的核心是一系列的過濾器酒朵。介于篇幅問題,關(guān)于過濾器的介紹扎附、自定義過濾器蔫耽、異常處理、熔斷降級等放在下一章節(jié)來講解留夜。而相關(guān)的其他配置匙铡,大家可以去官網(wǎng)進(jìn)行查看图甜,或者自行搜索下,也可以查看下:org.springframework.cloud.netflix.zuul.filters.ZuulProperties類鳖眼,相關(guān)配置信息都在里面了黑毅。

最后

目前互聯(lián)網(wǎng)上大佬都有分享SpringCloud系列教程,內(nèi)容可能會類似钦讳,望多多包涵了矿瘦。原創(chuàng)不易,碼字不易愿卒,還希望大家多多支持匪凡。若文中有錯誤之處,還望提出掘猿,謝謝病游。

老生常談

  • 個人QQ:499452441
  • 微信公眾號:lqdevOps
公眾號

個人博客:http://blog.lqdev.cn

源碼示例:https://github.com/xie19900123/spring-cloud-learning

原文地址:http://blog.lqdev.cn/2018/10/14/SpringCloud/chapter-nine/

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市滋尉,隨后出現(xiàn)的幾起案子狮惜,更是在濱河造成了極大的恐慌碌识,老刑警劉巖筏餐,帶你破解...
    沈念sama閱讀 218,386評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件魁瞪,死亡現(xiàn)場離奇詭異导俘,居然都是意外死亡,警方通過查閱死者的電腦和手機辅髓,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,142評論 3 394
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來猎莲,“玉大人著洼,你說我怎么就攤上這事身笤。” “怎么了瞻佛?”我有些...
    開封第一講書人閱讀 164,704評論 0 353
  • 文/不壞的土叔 我叫張陵伤柄,是天一觀的道長适刀。 經(jīng)常有香客問我笔喉,道長硝皂,這世上最難降的妖魔是什么稽物? 我笑而不...
    開封第一講書人閱讀 58,702評論 1 294
  • 正文 為了忘掉前任姨裸,我火速辦了婚禮傀缩,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘售淡。我一直安慰自己揖闸,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,716評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著贮泞,像睡著了一般啃擦。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上聚霜,一...
    開封第一講書人閱讀 51,573評論 1 305
  • 那天俯萎,我揣著相機與錄音夫啊,去河邊找鬼辆憔。 笑死,一個胖子當(dāng)著我的面吹牛熊榛,可吹牛的內(nèi)容都是我干的玄坦。 我是一名探鬼主播煎楣,決...
    沈念sama閱讀 40,314評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼车伞,長吁一口氣:“原來是場噩夢啊……” “哼另玖!你這毒婦竟也來了表伦?” 一聲冷哼從身側(cè)響起蹦哼,我...
    開封第一講書人閱讀 39,230評論 0 276
  • 序言:老撾萬榮一對情侶失蹤纲熏,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后飘痛,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,680評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡车柠,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,873評論 3 336
  • 正文 我和宋清朗相戀三年竹祷,在試婚紗的時候發(fā)現(xiàn)自己被綠了塑陵。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片令花。...
    茶點故事閱讀 39,991評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡兼都,死狀恐怖稽寒,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情慎王,我是刑警寧澤柬祠,帶...
    沈念sama閱讀 35,706評論 5 346
  • 正文 年R本政府宣布负芋,位于F島的核電站,受9級特大地震影響莽龟,放射性物質(zhì)發(fā)生泄漏毯盈。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,329評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望脑奠。 院中可真熱鬧,春花似錦轰豆、人聲如沸酸休。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,910評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至特占,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間谤饭,已是汗流浹背揉抵。 一陣腳步聲響...
    開封第一講書人閱讀 33,038評論 1 270
  • 我被黑心中介騙來泰國打工冤今, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留茂缚,地道東北人。 一個月前我還...
    沈念sama閱讀 48,158評論 3 370
  • 正文 我出身青樓龟糕,卻偏偏與公主長得像讲岁,于是被迫代替她去往敵國和親缓艳。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,941評論 2 355

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