鏈接:https://www.zhihu.com/question/283286745/answer/763040709
著作權(quán)歸作者所有陨界。商業(yè)轉(zhuǎn)載請聯(lián)系作者獲得授權(quán)议蟆,非商業(yè)轉(zhuǎn)載請注明出處菱属。
SpringCloud GitHub Demo(看完文章的同學可以自己練手玩玩):
https://github.com/ZhongFuCheng3y/msc-Demo
項目結(jié)構(gòu)圖:
二、集群/分布式/微服務(wù)/SOA是什么担巩?
像我這種技術(shù)小白讨衣,看到這些詞(集群/分布式/微服務(wù)/SOA)的時候换棚,感覺就是遙不可及的(高大尚的技術(shù)!反镇!)固蚤。就好像剛學Java面向?qū)ο蟮臅r候,在論壇上翻閱資料的時候歹茶,無意看到"面向切面編程"夕玩,也認為這是遙不可及的(高大尚的技術(shù)!惊豺!)风秤。
但真正接觸到"面向切面編程"的時候,發(fā)現(xiàn)原來就是如此啊扮叨,也沒什么大不了的。只不過當時被它的名字給唬住了...
不知道各位在剛接觸這些名字集群/分布式/微服務(wù)/SOA的時候领迈,有沒有被唬住了呢彻磁??
下面我就簡單說說這些名詞的意思
2.1什么是集群
以下內(nèi)容來源維基百科:
計算機集群簡稱集群是一種計算機系統(tǒng)狸捅,它通過一組松散集成的計算機軟件和/或硬件連接起來高度緊密地協(xié)作完成計算工作衷蜓。在某種意義上,他們可以被看作是一臺計算機尘喝。集群系統(tǒng)中的單個計算機通常稱為節(jié)點磁浇,通常通過局域網(wǎng)連接,但也有其它的可能連接方式朽褪。集群計算機通常用來改進單個計算機的計算速度和/或可靠性置吓。一般情況下集群計算機比單個計算機,比如工作站或超級計算機性能價格比要高得多
集群技術(shù)特點:
通過多臺計算機完成同一個工作缔赠,達到更高的效率衍锚。
兩機或多機內(nèi)容、工作過程等完全一樣嗤堰。如果一臺死機戴质,另一臺可以起作用。
在維基百科上說得也挺明白的了,我來舉個例子吧告匠。
小周在公司寫Java程序戈抄,但公司業(yè)務(wù)在發(fā)展,一個Java開發(fā)者可能忙不過來后专,小周有的時候也得請個假呀划鸽。于是請了3y過去一起做Java開發(fā)。平時小周和3y就寫Java程序行贪,但3y可能有事要回學校一趟漾稀。沒事,公司還有小周做Java開發(fā)呢建瘫,公司開發(fā)還能繼續(xù)運作崭捍。
3y跟小周都是做Java開發(fā)。
3y來了啰脚,小周的工作可以分擔一些殷蛇。
3y請假了,還有小周在呢橄浓。
我寫了一個910便利網(wǎng)發(fā)布到服務(wù)器去了粒梦,現(xiàn)在越來越多的人訪問了,訪問有點慢荸实,怎么辦匀们??准给?很簡單泄朴,(只有充錢才能變強),加配置吧(加cpu露氮,加內(nèi)存)祖灰。升級完配置之后,訪問人數(shù)越來越多畔规,于是發(fā)現(xiàn)又不禁用啦局扶,在這臺機器上加配置已經(jīng)解決不了了,怎么辦叁扫?三妈??很簡單莫绣,(只有充錢才能變強)沈跨,我再買一臺服務(wù)器,將910便利網(wǎng)也發(fā)布到新買的這臺服務(wù)器上去兔综。
特點:
這兩臺服務(wù)器都是運行同一個系統(tǒng)--->910便利網(wǎng)
好處:
本來只有一臺機器處理訪問饿凛,現(xiàn)在有兩臺機器處理訪問了狞玛,分擔了壓力。
如果其中一臺忘記繳費了涧窒,暫時用不了了心肪。沒關(guān)系,還有另一臺可以用呢纠吴。
集群:同一個業(yè)務(wù)硬鞍,部署在多個服務(wù)器上(不同的服務(wù)器運行同樣的代碼,干同一件事)
2.2什么是分布式
以下內(nèi)容來源維基百科:
分布式系統(tǒng)是一組計算機戴已,通過網(wǎng)絡(luò)相互連接傳遞消息與通信后并協(xié)調(diào)它們的行為而形成的系統(tǒng)固该。組件之間彼此進行交互以實現(xiàn)一個共同的目標。
我也來舉個例子來說明一下吧:
現(xiàn)在公司有小周和3y一起做Java開發(fā)糖儡,做Java開發(fā)一般jQuery伐坏,AJAX都能寫一點,所以這些活都由我們來干握联“裆唬可是呢贡羔,3y對前端不是很熟沉颂,有的時候調(diào)試半天都調(diào)不出來促脉。老板認為3y是真的菜!于是讓小周專門來處理前端的事情代芜。這樣3y就高興了埠褪,可以專心寫自己的Java,前端就專門交由小周負責了挤庇。于是组橄,小周和3y就變成了協(xié)作開發(fā)。
3y對前端不熟(能寫出來)罚随,但在調(diào)試的時候可能會花費很多時間
小周來專門做前端的事,3y可以專心寫自己的Java程序了羽资。
都是為了項目正常運行以及迭代淘菩。
我的910便利網(wǎng)已經(jīng)部署到兩臺服務(wù)器去了,但是越來越多的人去訪問⊥郎現(xiàn)在也逐漸承受不住啦潮改。那現(xiàn)在怎么辦啊腹暖?汇在?那繼續(xù)充錢變強?脏答?作為一個理智的我糕殉,肯定得想想是哪里有問題∧豆恚現(xiàn)在910便利網(wǎng)的模塊有好幾個,全都丟在同一個Tomcat里邊阿蝶。
其實有些模塊的訪問是很低的(比如后臺管理)雳锋,那我可不可以這樣做:將每個模塊抽取獨立出來,訪問量大的模塊用好的服務(wù)器裝著羡洁,沒啥人訪問的模塊用差的服務(wù)器裝著玷过。這樣的好處是:一、資源合理利用了(沒人訪問的模塊用性能差的服務(wù)器筑煮,訪問量大的模塊單獨提升性能就好了)辛蚊。二、耦合度降低了:每個模塊獨立出來真仲,各干各的事(專業(yè)的人做專業(yè)的事)袋马,便于擴展
特點:
將910便利網(wǎng)的功能拆分,模塊之間獨立袒餐,在使用的時候再將這些獨立的模塊組合起來就是一個系統(tǒng)了飞蛹。
好處:
模塊之間獨立,各做各的事灸眼,便于擴展卧檐,復用性高
高吞吐量。某個任務(wù)需要一個機器運行10個小時焰宣,將該任務(wù)用10臺機器的分布式跑(將這個任務(wù)拆分成10個小任務(wù))霉囚,可能2個小時就跑完了
分布式:一個業(yè)務(wù)分拆多個子業(yè)務(wù),部署在不同的服務(wù)器上(不同的服務(wù)器匕积,運行不同的代碼盈罐,為了同一個目的)
2.3集群/分布式
集群和分布式并不沖突,可以有分布式集群
現(xiàn)在3y的公司規(guī)模變大了闪唆,有5個小伙子寫Java盅粪,4個小伙子寫前端,2個小伙子做測試悄蕾,1個小伙子做DBA票顾。
Java,前端帆调,測試奠骄,DBA的關(guān)系看作是分布式的
5個Java看作是集群的(前端,測試同理)...
2.4分布式/微服務(wù)/SOA
其實我認為分布式/微服務(wù)/SOA這三個概念是差不多的番刊,了解了其中的一個含鳞,然后將自己的理解往上面套就好了。沒必要細分每個的具體概念~~(當然了芹务,我很期待有大佬可以在評論區(qū)留言說下自己的看法哈)
參考資料:
分布式與集群的區(qū)別是什么蝉绷?https://www.zhihu.com/question/20004877
分布式鸭廷、集群、微服務(wù)潜必、SOA 之間的區(qū)別https://blog.csdn.net/heatdeath/article/details/79038795
三靴姿、CAP理論
從上面所講的分布式概念我們已經(jīng)知道,分布式簡單理解就是:一個業(yè)務(wù)分拆多個子業(yè)務(wù)磁滚,部署在不同的服務(wù)器上
一般來說佛吓,一個子業(yè)務(wù)我們稱為節(jié)點。
如果你接觸過一些分布式的基礎(chǔ)概念垂攘,那肯定會聽過CAP這個理論维雇。就比如說:你學了MySQL的InnoDB存儲引擎相關(guān)知識,你肯定聽過ACID晒他!
首先吱型,我們來看一下CAP分別代表的是什么意思:
C:數(shù)據(jù)一致性(consistency)
所有節(jié)點擁有數(shù)據(jù)的最新版本
A:可用性(availability)
數(shù)據(jù)具備高可用性
P:分區(qū)容錯性(partition-tolerance)
容忍網(wǎng)絡(luò)出現(xiàn)分區(qū),分區(qū)之間網(wǎng)絡(luò)不可達陨仅。
下面有三個節(jié)點(它們是集群的)津滞,此時三個節(jié)點都能夠相互通信:
由于我們的系統(tǒng)是分布式的,節(jié)點之間的通信是通過網(wǎng)絡(luò)來進行的灼伤。只要是分布式系統(tǒng)触徐,那很有可能會出現(xiàn)一種情況:因為一些故障,使得有些節(jié)點之間不連通了狐赡,整個網(wǎng)絡(luò)就分成了幾塊區(qū)域撞鹉。
數(shù)據(jù)就散布在了這些不連通的區(qū)域中,這就叫分區(qū)
現(xiàn)在出現(xiàn)了網(wǎng)絡(luò)分區(qū)后颖侄,此時有一個請求過來了鸟雏,想要注冊一個賬戶。
此時我們節(jié)點一和節(jié)點三是不可通信的览祖,這就有了抉擇:
如果允許當前用戶注冊一個賬戶孝鹊,此時注冊的記錄數(shù)據(jù)只會在節(jié)點一和節(jié)點二或者節(jié)點二和節(jié)點三同步,因為節(jié)點一和節(jié)點三的記錄不能同步的展蒂。
這種情況其實就是選擇了可用性(availability)又活,拋棄了數(shù)據(jù)一致性(consistency)
如果不允許當前用戶注冊一個賬戶(就是要等到節(jié)點一和節(jié)點三恢復通信)。節(jié)點一和節(jié)點三一旦恢復通信玄货,我們就可以保證節(jié)點擁有的數(shù)據(jù)是最新版本。
這種情況其實就是拋棄了可用性(availability)悼泌,選擇了數(shù)據(jù)一致性(consistency)
3.1再次梳理一下CAP理論
一般我們說的分布式系統(tǒng)松捉,P:分區(qū)容錯性(partition-tolerance)這個是必需的,這是客觀存在的馆里。
CAP是無法完全兼顧的隘世,從上面的例子也可以看出可柿,我們可以選AP,也可以選CP丙者。但是复斥,要注意的是:不是說選了AP,C就完全拋棄了械媒。不是說選了CP目锭,A就完全拋棄了!
在CAP理論中纷捞,C所表示的一致性是強一致性(每個節(jié)點的數(shù)據(jù)都是最新版本)痢虹,其實一致性還有其他級別的:
弱一致性:弱一致性是相對于強一致性而言,它不保證總能得到最新的值主儡;
最終一致性(eventual consistency):放寬對時間的要求奖唯,在被調(diào)完成操作響應(yīng)后的某個時間點,被調(diào)多個節(jié)點的數(shù)據(jù)最終達成一致
可用性的值域可以定義成0到100%的連續(xù)區(qū)間糜值。
所以丰捷,CAP理論定義的其實是在容忍網(wǎng)絡(luò)分區(qū)的條件下,“強一致性”和“極致可用性”無法同時達到寂汇。
參考資料:
CAP理論中的P到底是個什么意思病往?https://www.zhihu.com/question/54105974
淺談分布式系統(tǒng)的基本問題:可用性與一致性:https://m.aliyun.com/yunqi/articles/2709
分布式系統(tǒng)的CAP理論:http://www.hollischuang.com/archives/666
為什么CAP理論在舍棄P的情況下,可以有完美的CA健无?https://www.zhihu.com/question/285878189
不懂點CAP理論荣恐,你好意思說你是做分布式的嗎?http://www.yunweipai.com/archives/8432.html
擴展閱讀:
淺談分布式事務(wù):https://m.aliyun.com/yunqi/articles/230242
四累贤、SpringCloud就是這么簡單
相信大家讀到這里叠穆,對分布式/微服務(wù)已經(jīng)有一定的了解了,其實單從概念來說臼膏,是非常容易理解的硼被。只是很可能被它的名字給唬住了。
下面我就來講講SpringCloud最基礎(chǔ)的知識~
4.1為什么需要SpringCloud渗磅?
前面也講了嚷硫,從分布式/微服務(wù)的角度而言:就是把我們一大的項目,分解成多個小的模塊始鱼。這些小的模塊組合起來仔掸,完成功能。
舉個可能不太恰當?shù)睦?現(xiàn)實可能不會這么拆分医清,但意思到位就好了):
拆分出多個模塊以后起暮,就會出現(xiàn)各種各樣的問題,而SpringCloud提供了一整套的解決方案会烙!
注:這些模塊是獨立成一個子系統(tǒng)的(不同主機)负懦。
SpringCloud的基礎(chǔ)功能:
服務(wù)治理: Spring Cloud Eureka
客戶端負載均衡: Spring Cloud Ribbon
服務(wù)容錯保護: Spring Cloud Hystrix
聲明式服務(wù)調(diào)用: Spring Cloud Feign
API網(wǎng)關(guān)服務(wù):Spring Cloud Zuul
分布式配置中心: Spring Cloud Config
SpringCloud的高級功能(本文不講):
消息總線: Spring Cloud Bus
消息驅(qū)動的微服務(wù): Spring Cloud Stream
分布式服務(wù)跟蹤: Spring Cloud Sleuth
五筒捺、引出Eureka
那會出現(xiàn)什么問題呢?纸厉?首當其沖的就是子系統(tǒng)之間的通訊問題系吭。子系統(tǒng)與子系統(tǒng)之間不是在同一個環(huán)境下,那就需要遠程調(diào)用颗品。遠程調(diào)用可能就會想到httpClient肯尺,WebService等等這些技術(shù)來實現(xiàn)。
既然是遠程調(diào)用抛猫,就必須知道ip地址蟆盹,我們可能有以下的場景。
功能實現(xiàn)一:A服務(wù)需要調(diào)用B服務(wù)
在A服務(wù)的代碼里面調(diào)用B服務(wù)闺金,顯式通過IP地址調(diào)用:http://123.123.123.123:8888/java3y/3
功能實現(xiàn)二:A服務(wù)調(diào)用B服務(wù)逾滥,B服務(wù)調(diào)用C服務(wù),C服務(wù)調(diào)用D服務(wù)
在A服務(wù)的代碼里面調(diào)用B服務(wù)败匹,顯式通過IP地址調(diào)用:http://123.123.123.123:8888/java3y/3寨昙,(同樣地)B->C,C->D
功能實現(xiàn)三:D服務(wù)調(diào)用B服務(wù)掀亩,B服務(wù)調(diào)用C服務(wù)
在D服務(wù)的代碼里面調(diào)用B服務(wù)舔哪,顯式通過IP地址調(diào)用:http://123.123.123.123:8888/java3y/3,(同樣地)B->C
.....等等等等
萬一槽棍,我們B服務(wù)的IP地址變了捉蚤,想想會出現(xiàn)什么問題:A服務(wù),D服務(wù)(等等)需要手動更新B服務(wù)的地址
在服務(wù)多的情況下,手動來維護這些靜態(tài)配置就是噩夢炼七!
為了解決微服務(wù)架構(gòu)中的服務(wù)實例維護問題(ip地址)缆巧, 產(chǎn)生了大量的服務(wù)治理框架和產(chǎn)品。 這些框架和產(chǎn)品的實現(xiàn)都圍繞著服務(wù)注冊與服務(wù)發(fā)現(xiàn)機制來完成對微服務(wù)應(yīng)用實例的自動化管理豌拙。
在SpringCloud中我們的服務(wù)治理框架一般使用的就是Eureka陕悬。
我們的問題:
現(xiàn)在有A、B按傅、C捉超、D四個服務(wù),它們之間會互相調(diào)用(而且IP地址很可能會發(fā)生變化)唯绍,一旦某個服務(wù)的IP地址變了拼岳,那服務(wù)中的代碼要跟著變,手動維護這些靜態(tài)配置(IP)非常麻煩况芒!
Eureka是這樣解決上面所說的情況的:
創(chuàng)建一個E服務(wù)惜纸,將A、B、C堪簿、D四個服務(wù)的信息都注冊到E服務(wù)上,E服務(wù)維護這些已經(jīng)注冊進來的信息
A皮壁、B椭更、C、D四個服務(wù)都可以拿到Eureka(服務(wù)E)那份注冊清單蛾魄。A虑瀑、B、C滴须、D四個服務(wù)互相調(diào)用不再通過具體的IP地址舌狗,而是通過服務(wù)名來調(diào)用!
拿到注冊清單--->注冊清單上有服務(wù)名--->自然就能夠拿到服務(wù)具體的位置了(IP)扔水。
其實簡單來說就是:代碼中通過服務(wù)名找到對應(yīng)的IP地址(IP地址會變痛侍,但服務(wù)名一般不會變)
5.1Eureka細節(jié)
Eureka專門用于給其他服務(wù)注冊的稱為Eureka Server(服務(wù)注冊中心),其余注冊到Eureka Server的服務(wù)稱為Eureka Client魔市。
在Eureka Server一般我們會這樣配置:
register-with-eureka: false? ? #false表示不向注冊中心注冊自己主届。
? ? fetch-registry: false? ? #false表示自己端就是注冊中心,我的職責就是維護服務(wù)實例待德,并不需要去檢索服務(wù)
Eureka Client分為服務(wù)提供者和服務(wù)消費者君丁。
但很可能,某服務(wù)既是服務(wù)提供者又是服務(wù)消費者将宪。
如果在網(wǎng)上看到SpringCloud的某個服務(wù)配置沒有"注冊"到Eureka-Server也不用過于驚訝(但是它是可以獲取Eureka服務(wù)清單的)
很可能只是作者把該服務(wù)認作為單純的服務(wù)消費者绘闷,單純的服務(wù)消費者無需對外提供服務(wù),也就無須注冊到Eureka中了
eureka:
? client:
? ? register-with-eureka: false? # 當前微服務(wù)不注冊到eureka中(消費端)
? ? service-url:
? ? ? defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
下面是Eureka的治理機制:
服務(wù)提供者
服務(wù)注冊:啟動的時候會通過發(fā)送REST請求的方式將自己注冊到Eureka Server上较坛,同時帶上了自身服務(wù)的一些元數(shù)據(jù)信息印蔗。
**服務(wù)續(xù)約:**在注冊完服務(wù)之后,服務(wù)提供者會維護一個心跳用來持續(xù)告訴Eureka Server: "我還活著 ” 燎潮、
服務(wù)下線:當服務(wù)實例進行正常的關(guān)閉操作時喻鳄,它會觸發(fā)一個服務(wù)下線的REST請求給Eureka Server, 告訴服務(wù)注冊中心:“我要下線了 ”。
服務(wù)消費者
獲取服務(wù):當我們啟動服務(wù)消費者的時候确封,它會發(fā)送一個REST請求給服務(wù)注冊中心除呵,來獲取上面注冊的服務(wù)清單
服務(wù)調(diào)用:服務(wù)消費者在獲取服務(wù)清單后,通過服務(wù)名可以獲得具體提供服務(wù)的實例名和該實例的元數(shù)據(jù)信息爪喘。在進行服務(wù)調(diào)用的時候颜曾,優(yōu)先訪問同處一個Zone中的服務(wù)提供方。
Eureka Server(服務(wù)注冊中心):
失效剔除:默認每隔一段時間(默認為60秒) 將當前清單中超時(默認為90秒)沒有續(xù)約的服務(wù)剔除出去秉剑。
自我保護:泛豪。EurekaServer 在運行期間,會統(tǒng)計心跳失敗的比例在15分鐘之內(nèi)是否低于85%(通常由于網(wǎng)絡(luò)不穩(wěn)定導致)。 Eureka Server會將當前的實例注冊信息保護起來诡曙, 讓這些實例不會過期臀叙,盡可能保護這些注冊信息。
最后价卤,我們就有了這張圖:
舉個例子:
3y跟女朋友去東站的東方寶泰逛街劝萤,但不知道東方寶泰有什么好玩的。于是就去物業(yè)搜了一下東方寶泰商戶清單慎璧,發(fā)現(xiàn)一樓有優(yōu)衣庫床嫌,二樓有星巴克,三樓有麥當勞胸私。
在優(yōu)衣庫旁邊厌处,有新開張的KFC,在墻壁打上了很大的標識“歡迎KFC入駐東方寶泰”岁疼。
商家們需要定時交物業(yè)費給物業(yè)阔涉。
物業(yè)維持東方寶泰的穩(wěn)定性。如果某個商家不想在東方寶泰運營了捷绒,告訴了物業(yè)洒敏。物業(yè)自然就會將其在東方寶泰商戶清單去除。
優(yōu)秀博文:
Spring Cloud Eureka詳解:https://blog.csdn.net/sunhuiliang85/article/details/76222517
《Spring Cloud Netflix》 -- 服務(wù)注冊和服務(wù)發(fā)現(xiàn)-Eureka 的使用:https://zhuanlan.zhihu.com/p/26472547
微服務(wù)架構(gòu):Eureka參數(shù)配置項詳解:https://www.cnblogs.com/fangfuhai/p/7070325.html
六疙驾、引出RestTemplate和Ribbon
通過Eureka服務(wù)治理框架凶伙,我們可以通過服務(wù)名來獲取具體的服務(wù)實例的位置了(IP)。一般在使用SpringCloud的時候不需要自己手動創(chuàng)建HttpClient來進行遠程調(diào)用它碎。
可以使用Spring封裝好的RestTemplate工具類函荣,使用起來很簡單:
// 傳統(tǒng)的方式,直接顯示寫死IP是不好的扳肛!
? ? //private static final String REST_URL_PREFIX = "http://localhost:8001";
// 服務(wù)實例名
? ? private static final String REST_URL_PREFIX = "http://MICROSERVICECLOUD-DEPT";
? ? /**
? ? * 使用 使用restTemplate訪問restful接口非常的簡單粗暴無腦傻挂。 (url, requestMap,
? ? * ResponseBean.class)這三個參數(shù)分別代表 REST請求地址、請求參數(shù)挖息、HTTP響應(yīng)轉(zhuǎn)換被轉(zhuǎn)換成的對象類型金拒。
? ? */
? ? @Autowired
? ? private RestTemplate restTemplate;
? ? @RequestMapping(value = "/consumer/dept/add")
? ? public boolean add(Dept dept) {
? ? ? ? return restTemplate.postForObject(REST_URL_PREFIX + "/dept/add", dept, Boolean.class);
? ? }
為了實現(xiàn)服務(wù)的高可用,我們可以將服務(wù)提供者集群套腹。比如說绪抛,現(xiàn)在一個秒殺系統(tǒng)設(shè)計出來了,準備上線了电禀。在11月11號時為了能夠支持高并發(fā)幢码,我們開多臺機器來支持并發(fā)量。
現(xiàn)在想要這三個秒殺系統(tǒng)合理攤分用戶的請求(專業(yè)來說就是負載均衡)尖飞,可能你會想到nginx症副。
其實SpringCloud也支持的負載均衡功能店雅,只不過它是客戶端的負載均衡,這個功能實現(xiàn)就是Ribbon贞铣!
負載均衡又區(qū)分了兩種類型:
客戶端負載均衡(Ribbon)
服務(wù)實例的清單在客戶端闹啦,客戶端進行負載均衡算法分配。
(從上面的知識我們已經(jīng)知道了:客戶端可以從Eureka Server中得到一份服務(wù)清單辕坝,在發(fā)送請求時通過負載均衡算法亥揖,在多個服務(wù)器之間選擇一個進行訪問)
服務(wù)端負載均衡(Nginx)
服務(wù)實例的清單在服務(wù)端,服務(wù)器進行負載均衡算法分配
所以圣勒,我們的圖可以畫成這樣:
6.1Ribbon細節(jié)
Ribbon是支持負載均衡,默認的負載均衡策略是輪詢摧扇,我們也是可以根據(jù)自己實際的需求自定義負載均衡策略的圣贸。
@Configuration
public class MySelfRule
{
@Bean
public IRule myRule()
{
//return new RandomRule();// Ribbon默認是輪詢,我自定義為隨機
//return new RoundRobinRule();// Ribbon默認是輪詢扛稽,我自定義為隨機
return new RandomRule_ZY();// 我自定義為每臺機器5次
}
}
實現(xiàn)起來也很簡單:繼承AbstractLoadBalancerRule類吁峻,重寫public Server choose(ILoadBalancer lb, Object key)即可。
SpringCloud 在CAP理論是選擇了AP的在张,在Ribbon中還可以配置重試機制的(有興趣的同學可以去搜搜)~
舉個例子:
3y跟女朋友過了幾個月用含,又去東方寶泰了。由于記性不好帮匾,又去物業(yè)那弄了一份東方寶泰商戶清單啄骇。
這次看到東方寶泰又開了一間麥當勞,一間在二樓瘟斜,一間在三樓缸夹。原來生意太好了,為了能提高用戶體驗螺句,在二樓多開了一間麥當勞虽惭。
這時,3y問女朋友:“去哪間麥當勞比較好蛇尚?要不我們拋硬幣決定芽唇?”3y女朋友說:”你是不是傻,肯定哪間近去哪間啊“
優(yōu)秀博文:
擼一擼Spring Cloud Ribbon的原理-負載均衡策略:https://www.cnblogs.com/kongxianghai/p/8477781.html
七取劫、引出Hystrix
到目前為止匆笤,我們的服務(wù)看起來好像挺好的了:能夠根據(jù)服務(wù)名來遠程調(diào)用其他的服務(wù),可以實現(xiàn)客戶端的負載均衡谱邪。
但是疚膊,如果我們在調(diào)用多個遠程服務(wù)時,某個服務(wù)出現(xiàn)延遲虾标,會怎么樣寓盗?灌砖?
在高并發(fā)的情況下,由于單個服務(wù)的延遲傀蚌,可能導致所有的請求都處于延遲狀態(tài)基显,甚至在幾秒鐘就使服務(wù)處于負載飽和的狀態(tài),資源耗盡善炫,直到不可用撩幽,最終導致這個分布式系統(tǒng)都不可用,這就是“雪崩”箩艺。
針對上述問題窜醉, Spring Cloud Hystrix實現(xiàn)了斷路器、線程隔離等一系列服務(wù)保護功能艺谆。
Fallback(失敗快速返回):當某個服務(wù)單元發(fā)生故障(類似用電器發(fā)生短路)之后榨惰,通過斷路器的故障監(jiān)控(類似熔斷保險絲),向調(diào)用方返回一個錯誤響應(yīng)静汤, 而不是長時間的等待琅催。這樣就不會使得線程因調(diào)用故障服務(wù)被長時間占用不釋放,避免了故障在分布式系統(tǒng)中的蔓延虫给。
資源/依賴隔離(線程池隔離):它會為每一個依賴服務(wù)創(chuàng)建一個獨立的線程池藤抡,這樣就算某個依賴服務(wù)出現(xiàn)延遲過高的情況,也只是對該依賴服務(wù)的調(diào)用產(chǎn)生影響抹估, 而不會拖慢其他的依賴服務(wù)缠黍。
Hystrix提供幾個熔斷關(guān)鍵參數(shù):滑動窗口大小(20)药蜻、 熔斷器開關(guān)間隔(5s)嫁佳、錯誤率(50%)
每當20個請求中,有50%失敗時谷暮,熔斷器就會打開蒿往,此時再調(diào)用此服務(wù),將會直接返回失敗湿弦,不再調(diào)遠程服務(wù)瓤漏。
直到5s鐘之后,重新檢測該觸發(fā)條件颊埃,判斷是否把熔斷器關(guān)閉蔬充,或者繼續(xù)打開。
Hystrix還有請求合并班利、請求緩存這樣強大的功能饥漫,在此我就不具體說明了,有興趣的同學可繼續(xù)深入學習~
7.1Hystrix儀表盤
Hystrix儀表盤:它主要用來實時監(jiān)控Hystrix的各項指標信息罗标。通過Hystrix Dashboard反饋的實時信息庸队,可以幫助我們快速發(fā)現(xiàn)系統(tǒng)中存在的問題积蜻,從而及時地采取應(yīng)對措施。
啟動時的頁面:
監(jiān)控單服務(wù)的頁面:
我們現(xiàn)在的服務(wù)是這樣的:
除了可以開啟單個實例的監(jiān)控頁面之外彻消,還有一個監(jiān)控端點/turbine.stream是對集群使用的竿拆。 從端點的命名中,可以引入Turbine, 通過它來匯集監(jiān)控信息宾尚,并將聚合后的信息提供給 HystrixDashboard 來集中展示和監(jiān)控丙笋。
舉個例子:
3y和女朋友決定去萬達玩,去到萬達的停車場發(fā)現(xiàn)在負一層已經(jīng)大大寫上“負一層已停滿煌贴,請下負二層御板,負二層空余停車位還有100個!”
這時牛郑,3y就跟女朋友說:“萬達停車場是做得挺好的怠肋,如果它沒有直接告知我負一層已滿,可能我就去負一層找位置了井濒,要是一堆人跑去負一層但都找不到車位的話,恐怕就塞死了”列林。3y接著說:“看停車位的狀態(tài)也做得不錯瑞你,在停車位上頭有一個感應(yīng)(監(jiān)控),如果是紅色就代表已被停了希痴,如果是綠色就說明停車位是空的”者甲。
3y女朋友不屑的說:“你話是真的多”
參考資料:
Hystrix ,為什么說它是每個系統(tǒng)不可或缺的開源框架砌创?https://zhuanlan.zhihu.com/p/34304136
深入理解Hystrix之文檔翻譯:https://zhuanlan.zhihu.com/p/28523060
談?wù)勎覍Ψ?wù)熔斷虏缸、服務(wù)降級的理解:https://blog.csdn.net/guwei9111986/article/details/51649240
Hystrix幾篇文章《青芒》:https://segmentfault.com/u/yedge/articles
八、引出Feign
上面已經(jīng)介紹了Ribbon和Hystrix了嫩实,可以發(fā)現(xiàn)的是:他倆作為基礎(chǔ)工具類框架廣泛地應(yīng)用在各個微服務(wù)的實現(xiàn)中刽辙。我們會發(fā)現(xiàn)對這兩個框架的使用幾乎是同時出現(xiàn)的。
為了簡化我們的開發(fā)甲献,Spring Cloud Feign出現(xiàn)了宰缤!它基于 Netflix Feign 實現(xiàn),整合了 Spring Cloud Ribbon 與 Spring Cloud Hystrix, 除了整合這兩者的強大功能之外晃洒,它還提 供了聲明式的服務(wù)調(diào)用(不再通過RestTemplate)慨灭。
Feign是一種聲明式、模板化的HTTP客戶端球及。在Spring Cloud中使用Feign, 我們可以做到使用HTTP請求遠程服務(wù)時能與調(diào)用本地方法一樣的編碼體驗氧骤,開發(fā)者完全感知不到這是遠程方法,更感知不到這是個HTTP請求吃引。
下面就簡單看看Feign是怎么優(yōu)雅地實現(xiàn)遠程調(diào)用的:
服務(wù)綁定:
// value --->指定調(diào)用哪個服務(wù)
// fallbackFactory--->熔斷器的降級提示
@FeignClient(value = "MICROSERVICECLOUD-DEPT", fallbackFactory = DeptClientServiceFallbackFactory.class)
public interface DeptClientService {
? ? // 采用Feign我們可以使用SpringMVC的注解來對服務(wù)進行綁定筹陵!
? ? @RequestMapping(value = "/dept/get/{id}", method = RequestMethod.GET)
? ? public Dept get(@PathVariable("id") long id);
? ? @RequestMapping(value = "/dept/list", method = RequestMethod.GET)
? ? public List<Dept> list();
? ? @RequestMapping(value = "/dept/add", method = RequestMethod.POST)
? ? public boolean add(Dept dept);
}
Feign中使用熔斷器:
/**
* Feign中使用斷路器
* 這里主要是處理異常出錯的情況(降級/熔斷時服務(wù)不可用刽锤,fallback就會找到這里來)
*/
@Component // 不要忘記添加,不要忘記添加
public class DeptClientServiceFallbackFactory implements FallbackFactory<DeptClientService> {
? ? @Override
? ? public DeptClientService create(Throwable throwable) {
? ? ? ? return new DeptClientService() {
? ? ? ? ? ? @Override
? ? ? ? ? ? public Dept get(long id) {
? ? ? ? ? ? ? ? return new Dept().setDeptno(id).setDname("該ID:" + id + "沒有沒有對應(yīng)的信息,Consumer客戶端提供的降級信息,此刻服務(wù)Provider已經(jīng)關(guān)閉")
? ? ? ? ? ? ? ? ? ? ? ? .setDb_source("no this database in MySQL");
? ? ? ? ? ? }
? ? ? ? ? ? @Override
? ? ? ? ? ? public List<Dept> list() {
? ? ? ? ? ? ? ? return null;
? ? ? ? ? ? }
? ? ? ? ? ? @Override
? ? ? ? ? ? public boolean add(Dept dept) {
? ? ? ? ? ? ? ? return false;
? ? ? ? ? ? }
? ? ? ? };
? ? }
}
調(diào)用:
九惶翻、引出Zuul
基于上面的學習姑蓝,我們現(xiàn)在的架構(gòu)很可能會設(shè)計成這樣:
這樣的架構(gòu)會有兩個比較麻煩的問題:
路由規(guī)則與服務(wù)實例的維護間題:外層的負載均衡(nginx)需要維護所有的服務(wù)實例清單(圖上的OpenService)
簽名校驗、 登錄校驗冗余問題:為了保證對外服務(wù)的安全性吕粗, 我們在服務(wù)端實現(xiàn)的微服務(wù)接口纺荧,往往都會有一定的權(quán)限校驗機制,但我們的服務(wù)是獨立的颅筋,我們不得不在這些應(yīng)用中都實現(xiàn)這樣一套校驗邏輯宙暇,這就會造成校驗邏輯的冗余。
還是畫個圖來理解一下吧:
每個服務(wù)都有自己的IP地址议泵,Nginx想要正確請求轉(zhuǎn)發(fā)到服務(wù)上占贫,就必須維護著每個服務(wù)實例的地址!
更是災難的是:這些服務(wù)實例的IP地址還有可能會變先口,服務(wù)之間的劃分也很可能會變型奥。
http://123.123.123.123
http://123.123.123.124
http://123.123.123.125
http://123.123.123.126
http://123.123.123.127
購物車和訂單模塊都需要用戶登錄了才可以正常訪問,基于現(xiàn)在的架構(gòu)碉京,只能在購物車和訂單模塊都編寫校驗邏輯厢汹,這無疑是冗余的代碼。
為了解決上面這些常見的架構(gòu)問題谐宙,API網(wǎng)關(guān)的概念應(yīng)運而生烫葬。在SpringCloud中了提供了基于Netfl ix Zuul實現(xiàn)的API網(wǎng)關(guān)組件Spring Cloud Zuul。
Spring Cloud Zuul是這樣解決上述兩個問題的:
SpringCloud Zuul通過與SpringCloud Eureka進行整合凡蜻,將自身注冊為Eureka服務(wù)治理下的應(yīng)用搭综,同時從Eureka中獲得了所有其他微服務(wù)的實例信息。外層調(diào)用都必須通過API網(wǎng)關(guān)划栓,使得將維護服務(wù)實例的工作交給了服務(wù)治理框架自動完成兑巾。
在API網(wǎng)關(guān)服務(wù)上進行統(tǒng)一調(diào)用來對微服務(wù)接口做前置過濾,以實現(xiàn)對微服務(wù)接口的攔截和校驗。
Zuul天生就擁有線程隔離和斷路器的自我保護功能,以及對服務(wù)調(diào)用的客戶端負載均衡功能致盟。也就是說:Zuul也是支持Hystrix和Ribbon糜颠。
關(guān)于Zuul還有很多知識點(由于篇幅問題,這里我就不細說了):
路由匹配(動態(tài)路由)
過濾器實現(xiàn)(動態(tài)過濾器)
默認會過濾掉Cookie與敏感的HTTP頭信息(額外配置)
9.1可能對Zuul的疑問
Zuul支持Ribbon和Hystrix,也能夠?qū)崿F(xiàn)客戶端的負載均衡。我們的Feign不也是實現(xiàn)客戶端的負載均衡和Hystrix的嗎?既然Zuul已經(jīng)能夠?qū)崿F(xiàn)了称诗,那我們的Feign還有必要嗎?
或者可以這樣理解:
zuul是對外暴露的唯一接口相當于路由的是controller的請求头遭,而Ribbonhe和Fegin路由了service的請求
zuul做最外層請求的負載均衡 寓免,而Ribbon和Fegin做的是系統(tǒng)內(nèi)部各個微服務(wù)的service的調(diào)用的負載均衡
有了Zuul癣诱,還需要Nginx嗎?他倆可以一起使用嗎袜香?
我的理解:Zuul和Nginx是可以一起使用的(畢竟我們的Zuul也是可以搭成集群來實現(xiàn)高可用的)撕予,要不要一起使用得看架構(gòu)的復雜度了(業(yè)務(wù))~~~
參考資料:
微服務(wù)與API網(wǎng)關(guān)(上): 為什么需要API網(wǎng)關(guān)?:http://blog.didispace.com/hzf-ms-apigateway-1/
談?wù)?API 網(wǎng)關(guān):http://www.reibang.com/p/b52a2773e75f
談?wù)勎⒎?wù)中的 API 網(wǎng)關(guān)(API Gateway):https://www.cnblogs.com/savorboard/p/api-gateway.html
API網(wǎng)關(guān)性能比較:NGINX vs. ZUUL vs. Spring Cloud Gateway :http://www.360doc.com/content/18/0208/05/46368139_728502763.shtml
談API網(wǎng)關(guān)的背景蜈首、架構(gòu)以及落地方案:http://www.infoq.com/cn/news/2016/07/API-background-architecture-floo
zuul和nginx:https://zhuanlan.zhihu.com/p/37385481
十实抡、引出SpringCloud Config
隨著業(yè)務(wù)的擴展,我們的服務(wù)會越來越多欢策,越來越多吆寨。每個服務(wù)都有自己的配置文件。
既然是配置文件踩寇,給我們配置的東西啄清,那難免會有些改動的。
比如我們的Demo中俺孙,每個服務(wù)都寫上相同的配置文件辣卒。萬一我們有一天,配置文件中的密碼需要更換了睛榄,那就得三個都要重新更改荣茫。
在分布式系統(tǒng)中,某一個基礎(chǔ)服務(wù)信息變更懈费,都很可能會引起一系列的更新和重啟
Spring Cloud Config項目是一個解決分布式系統(tǒng)的配置管理方案计露。它包含了Client和Server兩個部分博脑,server提供配置文件的存儲憎乙、以接口的形式將配置文件的內(nèi)容提供出去,client通過接口獲取數(shù)據(jù)叉趣、并依據(jù)此數(shù)據(jù)初始化自己的應(yīng)用泞边。
簡單來說,使用Spring Cloud Config就是將配置文件放到統(tǒng)一的位置管理(比如GitHub)疗杉,客戶端通過接口去獲取這些配置文件阵谚。
在GitHub上修改了某個配置文件,應(yīng)用加載的就是修改后的配置文件烟具。
SpringCloud Config其他的知識:
在SpringCloud Config的服務(wù)端梢什, 對于配置倉庫的默認實現(xiàn)采用了Git,我們也可以配置SVN朝聋。
配置文件內(nèi)的信息加密和解密
修改了配置文件嗡午,希望不用重啟來動態(tài)刷新配置,配合Spring Cloud Bus 使用~
使用SpringCloud Config可能的疑問:application.yml和 bootstrap.yml區(qū)別
https://www.cnblogs.com/BlogNetSpace/p/8469033.html
總結(jié)
本文主要寫了SpringCloud的基礎(chǔ)知識冀痕,希望大家看完能有所幫助~
SpringCloud的資料也很多荔睹,我整理一些我認為比較好狸演,想要深入的同學不妨看看下邊的資源~~~
SpringCloud系列文章參考資料:
史上最簡單的 SpringCloud 教程 | 終章https://blog.csdn.net/forezp/article/details/70148833
Spring Cloud基礎(chǔ)教程《程序員DD》http://blog.didispace.com/Spring-Cloud%E5%9F%BA%E7%A1%80%E6%95%99%E7%A8%8B/
Spring Cloud 系列文章《純潔的微笑》:http://www.ityouknow.com/spring-cloud.html
SpringCloud系列文章:https://www.cnblogs.com/woshimrf/tag/SpringCloud/
SpringCloud系列文章《狂小白》:https://www.cnblogs.com/huangjuncong/tag/SpringCloud/
SpringCloud官方文檔:http://projects.spring.io/spring-cloud/
Spring Cloud 中文文檔:https://springcloud.cc/spring-cloud-dalston.html#_appendix_compendium_of_configuration_properties
參考書籍:
《SpringCloud 微服務(wù)實戰(zhàn)》
SpringCloud GitHub Demo(看完文章的同學可以自己練手玩玩,寫好了ReadMe了):
https://github.com/ZhongFuCheng3y/msc-Demo
涵蓋Java后端所有知識點的開源項目(已有5.8K star):https://github.com/ZhongFuCheng3y/3y
如果大家想要實時關(guān)注我更新的文章以及分享的干貨的話僻他,微信搜索Java3y
PDF文檔的內(nèi)容均為手打宵距,有任何的不懂都可以直接來問我(公眾號有我的聯(lián)系方式)。
收藏等于白嫖吨拗,點贊才是真情满哪!