轉(zhuǎn)載
一:首先看一張springCloud的圖片:

二:簡(jiǎn)單介紹下什么是springCloud?
"Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智能路由,微代理,控制總線)。分布式系統(tǒng)的協(xié)調(diào)導(dǎo)致了樣板模式, 使用Spring Cloud開發(fā)人員可以快速地支持實(shí)現(xiàn)這些模式的服務(wù)和應(yīng)用程序。他們將在任何分布式環(huán)境中運(yùn)行良好,包括開發(fā)人員自己的筆記本電腦,裸機(jī)數(shù)據(jù)中心,以及Cloud Foundry等托管平臺(tái)。" -----來(lái)自官網(wǎng)
三:為了方便理解假設(shè)一個(gè)業(yè)務(wù)場(chǎng)景(場(chǎng)景來(lái)源于石杉的架構(gòu)筆記(id:shishan100))
假設(shè)現(xiàn)在開發(fā)一個(gè)電商網(wǎng)站,要實(shí)現(xiàn)支付訂單功能:流程如下--
?? ?1.創(chuàng)建一個(gè)訂單后,如果用戶立刻支付了這個(gè)訂單,我們需要將這個(gè)訂單狀態(tài)更新為(已經(jīng)支付)
?? ?2.扣減相對(duì)應(yīng)的商品庫(kù)存
?? ?3.通知倉(cāng)儲(chǔ)中心,進(jìn)行發(fā)貨
?? ?4.給用戶這次購(gòu)物怎加相對(duì)應(yīng)的積分
針對(duì)上述流程,我們需要有訂單服務(wù)、庫(kù)存服務(wù)、倉(cāng)儲(chǔ)服務(wù)、積分服務(wù)。整個(gè)流程的大體思路如下:
?? ?1.用戶針對(duì)一個(gè)訂單完成支付后,就回去找訂單服務(wù),跟新訂單狀態(tài)
?? ?2.訂單服務(wù)調(diào)用庫(kù)存服務(wù),完成相應(yīng)的功能
?? ?3.訂單服務(wù)調(diào)用倉(cāng)儲(chǔ)服務(wù),完成相應(yīng)的功能
?? ?4.訂單服務(wù)調(diào)用積分服務(wù),完成相應(yīng)的功能
整個(gè)支付流程結(jié)束
整個(gè)過(guò)程可以如下圖所示:

四:SpringCloud核心組件:Eureka
4.1首先考慮第一個(gè)問(wèn)題,訂單服務(wù)要調(diào)用庫(kù)存服務(wù),倉(cāng)儲(chǔ)服務(wù),或積分服務(wù),怎么調(diào)用?
1.訂單服務(wù)根本不知道庫(kù)存服務(wù)在哪臺(tái)機(jī)器上,就算想起來(lái),都不知道發(fā)送給誰(shuí)?
?? ?隨意springCloud就有一個(gè)springCloud的Eureka,Eureka是服務(wù)架構(gòu)的注冊(cè)中心
?? ?專門負(fù)責(zé)服務(wù)的注冊(cè)和發(fā)現(xiàn);
看下這個(gè)圖:

如上圖所示:庫(kù)存服務(wù),倉(cāng)儲(chǔ)服務(wù),積分服務(wù),都有一個(gè)Eureka Client組件組件,這個(gè)專門這個(gè)服務(wù)的信息注冊(cè)到Eureka Server中,說(shuō)白了就是告訴Eureka Server,自己在哪臺(tái)機(jī)器上,監(jiān)聽那個(gè)端口,而Eureka?是一個(gè)注冊(cè)中心,里面有一個(gè)注冊(cè)表,保存了各個(gè)服務(wù)器的機(jī)器和端口,
訂單服務(wù)里面有一個(gè)Eureka Client組件組件,Eureka Client組件會(huì)問(wèn)一下:庫(kù)存在那臺(tái)服務(wù)器上,監(jiān)聽的端口號(hào)是哪個(gè),倉(cāng)儲(chǔ)服務(wù)呢?積分服務(wù)呢?然后就可以把這些相關(guān)信息從Eureka Server的注冊(cè)表中拉取到自己本地緩存起來(lái)。
這時(shí)候如果訂單服務(wù)想要調(diào)用庫(kù)存服務(wù),不就可以找自己本地Eureka Client問(wèn)題下庫(kù)存服務(wù)在那臺(tái)機(jī)器上,監(jiān)聽哪個(gè)端口嗎?收到響應(yīng)后,緊接著就可以發(fā)送一個(gè)請(qǐng)求過(guò)去,調(diào)用庫(kù)存服務(wù)扣減庫(kù)存的那個(gè)接口!同理,如果訂單服務(wù)要調(diào)用倉(cāng)儲(chǔ)服務(wù)、積分服務(wù),也是如法炮制。
所以總結(jié)下:
? Eureka?service:注冊(cè)中心,里面有一個(gè)注冊(cè)表,保存了各個(gè)服務(wù)所在的機(jī)器和端口號(hào)
? Eurake Client:負(fù)責(zé)將這個(gè)服務(wù)的信息注冊(cè)到Eureka Server中
五springCloud核心組件;Feign
現(xiàn)在訂單服務(wù)確實(shí)知道庫(kù)存服務(wù),積分服務(wù),倉(cāng)儲(chǔ)服務(wù)在哪里了,同事有監(jiān)聽著這些端口號(hào),
但是新問(wèn)題又來(lái)了,難道訂單服務(wù)要寫一大堆代碼,跟其他服務(wù)建立網(wǎng)絡(luò)連接,然后構(gòu)造一個(gè)復(fù)雜的
請(qǐng)求,接著發(fā)送請(qǐng)求過(guò)去,結(jié)果寫一大堆代碼來(lái)相應(yīng)處理
比如這樣:

如果每次手寫代碼,代碼量比上面的還要多,隨意SpringCloud提供了一個(gè)優(yōu)雅的解決方案,看看Feign的話訂單服務(wù)調(diào)用庫(kù)存的代碼會(huì)變成啥樣?

沒(méi)有底層的建立連接、構(gòu)造請(qǐng)求、解析響應(yīng)的代碼,直接就是用注解定義一個(gè) FeignClient接口,然后調(diào)用那個(gè)接口就可以了。人家Feign Client會(huì)在底層根據(jù)你的注解,跟你指定的服務(wù)建立連接、構(gòu)造請(qǐng)求、發(fā)起靕求、獲取響應(yīng)、解析響應(yīng),等等。這一系列臟活累活,人家Feign全給你干了。
問(wèn)題來(lái)了,Feign是如何做到的呢?其實(shí)Feign的一個(gè)機(jī)制就是使用了動(dòng)態(tài)代理,
首先,如果你對(duì)某個(gè)接口定義了@FeignClient注解,F(xiàn)eign就會(huì)針對(duì)這個(gè)接口創(chuàng)建一個(gè)動(dòng)態(tài)代理
接著你要是調(diào)用那個(gè)接口,本質(zhì)就是會(huì)調(diào)用 Feign創(chuàng)建的動(dòng)態(tài)代理,這是核心中的核心
Feign的動(dòng)態(tài)代理會(huì)根據(jù)你在接口上的@RequestMapping等注解,來(lái)動(dòng)態(tài)構(gòu)造出你要請(qǐng)求的服務(wù)的地址
最后針對(duì)這個(gè)地址,發(fā)起請(qǐng)求、解析響應(yīng)

六:springCloud核心組件:Ribbon
說(shuō)完了,那么問(wèn)題來(lái)了,如果庫(kù)存服務(wù)上面部署了臺(tái)機(jī)器,
192.168.169:9000
192.168.170:9000
192.168.171:9000
192.168.172:9000
192.168.173:9000
那Feign怎么知道請(qǐng)求那臺(tái)服務(wù)器呢,這是SpringCloud就派上用場(chǎng)了,Ribbon?務(wù)就是解決這個(gè)問(wèn)題的,他的作用是負(fù)載均衡,會(huì)幫你在每一次請(qǐng)求的時(shí)候選擇一臺(tái)機(jī)器,均勻的把請(qǐng)求發(fā)送到各個(gè)機(jī)器上 ,Ribbon的負(fù)載均衡默認(rèn)的使用RoundRobin輪詢算法,什么是輪詢算法?如果訂單服務(wù)對(duì)庫(kù)存發(fā)起十次請(qǐng)求,那就先讓你請(qǐng)求第一臺(tái)機(jī)器,然后是第二臺(tái)機(jī)器,第三臺(tái)機(jī)器,.......接著循環(huán)到第十臺(tái)機(jī)器
此外,Ribbon是和Feign以及Eureka緊密協(xié)作,完成工作的,具體如下:
首先Ribbon會(huì)從?Eureka Client里面獲取到對(duì)應(yīng)的服務(wù)注冊(cè)表,也就知道了所有的服務(wù)都部署在了那臺(tái)機(jī)器上,在監(jiān)聽哪些端口,
然后Ribbon就可以使用默認(rèn)的Round Robin算法,從中選擇一臺(tái)機(jī)器,
Feigin就會(huì)針對(duì)這些機(jī)器構(gòu)造并發(fā)送請(qǐng)求.可以參考如下這圖:

七:SpringCloud的核心組件:Hystrix
在微服務(wù)架構(gòu)里,一個(gè)系統(tǒng)會(huì)有多個(gè)服務(wù),?以本文的業(yè)務(wù)場(chǎng)景為例:訂單服務(wù)在一個(gè)業(yè)務(wù)流程里需要調(diào)用三個(gè)服務(wù),現(xiàn)在假設(shè)訂單服務(wù)自己最多只有100個(gè)線程可以處理請(qǐng)求然后呢,積分服務(wù)不幸的掛了,每次訂單服務(wù)調(diào)用積分服務(wù)的時(shí)候,都會(huì)卡住幾秒鐘,然后拋出—個(gè)超時(shí)異常。
分析下這樣會(huì)導(dǎo)致什么問(wèn)題:如果系統(tǒng)在高并發(fā)的情況下,大量請(qǐng)求涌過(guò)來(lái)的時(shí)候,訂單服務(wù)的100個(gè)線程會(huì)卡在積分服務(wù)這塊,導(dǎo)致訂單服務(wù)沒(méi)有一個(gè)線程可以處理請(qǐng)求,然后會(huì)導(dǎo)致別的請(qǐng)求訂單服務(wù)的時(shí)候,發(fā)現(xiàn)訂單服務(wù)掛掉,不響應(yīng)任何請(qǐng)求了,這種問(wèn)題就是微服務(wù)架構(gòu)中恐怖的服務(wù)器雪崩問(wèn)題:如下圖,這么多的服務(wù)互相調(diào)用要是不做任何保護(hù)的話,某一個(gè)服務(wù)掛掉會(huì)引起連鎖反應(yīng),導(dǎo)致別的服務(wù)掛掉,比如積分服務(wù)掛了會(huì)導(dǎo)致訂單服務(wù)的線程全部卡在請(qǐng)求積分服務(wù)這里沒(méi)有一個(gè)線程可以工作,瞬間導(dǎo)致訂單服務(wù)也掛了別人請(qǐng)求訂單服務(wù)全部會(huì)卡住,無(wú)法響應(yīng)。

但是我們思考一下,就算積分服務(wù)掛了,訂單服務(wù)也可以不用掛?。槭裁矗?/p>
我們結(jié)合業(yè)務(wù)來(lái)看:支付訂單的時(shí)候,只要把庫(kù)存扣減了,然后通知倉(cāng)庫(kù)發(fā)貨就OK了
如果積分服務(wù)掛了,大不了等他恢復(fù)之后,慢慢人肉手工恢復(fù)數(shù)據(jù)!為啥一定要因?yàn)橐粋€(gè)積分服務(wù)掛了,就直接導(dǎo)致訂單服務(wù)也掛了呢?不可以接受!
現(xiàn)在問(wèn)題分析完了,如何解決?
這時(shí)就輪到Hystrix閃亮登場(chǎng)了。Hystrix是隔離、熔斷以及降級(jí)的一個(gè)框架。啥意思說(shuō)白了就是Hystrix會(huì)搞很多小線程池,每個(gè)小線程池里的線程僅用去請(qǐng)求的服務(wù),
打個(gè)比方:現(xiàn)在很不幸,積分服務(wù)掛了,會(huì)咋樣?
當(dāng)然會(huì)導(dǎo)致訂單服務(wù)里那個(gè)用來(lái)調(diào)用積分服務(wù)的線程都卡死不能工作了??!但由于訂單服務(wù)調(diào)用庫(kù)存服務(wù)、倉(cāng)儲(chǔ)服務(wù)的這兩個(gè)線程池都是正常工作的,所以這兩個(gè)服務(wù)不會(huì)受到任何影響。這個(gè)時(shí)候如果別人請(qǐng)求訂單服務(wù),訂單服務(wù)還是可以正常調(diào)用訂單服務(wù)還是可以正常調(diào)用庫(kù)存服務(wù)扣減庫(kù)存調(diào)用倉(cāng)儲(chǔ)服務(wù)通知發(fā)貨。只不過(guò)調(diào)用積分服務(wù)的時(shí)候,每次都會(huì)報(bào)錯(cuò)。但是如果積分服務(wù)都掛了,每次調(diào)用都要去卡住幾秒鐘干啥呢?有意義嗎?當(dāng)然沒(méi)有!所以我們直接對(duì)積分服務(wù)熔斷不就得了,比如在5分鐘內(nèi)請(qǐng)求積分服務(wù)直接就返回了,不要去走網(wǎng)絡(luò)請(qǐng)求卡住幾秒鐘,這個(gè)過(guò)程,就是所謂的熔斷!
那人家又說(shuō),兄弟,積分服務(wù)掛了你就熔斷,好歹你干點(diǎn)兒什么??!別啥都不干就直接返回啊?沒(méi)問(wèn)題,咱們就來(lái)個(gè)降級(jí):每次調(diào)用積分服務(wù),你就在數(shù)據(jù)庫(kù)里記錄一條消息,說(shuō)給某某用戶增加了多少積分,因?yàn)榉e分服務(wù)掛了,導(dǎo)致沒(méi)增加成功!這樣等積分服務(wù)恢復(fù)了,你可以根據(jù)這些記錄手工加一下積分。這個(gè)過(guò)程,就是所謂的降級(jí)。為幫助大家更直觀的理解,接下來(lái)用一張圖,梳理一下Hystrix隔離、熔斷和降級(jí)的全流程:

七:SpringCloud核心組件:zull
Zuul:微服務(wù)網(wǎng)關(guān),這個(gè)組件是負(fù)責(zé)網(wǎng)絡(luò)路由的!
什么事網(wǎng)絡(luò)路由?
假設(shè)你后臺(tái)部署了幾百個(gè)服務(wù),現(xiàn)在有個(gè)前端兄弟,人家請(qǐng)求是直接從瀏覽器那兒發(fā)過(guò)來(lái)的。打個(gè)比方:人家要請(qǐng)求一下庫(kù)存服務(wù),你難道還讓人家記著這服務(wù)的名字叫做inventory-service?部署在5臺(tái)機(jī)器上?就算人家肯記住這一個(gè),你后臺(tái)可有幾百個(gè)服務(wù)的名稱和地址呢?難不成人家請(qǐng)求一個(gè),就得記住一個(gè)?你要這樣玩兒,那就是中美合拍,文體開花了!
上面這種情況,壓根兒是不現(xiàn)實(shí)的。所以一般微服務(wù)架構(gòu)中都必然會(huì)設(shè)計(jì)一個(gè)網(wǎng)關(guān)在里面,像android、ios、pc前端、微信小程序、H5等等,不用去關(guān)心后端有幾百個(gè)服務(wù),就知道有一個(gè)網(wǎng)關(guān),所有請(qǐng)求都往網(wǎng)關(guān)走,網(wǎng)關(guān)會(huì)根據(jù)請(qǐng)求中的一些特征,將請(qǐng)求轉(zhuǎn)發(fā)給后端的各個(gè)服務(wù)。
而且有一個(gè)網(wǎng)關(guān)之后,還有很多好處,比如可以做統(tǒng)一的降級(jí)、限流、認(rèn)證授權(quán)、安全,等等。
總結(jié)一下SpringCloud結(jié)果核心組件:
Eureka:個(gè)服務(wù)啟動(dòng)時(shí),Eureka會(huì)將服務(wù)注冊(cè)到EurekaService,并且EurakeClient還可以返回過(guò)來(lái)從EurekaService拉去注冊(cè)表,從而知道服務(wù)在哪里
Ribbon:服務(wù)間發(fā)起請(qǐng)求的時(shí)候,基于Ribbon服務(wù)做到負(fù)載均衡,從一個(gè)服務(wù)的對(duì)臺(tái)機(jī)器中選擇一臺(tái)
Feign:基于fegin的動(dòng)態(tài)代理機(jī)制,根據(jù)注解和選擇機(jī)器,拼接Url地址,發(fā)起請(qǐng)求
Hystrix:發(fā)起的請(qǐng)求是通過(guò)Hystrix的線程池來(lái)走,不同的服走不同的線程池,實(shí)現(xiàn)了不同的服務(wù)調(diào)度隔離,避免服務(wù)雪崩的問(wèn)題?
Zuul:如果前端后端移動(dòng)端調(diào)用后臺(tái)系統(tǒng),統(tǒng)一走zull網(wǎng)關(guān)進(jìn)入,有zull網(wǎng)關(guān)轉(zhuǎn)發(fā)請(qǐng)求給對(duì)應(yīng)的服務(wù)
Spring Cloud的5個(gè)核心組件通過(guò)一張圖串聯(lián)起來(lái)
