- 微服务架构
>> 微服務(wù)架構(gòu)基礎(chǔ)
~ 微服務(wù)概念
微服務(wù)架構(gòu)是一種架構(gòu)概念,旨在通過(guò)將功能分解到各個(gè)離散的服務(wù)中,以實(shí)現(xiàn)對(duì)解決方案的解耦;它的主要作用是將功能分解離散到各個(gè)服務(wù)中,從而降低系統(tǒng)的耦合性,并添加更靈活的服務(wù)支持;
把一個(gè)大型的單體應(yīng)用和服務(wù)拆分成數(shù)個(gè)微服務(wù);
~ 微服務(wù)架構(gòu)與傳統(tǒng)架構(gòu)的區(qū)別
1、系統(tǒng)架構(gòu)需要遵循3個(gè)標(biāo)準(zhǔn):
- 提高敏捷性:及時(shí)響應(yīng)業(yè)務(wù)需求;
- 提升用戶體驗(yàn):減少用戶流失;
- 降低成本:降低增加產(chǎn)品、客戶、業(yè)務(wù)方案的成本;
2、傳統(tǒng)式開(kāi)發(fā)(單體式開(kāi)發(fā)):將所有的功能打包在一個(gè)war包里,基本沒(méi)有外部依賴(除了容器),部署在一個(gè)JavaEE容器(Tomcat、JBoss、Weblogic)里面,包含MVC的所有邏輯;
優(yōu)點(diǎn):
- 開(kāi)發(fā)簡(jiǎn)單,集中式管理;
- 基本不會(huì)重復(fù)開(kāi)發(fā);
- 功能都在本地(整個(gè)應(yīng)用程序部署在一臺(tái)服務(wù)器),沒(méi)有分布式的管理和調(diào)用的消耗;
缺點(diǎn):
- 效率低:開(kāi)發(fā)都在同一個(gè)項(xiàng)目里改代碼,相互等待,沖突不斷;
- 維護(hù)難:代碼功能耦合在一起;
- 不靈活:構(gòu)建時(shí)間長(zhǎng),任何小修改都要重構(gòu)整個(gè)項(xiàng)目,耗時(shí)間;
- 穩(wěn)定性差:一個(gè)微小的問(wèn)題都可能導(dǎo)致整個(gè)應(yīng)用掛掉;
- 擴(kuò)展性不夠:無(wú)法滿足高并發(fā)下的業(yè)務(wù)需求;
3、微服務(wù)架構(gòu):有效的拆分應(yīng)用,將應(yīng)用拆分成多個(gè)微服務(wù),實(shí)現(xiàn)敏捷開(kāi)發(fā)和部署;
微服務(wù)特征:
- 一系列的獨(dú)立的服務(wù)共同組成系統(tǒng);
- 單獨(dú)部署;
- 每個(gè)服務(wù)為獨(dú)立的業(yè)務(wù)開(kāi)發(fā);
- 分布式管理;
- 非常強(qiáng)調(diào)隔離性;
>> 微服務(wù)實(shí)戰(zhàn) - 怎么實(shí)現(xiàn)微服務(wù)
要實(shí)際的應(yīng)用微服務(wù),需要解決一下問(wèn)題:
- 客戶端如何訪問(wèn)這些服務(wù);
- 每個(gè)服務(wù)之間如何通信;
- 如此多的服務(wù),怎么實(shí)現(xiàn);
- 服務(wù)掛了,怎么解決;(備份方案,應(yīng)急處理機(jī)制)
1、客戶端如何訪問(wèn)這些服務(wù)
通過(guò)API網(wǎng)關(guān)的模式來(lái)訪問(wèn)
傳統(tǒng)的單體開(kāi)發(fā),所有的服務(wù)都是在本地的,UI可以直接調(diào)用;現(xiàn)在按照功能拆分成獨(dú)立的服務(wù),每個(gè)服務(wù)都跑在獨(dú)立的虛擬機(jī)上的Java進(jìn)程里;UI要怎么去訪問(wèn)服務(wù)?
一個(gè)服務(wù),一個(gè)應(yīng)用,一個(gè)容器;每個(gè)服務(wù)都是一個(gè)獨(dú)立的計(jì)算機(jī),這就表示每個(gè)計(jì)算機(jī)都有一個(gè)獨(dú)立的IP和端口;
后臺(tái)有N個(gè)服務(wù),前臺(tái)就要去記住管理N個(gè)服務(wù);用戶去訪問(wèn)UI,UI去管理這么多服務(wù),怎么管理是個(gè)問(wèn)題;一個(gè)服務(wù)下線、更新、升級(jí),前臺(tái)就要重新部署;這不符合拆分的理念,特別是前臺(tái)是移動(dòng)應(yīng)用的時(shí)候:PC訪問(wèn)的話,后臺(tái)服務(wù)變了,把JSP頁(yè)面改改,重啟服務(wù),重新部署一下,用戶再次訪問(wèn)PC的時(shí)候,就自動(dòng)變了;移動(dòng)應(yīng)用訪問(wèn)的話,后臺(tái)服務(wù)變了,就得下載新的安裝包,麻煩;
一般微服務(wù)在系統(tǒng)的內(nèi)部,通常是無(wú)狀態(tài)的,也就是說(shuō)各個(gè)微服務(wù)之間的互相調(diào)用是無(wú)狀態(tài)的,不知道是誰(shuí)在調(diào)用;用戶登錄信息和權(quán)限管理最好有一個(gè)統(tǒng)一的地方維護(hù)管理(OAuth),這樣就不用在每個(gè)服務(wù)都登錄一次;當(dāng)用戶去訪問(wèn)UI的時(shí)候,都應(yīng)該去訪問(wèn)OAuth服務(wù)器(授權(quán)服務(wù)器),OAuth再去訪問(wèn)服務(wù);這樣就由OAuth服務(wù)器統(tǒng)一管理后面微服務(wù)的授權(quán)(用戶的登錄狀態(tài));
無(wú)狀態(tài):Http的請(qǐng)求時(shí)無(wú)狀態(tài)的,不會(huì)記錄是誰(shuí)來(lái)請(qǐng)求的;web應(yīng)用為了實(shí)現(xiàn)有狀態(tài)的效果,才有了會(huì)話,用session來(lái)記錄狀態(tài),而http請(qǐng)求本身是無(wú)狀態(tài)的;
一般在后臺(tái)N個(gè)服務(wù)和UI之間會(huì)有一個(gè)API Gateway,由網(wǎng)關(guān)實(shí)現(xiàn)OAuth的功能,它的作用包括:
- 提供統(tǒng)一的服務(wù)入口,讓服務(wù)對(duì)前臺(tái)透明;
- 聚合后臺(tái)的服務(wù),節(jié)省流量,提升性能;
- 提供安全,過(guò)濾,流量控制等API管理功能;
既然微服務(wù)內(nèi)部是無(wú)狀態(tài)的,我們就需要有一個(gè)東西讓它有狀態(tài),這個(gè)東西就是授權(quán)服務(wù)器,這個(gè)東西又稱為SSO(單點(diǎn)登錄);
單點(diǎn)登錄:單點(diǎn)就是一個(gè)點(diǎn)(一個(gè)地方),在一個(gè)地方登錄了,就相當(dāng)于在所有地方登錄了;
用戶訪問(wèn)UI,UI訪問(wèn)API網(wǎng)關(guān),API網(wǎng)關(guān)也是一個(gè)服務(wù),這個(gè)服務(wù)去聚合后面的微服務(wù);API網(wǎng)關(guān)又相當(dāng)于后面服務(wù)的防火墻,因?yàn)锳PI一個(gè)服務(wù),把后面整個(gè)隔離了,所有安全的東西都可以在API網(wǎng)關(guān)這里來(lái)做;
不使用API網(wǎng)關(guān)的時(shí)候,UI的PC端需要記錄所有后臺(tái)服務(wù)的IP地址和端口,移動(dòng)應(yīng)用也需要記錄一份IP地址,這時(shí)候如果后臺(tái)有一個(gè)服務(wù)的IP改了一下,PC端在后臺(tái)改一下代碼配置就可以了,但是移動(dòng)應(yīng)用就需要更新一個(gè)整個(gè)的安裝包,就為了后臺(tái)服務(wù)改了一個(gè)IP,不現(xiàn)實(shí);
有了API網(wǎng)關(guān),解決了這個(gè)問(wèn)題;UI的PC和移動(dòng)應(yīng)用上只需要記錄一個(gè)API網(wǎng)關(guān)的地址,后臺(tái)服務(wù)的IP地址由API網(wǎng)關(guān)來(lái)管理,只要API網(wǎng)關(guān)的地址不變,后臺(tái)服務(wù)的IP隨便怎么改,怎么增加,怎么減少都無(wú)所謂,因?yàn)橹恍枰薷腁PI網(wǎng)關(guān)管理的服務(wù)IP列表即可;這時(shí)候安卓端的每次后臺(tái)修改就要更新整個(gè)安裝包的尷尬問(wèn)題就沒(méi)有了;
用戶訪問(wèn)某個(gè)服務(wù)的時(shí)候,只需要通過(guò)UI去訪問(wèn)API網(wǎng)關(guān),然后由網(wǎng)關(guān)去調(diào)用不同的服務(wù);
API網(wǎng)關(guān)有很多實(shí)現(xiàn)辦法,可以是一個(gè)軟硬一體的盒子,可以是一個(gè)簡(jiǎn)單的MVC框架,可以是一個(gè)Node.js的服務(wù)端;它最重要的作用是為UI提供后臺(tái)服務(wù)的聚合,提供統(tǒng)一的服務(wù)出口,解除它們之間的耦合;但是API網(wǎng)關(guān)可能成為單點(diǎn)故障,或性能的瓶頸;
單點(diǎn)故障:網(wǎng)關(guān)掛掉了,所有后臺(tái)服務(wù)都不能訪問(wèn)了,即使后臺(tái)服務(wù)都能正常運(yùn)行;
性能瓶頸:API網(wǎng)關(guān)只有一個(gè)服務(wù)器,所有流量都要經(jīng)由這個(gè)網(wǎng)關(guān)服務(wù)器,然后由它分發(fā)到后臺(tái)服務(wù)上面去;
2、每個(gè)服務(wù)之間如何通信
所有的微服務(wù)都是獨(dú)立的Java進(jìn)程運(yùn)行在獨(dú)立的虛擬機(jī)/容器上,所以服務(wù)間的通信就是IPC(Inter Process Communication 進(jìn)程間通信);
解決服務(wù)間通信,有兩種方案:
(1)同步調(diào)用:
- REST(Spring Boot、SpringMVC):就是Http通信;
- RPC(Thrift,Dubbo):遠(yuǎn)程過(guò)程調(diào)用;使用的時(shí)候就和調(diào)用本地應(yīng)用一樣;
對(duì)外REST,對(duì)內(nèi)RPC;
對(duì)內(nèi)RPC因?yàn)镽PC在內(nèi)網(wǎng)中調(diào)用的速度非常快;而對(duì)外REST是因?yàn)橛蟹阑饓?#xff0c;防火墻只能接收字符串,REST提供的是json格式數(shù)據(jù),這個(gè)格式是由字符串組成的;網(wǎng)絡(luò)中只有字符串可以穿透防火墻,RPC是遠(yuǎn)程過(guò)程調(diào)用,是穿透不了防火墻的;
同步調(diào)用比較簡(jiǎn)單,一致性強(qiáng),但是容易出現(xiàn)調(diào)用問(wèn)題: 同步調(diào)用會(huì)出現(xiàn)阻塞,出現(xiàn)阻塞就會(huì)出現(xiàn)單點(diǎn)故障; 性能體驗(yàn)也會(huì)差一些,特別是調(diào)用層次多的時(shí)候;
一般REST基于HTTP,更容易實(shí)現(xiàn),服務(wù)端的實(shí)現(xiàn)技術(shù)也更靈活些,各種語(yǔ)言都支持,同時(shí)也能跨客戶端,對(duì)客戶端沒(méi)有特殊的要求,只要支持HTTP請(qǐng)求,就能拿到字符串,拿到字符串就能在自己的程序里想怎么樣就怎么樣;
(2)異步消息調(diào)用:
- kafka
- Notify
- MessageQueue
異步消息的方式在分布式系統(tǒng)中有特別廣泛的應(yīng)用,它既能降低調(diào)用服務(wù)之間的耦合,又能成為調(diào)用之間的緩沖,確保消息積壓不會(huì)沖垮被調(diào)用方,同時(shí)能保證調(diào)用方的服務(wù)體驗(yàn),繼續(xù)干自己該干的活,不至于被后臺(tái)性能拖慢;不過(guò)需要付出的代價(jià)是一致性的減弱,需要接受數(shù)據(jù) 最終一致性;還有就是后臺(tái)服務(wù)一般要實(shí)現(xiàn) 冪等性,因?yàn)橄⑺统鲇谛阅艿目紤]一般會(huì)有重復(fù)(保證消息的被收到且僅收到一次對(duì)性能是很大的考驗(yàn));最后就是必須引入一個(gè)獨(dú)立的 Broker;
-
調(diào)用服務(wù)之間的耦合:用戶服務(wù)與產(chǎn)品服務(wù)之間存在調(diào)用,若RPC的方式,用戶服務(wù)就得依賴產(chǎn)品服務(wù),產(chǎn)品服務(wù)在線,用戶服務(wù)才能上線;產(chǎn)品服務(wù)不在線,用戶服務(wù)無(wú)法啟動(dòng),因?yàn)橛脩舴?wù)無(wú)法遠(yuǎn)程調(diào)用到產(chǎn)品服務(wù),相當(dāng)于沒(méi)有添加需要的依賴;這就形成了耦合度;將RPC換成Broker能降低耦合;
-
Broker是一個(gè)服務(wù)器,它能成為用戶服務(wù)和產(chǎn)品服務(wù)之間的緩沖,用戶服務(wù)調(diào)用產(chǎn)品服務(wù)會(huì)傳遞消息過(guò)來(lái),Broker是一個(gè)服務(wù)器,形成一個(gè)緩沖的效果,這樣就不會(huì)因?yàn)橛脩舴?wù)而導(dǎo)致產(chǎn)品服務(wù)掛掉;
-
用戶服務(wù)調(diào)用產(chǎn)品服務(wù)的時(shí)候,會(huì)有大量的請(qǐng)求過(guò)來(lái),這就已經(jīng)在拖產(chǎn)品服務(wù)的速度、內(nèi)存消耗、CPU等;以此同時(shí)用戶也在通過(guò)UI調(diào)用網(wǎng)關(guān),在單獨(dú)的獨(dú)立的請(qǐng)求產(chǎn)品服務(wù),這就分成了兩個(gè)業(yè)務(wù)線在調(diào)用產(chǎn)品服務(wù):別的用戶在調(diào)用產(chǎn)品服務(wù),用戶服務(wù)在調(diào)用產(chǎn)品服務(wù);這時(shí)有Broker服務(wù)器緩沖一些后臺(tái)服務(wù)的調(diào)用,能降低一些壓力;
-
一致性的減弱:比如用戶通過(guò)UI調(diào)用API網(wǎng)關(guān)下了一個(gè)訂單,這個(gè)時(shí)候是用HTTP請(qǐng)求,是同步的,下完訂單馬上就有反饋;這個(gè)時(shí)候如果是異步,有一個(gè)緩沖,下完訂單,可能不會(huì)立刻處理,這樣也就不會(huì)立刻得到反饋;這就是一致性的減弱;
-
最終一致性:不是實(shí)時(shí)反饋,但是最終的結(jié)果是正確的就可以了;
-
冪等性:無(wú)論多少次請(qǐng)求,返回的結(jié)果都是一樣的;
-
獨(dú)立的Broker:稱之為消息隊(duì)列的中間服務(wù)器;
消息隊(duì)列:就是一個(gè)設(shè)計(jì)模式 - 生產(chǎn)者消費(fèi)者模式:生產(chǎn)者只管生產(chǎn),消費(fèi)者只管消費(fèi);
消息隊(duì)列分兩種:
-
有Broker的:
Broker是對(duì)消息的持久化;
有Broker就說(shuō)明有個(gè)服務(wù)器 ,做兩個(gè)服務(wù)之間的中間緩沖;
有Broker是為了做消息的持久化, -
無(wú)Broker的:
無(wú)Broker的就是兩個(gè)服務(wù)之間直連;
無(wú)Broker就是在對(duì)消息的完整型要求不高的情況下使用,kafka是代表;
kafka:全球最快消息隊(duì)列;一般拿來(lái)做日志;
比如創(chuàng)建一個(gè)訂單,由生產(chǎn)者進(jìn)行生產(chǎn),然后傳遞給消費(fèi)者;生產(chǎn)者這個(gè)服務(wù)只管生產(chǎn),而不管消費(fèi)者服務(wù)怎么處理、什么時(shí)候處理這個(gè)訂單,只是一直生產(chǎn)一直發(fā),這就會(huì)導(dǎo)致消費(fèi)者服務(wù)被拖垮;所以生產(chǎn)者和消費(fèi)者這個(gè)兩個(gè)服務(wù)之間要有一個(gè)稱為Broker的緩沖地帶;
生產(chǎn)者不管消費(fèi)者什么時(shí)候消費(fèi)、怎么消費(fèi),消費(fèi)者可能不能處理那么大的信息,這就會(huì)形成消息積壓;消費(fèi)者發(fā)送的請(qǐng)求都發(fā)送都Broker,Broker先存著,然后由Broker一條一條發(fā)送給消費(fèi)者,消費(fèi)者性能跟不上了,Broker就會(huì)等待,等消費(fèi)者能處理了再發(fā)送請(qǐng)求給消費(fèi)者;
生產(chǎn)者往消費(fèi)者發(fā)消息,若消費(fèi)者掛掉了,而生產(chǎn)者還在一直發(fā),若沒(méi)有緩沖地帶,這些消息就會(huì)消失,影響一致性;中間有一個(gè)Broker,對(duì)消息做了持久化,當(dāng)消費(fèi)者下線以后,再次上線,消息還在Broker中;
若消息很重要,不能丟失,就不可以在兩個(gè)服務(wù)之間直連,必須要有Broker來(lái)做消息的持久化;但有些消息可以丟失,要的是異步、速度,對(duì)數(shù)據(jù)的完整性(一致性)不考慮,比如日志傳輸,日志不需要完整,丟幾條也沒(méi)有問(wèn)題;這時(shí)候就可以使用kafka;
3、如此多的服務(wù),如何實(shí)現(xiàn)
在微服務(wù)架構(gòu)中,一般每個(gè)服務(wù)都有多個(gè)拷貝,來(lái)做負(fù)載均衡;一個(gè)服務(wù)隨時(shí)可能下線,也可能應(yīng)對(duì)臨時(shí)訪問(wèn)壓力增加新的服務(wù)節(jié)點(diǎn);
一個(gè)容器一個(gè)服務(wù),一個(gè)容器是一個(gè)節(jié)點(diǎn);一個(gè)服務(wù)有N個(gè)節(jié)點(diǎn)的時(shí)候,用戶請(qǐng)求的時(shí)候,每個(gè)節(jié)點(diǎn)都有可能去,多個(gè)用戶請(qǐng)求這個(gè)服務(wù),就把請(qǐng)求的壓力分散開(kāi)了,這就叫負(fù)載均衡;一個(gè)服務(wù)下線了,還有其他服務(wù)節(jié)點(diǎn)繼續(xù)提供服務(wù),這個(gè)效果就稱為高可用;
服務(wù)之間如何相互感知?服務(wù)如何管理?這就是服務(wù)發(fā)現(xiàn)的問(wèn)題了;
服務(wù)發(fā)現(xiàn):API網(wǎng)關(guān)怎么知道服務(wù)的IP和端口?這些服務(wù)下線了怎么辦?新增了一個(gè)服務(wù)節(jié)點(diǎn)06,網(wǎng)關(guān)怎么知道06節(jié)點(diǎn)的存在?
服務(wù)發(fā)現(xiàn)一般有2種做法,基本都是通過(guò)Zookeeper等類(lèi)似技術(shù)做服務(wù)注冊(cè)信息的分布式管理;當(dāng)服務(wù)上線時(shí),服務(wù)提供者將自己的服務(wù)信息注冊(cè)到ZK(或類(lèi)似框架),并通過(guò)心跳維持長(zhǎng)鏈接(Tcp長(zhǎng)鏈接),實(shí)時(shí)更新鏈接信息;調(diào)用者通過(guò)ZK尋址,根據(jù)可指定算法,找到一個(gè)服務(wù),還可以將一個(gè)服務(wù)信息緩存在本地以提高性能;當(dāng)服務(wù)下線時(shí),ZK會(huì)通知給服務(wù)客戶端;
Zookeeper是一個(gè)框架,主要用來(lái)做 服務(wù)的注冊(cè)與發(fā)現(xiàn);
(1)基于客戶端的服務(wù)注冊(cè)與發(fā)現(xiàn):
- 優(yōu)點(diǎn)是架構(gòu)簡(jiǎn)單,擴(kuò)展靈活,只對(duì)服務(wù)注冊(cè)器依賴;
- 缺點(diǎn)是客戶端要維護(hù)所有調(diào)用服務(wù)的地址,有技術(shù)難度,一般大公司都有成熟的內(nèi)部框架支持,比如 Dubbo;
Dubbo是RPC遠(yuǎn)程調(diào)用框架,Zookeeper是服務(wù)注冊(cè)與發(fā)現(xiàn)框架,兩者結(jié)合使用完成微服務(wù)的實(shí)現(xiàn);
客戶端服務(wù)自己注冊(cè)到服務(wù)注冊(cè)中心(ZK)去,ZK維護(hù)這個(gè)IP列表,訂單服務(wù)要調(diào)用產(chǎn)品服務(wù),就去注冊(cè)中心查找產(chǎn)品服務(wù)的IP、端口、服務(wù)名稱;
客戶端服務(wù)器啟動(dòng)的時(shí)候,需要把自己的IP、端口、服務(wù)名稱告訴 服務(wù)注冊(cè)與發(fā)現(xiàn) 服務(wù)器,API網(wǎng)關(guān)想要調(diào)用什么服務(wù),就告訴服務(wù)注冊(cè)中心服務(wù)名稱,注冊(cè)中心反饋回一個(gè)對(duì)應(yīng)的服務(wù)的IP與端口,網(wǎng)關(guān)就能直接調(diào)用這個(gè)服務(wù)了;
原來(lái)是由網(wǎng)關(guān)管理后臺(tái)服務(wù)的IP列表,現(xiàn)在由注冊(cè)中心來(lái)管理,服務(wù)器的信息,由服務(wù)自己注冊(cè)到服務(wù)中心;
(2)基于服務(wù)端的服務(wù)注冊(cè)與發(fā)現(xiàn):
優(yōu)點(diǎn)是簡(jiǎn)單,所有服務(wù)對(duì)于前臺(tái)調(diào)用方透明,一般在小公司在云服務(wù)上部署的應(yīng)用采用的比較多;
由服務(wù)調(diào)用者去調(diào)用負(fù)載均衡服務(wù)器,負(fù)載均衡服務(wù)器去調(diào)用注冊(cè)中心,再去調(diào)用對(duì)應(yīng)的服務(wù);比基于客戶端的方式多個(gè)一個(gè)LB服務(wù)器;
UI調(diào)用負(fù)載均衡服務(wù)器,再由LB調(diào)用API網(wǎng)關(guān),因?yàn)榫W(wǎng)關(guān)也需要開(kāi)辟多個(gè)節(jié)點(diǎn),做負(fù)載均衡,以避免單點(diǎn)故障的出現(xiàn),從而實(shí)現(xiàn)高可用;服務(wù)注冊(cè)中心也要做負(fù)載均衡;
所有的服務(wù)都要經(jīng)過(guò)注冊(cè)服務(wù)注冊(cè)中心,有服務(wù)注冊(cè)中心統(tǒng)一管理IP、端口、服務(wù)名稱;
4、服務(wù)掛了怎么辦
分布式最大的特性就是網(wǎng)絡(luò)是不可靠的:ping的時(shí)候偶爾會(huì)有丟包;
解決辦法:
-
重試機(jī)制:一次沒(méi)請(qǐng)求成功,再請(qǐng)求一次; ZK去請(qǐng)求后臺(tái)服務(wù)的時(shí)候,由于網(wǎng)絡(luò)原因,沒(méi)有連接上服務(wù),那就在超時(shí)之后再試一次;
-
限流:同時(shí)有一萬(wàn)個(gè)并發(fā)過(guò)來(lái)請(qǐng)求訪問(wèn)服務(wù)器2,壓力很大,因?yàn)槭峭秸?qǐng)求,就會(huì)阻塞,阻塞就可能掛掉,就會(huì)出現(xiàn)單點(diǎn)故障;這時(shí)候就可以在客戶端調(diào)用ZK那里進(jìn)行限流,讓一部分請(qǐng)求停止在客戶端那里,不會(huì)發(fā)送到后臺(tái)服務(wù)器上;
-
熔斷機(jī)制:客戶端的請(qǐng)求全部通過(guò)ZK發(fā)送到了后臺(tái),流量一上來(lái),就開(kāi)啟熔斷機(jī)制,在真正到達(dá)處理請(qǐng)求的服務(wù)器之前被阻斷,阻止請(qǐng)求發(fā)送到處理服務(wù)器;同時(shí)返回客戶端服務(wù)無(wú)法響應(yīng)的提示;
-
負(fù)載均衡:
-
降級(jí)(本地緩存):把服務(wù)下線,以保障系統(tǒng)最基本的功能能使用,表面看整個(gè)系統(tǒng)依然是高可用的;
當(dāng)大量請(qǐng)求發(fā)送到后臺(tái)的時(shí)候,沒(méi)有限流也沒(méi)有啟動(dòng)熔斷機(jī)制,因?yàn)榇_實(shí)需要提供服務(wù),但是因?yàn)榱髁窟^(guò)大,計(jì)算機(jī)承載不了這些流量以后,就要停止部分服務(wù),以保障數(shù)據(jù)一致性問(wèn)題;比如:訂單服務(wù),訂單服務(wù)后面又要去訪問(wèn)其他服務(wù),這時(shí)如訂單服務(wù)承載不了那么大的壓力了,一旦再往下傳遞請(qǐng)求,就可能出現(xiàn)數(shù)據(jù)不一致了,這時(shí)候若沒(méi)有更好的解決方案,那就停掉訂單服務(wù)器,讓整個(gè)訂單服務(wù)下線,不要再產(chǎn)生新的訂單了;但是網(wǎng)站的其他服務(wù)還可以繼續(xù)使用;
微服務(wù)實(shí)現(xiàn)總結(jié):
單體應(yīng)用拆分成多個(gè)獨(dú)立的服務(wù),每一個(gè)服務(wù)是一個(gè)應(yīng)用程序,使用Docker的容器化部署將所有這些服務(wù)進(jìn)行隔離;
服務(wù)與服務(wù)之間有一個(gè)通信問(wèn)題要解決,有兩種方式:同步請(qǐng)求方式和異步請(qǐng)求方式;同步請(qǐng)求方式有2種方式:REST和RPC方式;異步請(qǐng)求方式只有一種方式:消息隊(duì)列方式;
這個(gè)時(shí)候因?yàn)橛梢粋€(gè)API Gateway來(lái)統(tǒng)一的存儲(chǔ)所有服務(wù)的IP與端口,對(duì)維護(hù)起來(lái)就增加了難度,于是就要使用另一個(gè)機(jī)制:服務(wù)注冊(cè)與發(fā)現(xiàn)機(jī)制;由統(tǒng)一的調(diào)度中心(API網(wǎng)關(guān))去請(qǐng)求服務(wù)注冊(cè)與發(fā)現(xiàn)機(jī)制 ,去獲取所需要的服務(wù)的對(duì)應(yīng)的IP和端口;由服務(wù)注冊(cè)中心來(lái)保障下面服務(wù)的高可用與一致性;
服務(wù)掛了之后可以使用”重試機(jī)制“、”限流“、”熔斷機(jī)制“、”負(fù)載均衡“、”服務(wù)降級(jí)“等方式以保障整個(gè)服務(wù)還處于高可用狀態(tài);
>> 單點(diǎn)故障與分布式鎖
- 單點(diǎn)故障:通俗講就是 由一個(gè)服務(wù)阻塞或掛機(jī)了,導(dǎo)致后面的服務(wù)都不可以使用了,這時(shí)候就稱為單點(diǎn)故障;
解決單點(diǎn)故障:使用分布式鎖;
Zookeeper:是一個(gè)服務(wù)注冊(cè)與發(fā)現(xiàn)的框架,同時(shí)也是一個(gè)分布式協(xié)調(diào)技術(shù); 最厲害的地方是它實(shí)現(xiàn)了分布式鎖的問(wèn)題;
-
分布式鎖:為了防止分布式系統(tǒng)中多個(gè)進(jìn)程之間相互干擾,就需要一種分布式協(xié)調(diào)技術(shù),來(lái)對(duì)這些進(jìn)程進(jìn)行協(xié)調(diào),而分布式協(xié)調(diào)的核心就是來(lái)實(shí)現(xiàn)分布式鎖;ZK就是這樣的一個(gè)實(shí)現(xiàn)了分布式鎖的分布式協(xié)調(diào)技術(shù);
-
分布式系統(tǒng)中的單點(diǎn)故障:
在分布式鎖服務(wù)中,有一種典型的應(yīng)用場(chǎng)景,就是通過(guò)對(duì)集群進(jìn)行master選舉,來(lái)解決分布式系統(tǒng)中的單點(diǎn)故障問(wèn)題;通常分布式系統(tǒng)采用主從模式,就是一個(gè)主機(jī)控制多個(gè)處理節(jié)點(diǎn),主節(jié)點(diǎn)負(fù)責(zé)分發(fā)任務(wù),從節(jié)點(diǎn)負(fù)責(zé)處理任務(wù),當(dāng)主節(jié)點(diǎn)發(fā)生故障時(shí),任務(wù)沒(méi)人分發(fā),那么整個(gè)系統(tǒng)就都掛掉了;這種故障就叫做單點(diǎn)故障;
~ 單點(diǎn)故障傳統(tǒng)解決方案:
采用一個(gè)備用節(jié)點(diǎn),這個(gè)備用節(jié)點(diǎn)定期給主節(jié)點(diǎn)發(fā)送ping包,主節(jié)點(diǎn)收到ping包以后向備用節(jié)點(diǎn)發(fā)送回復(fù)Ack,備用節(jié)點(diǎn)收到回復(fù)的時(shí)候,就會(huì)認(rèn)為當(dāng)前主節(jié)點(diǎn)還活著,讓它繼續(xù)提供服務(wù);
當(dāng)主節(jié)點(diǎn)掛了,這個(gè)時(shí)候備用節(jié)點(diǎn)就收不到回復(fù)了,然后它就認(rèn)為主節(jié)點(diǎn)掛了,就接替它成為主節(jié)點(diǎn);
但是這種方式存在一個(gè)隱患,就是網(wǎng)絡(luò)問(wèn)題;主節(jié)點(diǎn)沒(méi)有掛掉,但是由于網(wǎng)絡(luò)震蕩問(wèn)題,導(dǎo)致備用節(jié)點(diǎn)向主節(jié)點(diǎn)發(fā)送ping包之后,主節(jié)點(diǎn)沒(méi)有收到包,或是收到了,但是在返回Ack字節(jié)碼的時(shí)候,網(wǎng)絡(luò)突然丟了一個(gè)包,將主節(jié)點(diǎn)回應(yīng)給備用節(jié)點(diǎn)的Ack包丟了,這就一下,備用節(jié)點(diǎn)沒(méi)收到回復(fù),就認(rèn)為主節(jié)點(diǎn)掛了,然后備用節(jié)點(diǎn)就將它的Master實(shí)例啟動(dòng)起來(lái),這樣分布式系統(tǒng)中就出現(xiàn)了兩個(gè)主節(jié)點(diǎn) - 雙Master(雙主問(wèn)題);
出現(xiàn)Master以后,從節(jié)點(diǎn)就會(huì)將它所做的事一部分匯報(bào)給了主節(jié)點(diǎn),一部分匯報(bào)給了從節(jié)點(diǎn),這樣服務(wù)就亂套了:當(dāng)發(fā)送插入記錄的請(qǐng)求的時(shí)候,2個(gè)主節(jié)點(diǎn)都會(huì)收到這個(gè)請(qǐng)求,機(jī)會(huì)調(diào)用2此從節(jié)點(diǎn)處理這個(gè)請(qǐng)求,這樣就會(huì)插入兩次數(shù)據(jù);
為了防止雙主問(wèn)題,就要使用ZK加入分布式鎖的概念,鎖住主節(jié)點(diǎn)的資源;
~ Zookeeper 解決方案
(1)Master啟動(dòng):
在引入ZK以后,啟動(dòng)兩個(gè)主節(jié)點(diǎn)A和B,主節(jié)點(diǎn)-A和主節(jié)點(diǎn)-B啟動(dòng)以后,都向ZK去注冊(cè)一個(gè)節(jié)點(diǎn),注冊(cè)后就會(huì)有一個(gè)編號(hào);假設(shè)主節(jié)點(diǎn)-A 鎖注冊(cè)的節(jié)點(diǎn)是master-00001,主節(jié)點(diǎn)-B 鎖注冊(cè)的節(jié)點(diǎn)是master-00002,注冊(cè)以后進(jìn)行選舉,編號(hào)最小的節(jié)點(diǎn)將會(huì)在選舉中獲得鎖稱為主節(jié)點(diǎn),這里主節(jié)點(diǎn)-A獲勝;然后主節(jié)點(diǎn)-B將會(huì)被阻塞成為一個(gè)備用節(jié)點(diǎn);通過(guò)這種方式就完成了對(duì)兩個(gè)Master進(jìn)程的調(diào)度;
在我們通過(guò)UI發(fā)送請(qǐng)求的時(shí)候,回去請(qǐng)求ZK,由ZK去請(qǐng)求需要的主節(jié)點(diǎn)進(jìn)行消息的分發(fā);因?yàn)槭欠植际较到y(tǒng),會(huì)有多個(gè)主節(jié)點(diǎn)的實(shí)例,誰(shuí)來(lái)當(dāng)主節(jié)點(diǎn),由ZK自己來(lái)選舉;
(2)Master故障:
如果”主節(jié)點(diǎn)-A“掛了,這時(shí)候它在ZK中注冊(cè)的節(jié)點(diǎn)就會(huì)自動(dòng)刪除,ZK會(huì)自動(dòng)感知節(jié)點(diǎn)的變化,然后再次發(fā)出選舉,這時(shí)候主節(jié)點(diǎn)-B獲勝,替代A稱為新的主節(jié)點(diǎn);
ZK維護(hù)主節(jié)點(diǎn)們,也會(huì)向主節(jié)點(diǎn)們發(fā)送ping包,當(dāng)ZK向主節(jié)點(diǎn)-A發(fā)送Ping包,沒(méi)有回復(fù)之后,就會(huì)通知主節(jié)點(diǎn)-B重新選舉;如果主節(jié)點(diǎn)-A是因?yàn)榫W(wǎng)絡(luò)震蕩無(wú)法回復(fù)ZK的話,ZK就會(huì)將它從 服務(wù)注冊(cè)與發(fā)現(xiàn) 列表中直接刪除;當(dāng)A重新恢復(fù)上線以后,就會(huì)重新注冊(cè)到ZK中,這時(shí)候就會(huì)變成master-00003,而不是原來(lái)的00001;這時(shí)候ZK會(huì)感知節(jié)點(diǎn)的變化再次發(fā)動(dòng)選舉,這時(shí)候主節(jié)點(diǎn)-B會(huì)再次獲勝繼續(xù)擔(dān)任主節(jié)點(diǎn),節(jié)點(diǎn)A就會(huì)阻塞稱為備用節(jié)點(diǎn),等待下次選舉;這樣就不會(huì)出現(xiàn)之前的雙主e問(wèn)題了;
~ 總結(jié) - 面試:什么是ZK
什么是Zookeeper:服務(wù)注冊(cè)與發(fā)現(xiàn)中心;
ZK解決了什么問(wèn)題:分布式鎖的問(wèn)題;
先解釋單點(diǎn)故障:分布式系統(tǒng)才采用主從模式,就是一個(gè)主服務(wù)器調(diào)用兩個(gè)從服務(wù)器的資源;當(dāng)主服務(wù)器掛掉了,從服務(wù)器還在繼續(xù)提供服務(wù),但是由于主服務(wù)器掛掉了,兩個(gè)從服務(wù)器訪問(wèn)不到了,這就叫做單點(diǎn)故障;
傳統(tǒng)的解決單點(diǎn)故障的方式是有兩個(gè)節(jié)點(diǎn):主節(jié)點(diǎn)和備用節(jié)點(diǎn),備用節(jié)點(diǎn)會(huì)一直ping主節(jié)點(diǎn),若沒(méi)有收到主節(jié)點(diǎn)的回復(fù),就認(rèn)為主節(jié)點(diǎn)掛掉了,備用節(jié)點(diǎn)就上線代替原來(lái)的主節(jié)點(diǎn)稱為新的主節(jié)點(diǎn)提供服務(wù);但是若之前的主節(jié)點(diǎn)沒(méi)有掛掉,而是由于網(wǎng)絡(luò)震蕩問(wèn)題沒(méi)有及時(shí)回復(fù)備用節(jié)點(diǎn),使得備用節(jié)點(diǎn)誤以為主節(jié)點(diǎn)掛掉了,這就出現(xiàn)了雙主問(wèn)題;一旦出現(xiàn)雙主問(wèn)題,所有的請(qǐng)求都會(huì)出現(xiàn)多次、重復(fù),數(shù)據(jù)就會(huì)出現(xiàn)問(wèn)題;
為了解決這個(gè)問(wèn)題,就引入了分布式鎖的問(wèn)題,而ZK這個(gè)框架就是解決分布式鎖的問(wèn)題的;
ZK要求 所有服務(wù)啟動(dòng)的時(shí)候都要想ZK進(jìn)行注冊(cè),這時(shí)候ZK就維護(hù)了一個(gè)節(jié)點(diǎn)列表;ZK會(huì)發(fā)發(fā)動(dòng)選舉,決定誰(shuí)會(huì)成為主節(jié)點(diǎn),選舉出一個(gè)主節(jié)點(diǎn),剩下的節(jié)點(diǎn)就會(huì)阻塞稱為備用節(jié)點(diǎn);ZK會(huì)一直向主節(jié)點(diǎn)發(fā)送ping包,如沒(méi)有收到主節(jié)點(diǎn)的回復(fù),就會(huì)從它維護(hù)的節(jié)點(diǎn)列表中刪掉,而不是停掉,然后通知所有備用節(jié)點(diǎn)進(jìn)行選舉,選出新的主節(jié)點(diǎn)繼續(xù)提供服務(wù);若出現(xiàn)剛才相同的網(wǎng)絡(luò)震蕩的導(dǎo)致主節(jié)點(diǎn)無(wú)法回復(fù)ZK的時(shí)候,主節(jié)點(diǎn)重新上線,就會(huì)重新到ZK去注冊(cè),這個(gè)時(shí)候就會(huì)注冊(cè)成新的節(jié)點(diǎn),變成備用節(jié)點(diǎn),等待下次選舉;
~ 為什么要使用分布式鎖
三個(gè)并發(fā)同時(shí)去訪問(wèn)負(fù)載均衡服務(wù)器,負(fù)載均衡服務(wù)器會(huì)去調(diào)度后臺(tái)服務(wù);后臺(tái)有3個(gè)服務(wù),3個(gè)服務(wù)提供的是3個(gè)相同的應(yīng)用程序;
部署了3套應(yīng)用程序,就變成了有3個(gè)獨(dú)立的JVM進(jìn)程運(yùn)行在3臺(tái)不同的服務(wù)器上;但是這里面我們可能要調(diào)用相同的變量A(因?yàn)橄到y(tǒng)是一樣的,所以變量是一致的);
3個(gè)變量A在3個(gè)JVM內(nèi)存中,變量A同時(shí)都會(huì)在JVM分配內(nèi)存,3個(gè)請(qǐng)求發(fā)送過(guò)來(lái)同時(shí)對(duì)這個(gè)變量進(jìn)行操作,顯然結(jié)果是不對(duì)的;
不是同時(shí)發(fā)送過(guò)來(lái),三個(gè)請(qǐng)求分別操作3個(gè)不同JVM內(nèi)存區(qū)域的數(shù)據(jù),變量A之間不存在共享,也不具可見(jiàn)性,處理的結(jié)果也是不對(duì)的;
這個(gè)變量A主要體現(xiàn)是在一個(gè)類(lèi)中的一個(gè)成員變量,是一個(gè)有狀態(tài)的對(duì)象;
如果業(yè)務(wù)中確實(shí)存在這個(gè)場(chǎng)景,就需要一種方法解決這個(gè)問(wèn)題;
為了保證一個(gè)方法或?qū)傩栽诟卟l(fā)情況下的同一時(shí)間只能被一個(gè)線程執(zhí)行,在單機(jī)環(huán)境中,Java提供了很多并發(fā)處理相關(guān)的API:同步鎖;
由于分布式系統(tǒng)多線程、多進(jìn)程,并且分布在不同機(jī)器上,這使得原單機(jī)部署情況下的并發(fā)控制鎖策略生效;
這就需要一種跨JVM的互斥機(jī)制來(lái)控制共享資源的訪問(wèn);分布式鎖就是解決這個(gè)問(wèn)題的;
Zookeeper就能做到跨進(jìn)程協(xié)作;
分布式鎖應(yīng)該具備的條件:
- 在分布式系統(tǒng)環(huán)境下,一個(gè)方法在同一時(shí)間只能被一個(gè)機(jī)器的一個(gè)線程執(zhí)行;
- 高可用的獲取鎖和釋放鎖:獲取鎖、釋放鎖的服務(wù)器(ZK)本身也得高可用;
- 高性能的獲取鎖和釋放鎖:獲取/釋放鎖的操作要快;
- 具備可重入性:可理解為重新進(jìn)入(重新觸發(fā)這個(gè)事情的時(shí)候),由多于一個(gè)任務(wù)并發(fā)使用,而不必?fù)?dān)心數(shù)據(jù)錯(cuò)誤;
- 具備鎖失效機(jī)制,防止死鎖;
- 具備非阻塞鎖特性,就是沒(méi)有獲取到鎖將直接返回獲取鎖失敗;類(lèi)似熔斷機(jī)制,拿不到鎖直接返回結(jié)果,不能讓程序阻塞在這個(gè)地方;
>> 微服務(wù)架構(gòu)設(shè)計(jì)模式
https://www.funtl.com/zh/micro-service-about/再談微服務(wù)-微服務(wù)架構(gòu)設(shè)計(jì)模式.html#微服務(wù)架構(gòu)需要考慮的問(wèn)題
文章整理自此博客視頻教程
總結(jié)
- 上一篇: 设置linux的自动关机和windows
- 下一篇: Group Normalization(