SpringCloud相關(guān)核心知識點(diǎn)
1 SpringBoot和SpringCloud什么區(qū)別 ?
springboot和springcloud的區(qū)別主要是:
1.作用不同;springboot的作用是為了提供一個(gè)默認(rèn)配置,從而簡化配置過程;springcloud的作用是為了給微服務(wù)提供一個(gè)綜合管理框架
2.使用方式不同;springboot可以單獨(dú)使用;springcloud必須在springboot使用的前提下才能使用。
springboot的設(shè)計(jì)目的是為了在微服務(wù)開發(fā)過程中可以簡化配置文件,提高工作效率,可以認(rèn)為是一個(gè)腳手架工具 , 幫助我們快速的搭建基于spring的項(xiàng)目
SpringCloud就是利用SpringBoot將各種微服務(wù)項(xiàng)目中的解決方案封裝成starter , 提供默認(rèn)配置 , 讓我們在項(xiàng)目開發(fā)過程中能夠方便的使用各種組件
2 你們項(xiàng)目為什么要使用微服務(wù)
傳統(tǒng)的大型單體應(yīng)用程序在部署和運(yùn)行時(shí),需要單臺服務(wù)器具有大量內(nèi)存和其他資源。大型的單體應(yīng)用必須通過在多個(gè)服務(wù)器上復(fù)制整個(gè)應(yīng)用程序來實(shí)現(xiàn)橫向擴(kuò)展,因此其擴(kuò)展能力極差;此外,這些應(yīng)用程序往往更復(fù)雜,各個(gè)功能組件緊耦合,使得維護(hù)和更新非常困難。在這種情況下,想單獨(dú)升級應(yīng)用的一個(gè)功能組件,就會牽一發(fā)而動(dòng)全身 , 某一個(gè)功能升級了可能會導(dǎo)致其他功能又出現(xiàn)故障 , 項(xiàng)目運(yùn)行過程中某一個(gè)地方出現(xiàn)了bug可能會導(dǎo)致整個(gè)應(yīng)用崩潰
在微服務(wù)架構(gòu)中,傳統(tǒng)的大型單體應(yīng)用被拆分為小型模塊化的服務(wù),每項(xiàng)服務(wù)都圍繞特定的業(yè)務(wù)領(lǐng)域構(gòu)建,不同微服務(wù)可以用不同的編程語言編寫,甚至可以使用完全不同的工具進(jìn)行管理和部署 , 與單體應(yīng)用程序相比,微服務(wù)組織更好、更小、更松耦合,并且是獨(dú)立開發(fā)、測試和部署的。由于微服務(wù)可以獨(dú)立發(fā)布,因此修復(fù)錯(cuò)誤或添加新功能所需的時(shí)間要短得多,并且可以更有效地將更改部署到生產(chǎn)中。此外,由于微服務(wù)很小且無狀態(tài),因此更容易擴(kuò)展 !
但是微服務(wù)也有問題 , 微服務(wù)最致命的地方在于成本和管理問題。一個(gè)系統(tǒng)由多個(gè)微服務(wù)組成,多個(gè)微服務(wù)之間的系統(tǒng)整合,團(tuán)隊(duì)間合作和溝通難度,是呈指數(shù)級增長的。項(xiàng)目管理和部署的難度也非常高 , 需要考慮到很多東西 , 而且因?yàn)榉?wù)比較多 , 需要的服務(wù)器成本也比較高
所以具體要不要搞微服務(wù), 還是得仔細(xì)的分析和思考 , 權(quán)衡之后再決定 , 我們的項(xiàng)目中因?yàn)槊嫦虻氖钦麄€(gè)互聯(lián)網(wǎng)用戶 , 考慮到后期運(yùn)營比較好的情況下可能會出現(xiàn)的用戶增長 , 流量增長 , 以及不斷的版本迭代 , 方便后期擴(kuò)展和功能迭代所以選擇了微服務(wù)架構(gòu)
3 Spring Cloud 5大組件有哪些?
Spring Cloud五大組件主要是
1.注冊中心組件 , 例如 : Eureka 和 Nacos
2.負(fù)載均衡組件 , 例如 : Ribbon 和 Spring Cloud LoadBalancer
3.遠(yuǎn)程調(diào)用組件 , 例如 : Feign 和 Dubbo
4.服務(wù)熔斷組件 , 例如 : Hystrix 和 Sentinel
5.服務(wù)網(wǎng)關(guān)組件 , 例如 : Zuul 和 Spring Cloud Gateway
4 什么是微服務(wù)?微服務(wù)的優(yōu)缺點(diǎn)是什么?
微服務(wù)就是一個(gè)獨(dú)立的 , 職責(zé)單一的服務(wù)應(yīng)用程序,一般在項(xiàng)目開發(fā)過程中會按照業(yè)務(wù)和需求將項(xiàng)目拆分成N個(gè)微服務(wù)
1.優(yōu)點(diǎn):松耦合,聚焦單一業(yè)務(wù)功能,無關(guān)開發(fā)語言,團(tuán)隊(duì)規(guī)模降低 , 擴(kuò)展性好, 天然支持分庫
2.缺點(diǎn):隨著服務(wù)數(shù)量增加,管理復(fù)雜,部署復(fù)雜,服務(wù)器需要增多,服務(wù)通信和調(diào)用壓力增大
5 你們項(xiàng)目中微服務(wù)之間是如何通訊的?
服務(wù)的通訊方式主要有二種 :
1.同步通信:通過Feign發(fā)送http請求調(diào)用 或者 通過Dubbo發(fā)送RPC請求調(diào)用
2.異步通信:使用消息隊(duì)列進(jìn)行服務(wù)調(diào)用,如RabbitMQ、KafKa等
6 服務(wù)注冊和發(fā)現(xiàn)是什么意思?Spring Cloud 如何實(shí)現(xiàn)服務(wù)注冊發(fā)現(xiàn)?
各種注冊中心組件的原理和流程其實(shí)大體上類似 , 核心的功能就一下幾個(gè) :
1.服務(wù)注冊 : 服務(wù)啟動(dòng)的時(shí)候會將服務(wù)的信息注冊到注冊中心, 比如: 服務(wù)名稱 , 服務(wù)的IP , 端口號等
2.服務(wù)發(fā)現(xiàn) : 服務(wù)調(diào)用方調(diào)用服務(wù)的時(shí)候, 根據(jù)服務(wù)名稱從注冊中心拉取服務(wù)列表 , 然后根據(jù)負(fù)載均衡策略 , 選擇一個(gè)服務(wù), 獲取服務(wù)的IP和端口號, 發(fā)起遠(yuǎn)程調(diào)用
3.服務(wù)狀態(tài)監(jiān)控 : 服務(wù)提供者會定時(shí)向注冊中心發(fā)送心跳 , 注冊中心也會主動(dòng)向服務(wù)提供者發(fā)送心跳探測, 如果長時(shí)間沒有接收到心跳, 就將服務(wù)實(shí)例從注冊中心下線或者移除

我們項(xiàng)目中注冊中心用的是Nacos , 基本上所有的注冊中心的核心功能都包括服務(wù)注冊 , 服務(wù)發(fā)現(xiàn), 服務(wù)狀態(tài)監(jiān)控 , 他的核心原理如下 :
1.客戶端啟動(dòng)時(shí)會將當(dāng)前服務(wù)的信息包含ip、端口號、服務(wù)名、分組名、集群名等信息封裝為一個(gè)Instance對象,準(zhǔn)備向Nacos服務(wù)器注冊服務(wù),在注冊服務(wù)之前,會根據(jù)Instance中的信息創(chuàng)建一個(gè)BeatInfo對象,然后創(chuàng)建一個(gè)定時(shí)任務(wù),每隔一段時(shí)間向Nacos服務(wù)器發(fā)送PUT請求并攜帶相關(guān)信息,作為定時(shí)心跳連接,服務(wù)器端在接收到心跳請求后,會去檢查當(dāng)前服務(wù)列表中有沒有該實(shí)例,如果沒有的話將當(dāng)前服務(wù)實(shí)例重新注冊,注冊完成后立即開啟一個(gè)異步任務(wù),更新客戶端實(shí)例的最后心跳時(shí)間,如果當(dāng)前實(shí)例是非健康狀態(tài)則將其改為健康狀態(tài)
2.心跳定時(shí)任務(wù)創(chuàng)建完成后,通過POST請求將當(dāng)前服務(wù)實(shí)例信息注冊進(jìn)Nacos服務(wù)器,服務(wù)器端在接收到注冊實(shí)例請求后,會將請求攜帶的數(shù)據(jù)封裝為一個(gè)Instance對象,然后為這個(gè)服務(wù)實(shí)例創(chuàng)建一個(gè)服務(wù)Service,一個(gè)Service下可能有多個(gè)服務(wù)實(shí)例,服務(wù)在Nacos保存到一個(gè)ConcurrentHashMap中,格式為命名空間為key,value為map,分組名和服務(wù)名為內(nèi)層map的key,value為服務(wù)數(shù)據(jù)
3.服務(wù)創(chuàng)建完成之后,開啟一個(gè)定時(shí)任務(wù)(5s執(zhí)行一次),檢查當(dāng)前服務(wù)中的各個(gè)實(shí)例是否在線,如果實(shí)例上次心跳時(shí)間大于15s就將其狀態(tài)設(shè)置為不健康,如果超出30s,則直接將該實(shí)例刪除;
4.然后將當(dāng)前實(shí)例添加到對應(yīng)服務(wù)列表中,這里會通過synchronized鎖住當(dāng)前服務(wù),然后分兩種情況向集群中添加實(shí)例,如果是持久化數(shù)據(jù),則使用CP模型,通過leader節(jié)點(diǎn)將實(shí)例數(shù)據(jù)更新到內(nèi)存和磁盤文件中,然后同步寫入到其他節(jié)點(diǎn) , 必須集群半數(shù)以上節(jié)點(diǎn)寫入成功才會給客戶端返回成功;
5.如果是非持久話實(shí)例數(shù)據(jù),使用的是AP模型,首先向任務(wù)阻塞隊(duì)列添加一個(gè)本地服務(wù)實(shí)例改變?nèi)蝿?wù),去更新本地服務(wù)列表,然后在遍歷集群中所有節(jié)點(diǎn),分別創(chuàng)建數(shù)據(jù)同步任務(wù)放進(jìn)阻塞隊(duì)列異步進(jìn)行集群數(shù)據(jù)同步,不保證集群節(jié)點(diǎn)數(shù)據(jù)同步完成即可返回;
6.在將服務(wù)實(shí)例更新到服務(wù)注冊表中時(shí),為了防止并發(fā)讀寫沖突,采用的是CopyOnWrite的思想,將原注冊表數(shù)據(jù)拷貝一份,添加完成之后再替換回真正的注冊表,更新完成之后,通過發(fā)布服務(wù)變化事件,將服務(wù)變動(dòng)通知給客戶端,采用的是UDP通信,客戶端接收到UDP消息后會返回一個(gè)ACK信號,如果一定時(shí)間內(nèi)服務(wù)端沒有收到ACK信號,還會嘗試重發(fā),當(dāng)超出重發(fā)時(shí)間后就不在重發(fā),雖然通過UDP通信不能保證消息的可靠抵達(dá),但是由于Nacos客戶端會開啟定時(shí)任務(wù),每隔一段時(shí)間更新客戶端緩存的服務(wù)列表,通過定時(shí)輪詢更新服務(wù)列表做兜底,所以不用擔(dān)心數(shù)據(jù)不會更新的情況,這樣既保證了實(shí)時(shí)性,又保證了數(shù)據(jù)更新的可靠性;
7.服務(wù)發(fā)現(xiàn):客戶端通過定時(shí)任務(wù)定時(shí)從服務(wù)端拉取服務(wù)數(shù)據(jù)保存在本地緩存,服務(wù)端在發(fā)生心跳檢測、服務(wù)列表變更或者健康狀態(tài)改變時(shí)會觸發(fā)推送事件,在推送事件中會基于UDP通信將服務(wù)列表推送到客戶端,同時(shí)開啟定時(shí)任務(wù),每隔10s定時(shí)推送數(shù)據(jù)到客戶端
8 你們項(xiàng)目負(fù)載均衡如何實(shí)現(xiàn)的 ?
服務(wù)調(diào)用過程中的負(fù)載均衡一般使用SpringCloud的Ribbon 組件實(shí)現(xiàn) , Feign的底層已經(jīng)自動(dòng)集成了Ribbon , 使用起來非常簡單 , 客戶端調(diào)用的話一般會通過網(wǎng)關(guān), 通過網(wǎng)關(guān)實(shí)現(xiàn)請求的路由和負(fù)載均衡
RIbbon負(fù)載均衡原理 :
SpringCloudRibbon的底層采用了一個(gè)攔截器,攔截了RestTemplate發(fā)出的請求,對地址做了修改。

基本流程如下:
1.LoadBalancerInterceptor
攔截RestTemplate請求
2.調(diào)用RibbonLoadBalancerClient
從請求url中獲取服務(wù)名稱
3.調(diào)用DynamicServerListLoadBalancer
根據(jù)服務(wù)名稱到注冊中心拉取服務(wù)列表 , 注冊中心返回列表
4.DynamicServerListLoadBalancer
調(diào)用IRule使用配置的負(fù)載均衡策略負(fù)載均衡規(guī)則,從服務(wù)列表中選擇一個(gè)服務(wù)實(shí)例
5.RibbonLoadBalancerClient
用服務(wù)實(shí)例的IP和端口替換請求路徑中的服務(wù)名稱
6.向服務(wù)實(shí)例發(fā)起http請求
9 Ribbon負(fù)載均衡策略有哪些
Ribbon默認(rèn)的負(fù)載均衡策略有七種 :

通過定義IRule實(shí)現(xiàn)可以修改負(fù)載均衡規(guī)則,有兩種方式:
代碼方式:通過配置類, 配置一個(gè)IRule
接口的實(shí)現(xiàn)類 , 這是一種通用配置 , 使用于所有的服務(wù)調(diào)用
@Bean
public IRule randomRule(){?
? ?return new RandomRule();
}
配置文件方式:在配置文件中配置負(fù)載均衡規(guī)則
userservice: # 給某個(gè)微服務(wù)配置負(fù)載均衡規(guī)則,這里是userservice服務(wù)?
?ribbon: ??
?NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule # 負(fù)載均衡規(guī)則
10 你們項(xiàng)目的配置文件是怎么管理的 ?
大部分的固定的配置文件都放在服務(wù)本地 , 一些根據(jù)環(huán)境不同可能會變化的部分, 放到配置中心中管理 , 我們項(xiàng)目使用Nacos配置中心進(jìn)行配置的統(tǒng)一管理 , 包括 : 開發(fā)環(huán)境配置 , 測試環(huán)境配置 和 生產(chǎn)環(huán)境配置
11 你們項(xiàng)目中有沒有做過限流 ? 怎么做的 ?
限流其實(shí)在整個(gè)請求的處理流程中都需要做
1.客戶端發(fā)送請求到Nginx需要進(jìn)行限流
2.通過Nginx負(fù)載均衡請求到網(wǎng)關(guān) , 網(wǎng)關(guān)也需要限流
3.網(wǎng)關(guān)路由請求到微服務(wù) , 微服務(wù)也需要限流

每一層所使用的限流方案也不一樣 :
1.nginx層主要是對請求的IP進(jìn)行限流 , 使用的是limit_req_zone
和limit_req
配置 , 底層使用的是漏桶算法實(shí)現(xiàn)的 , nginx層限流主要是對下游的網(wǎng)關(guān)起到保護(hù)作用

2.網(wǎng)關(guān)層限流主要使用的是Spring Cloud Gateway提供Request Rate Limiting
過濾器實(shí)現(xiàn)的 , 底層使用Redis基于令牌桶算法實(shí)現(xiàn)限流 , 網(wǎng)關(guān)限流主要是對下游的微服務(wù)系統(tǒng)起到保護(hù)作用


3.微服務(wù)限流的目的主要是為了保護(hù)微服務(wù)本身不被大流量沖垮 , 可以使用Hystrix和Sentinel進(jìn)行限流 , 底層使用的是信號量和線程隔離實(shí)現(xiàn)的 , 當(dāng)請求達(dá)到限制或者失敗頻率較高會自動(dòng)熔斷 , 執(zhí)行降級邏輯
12 斷路器/熔斷器用過嘛 ? 斷路器的狀態(tài)有哪些
我們項(xiàng)目中使用Hystrix/Sentinel實(shí)現(xiàn)的斷路器 , 斷路器狀態(tài)機(jī)包括三個(gè)狀態(tài):

1.closed:關(guān)閉狀態(tài),斷路器放行所有請求,并開始統(tǒng)計(jì)異常比例、慢請求比例。超過閾值則切換到open狀態(tài)
2.open:打開狀態(tài),服務(wù)調(diào)用被熔斷,訪問被熔斷服務(wù)的請求會被拒絕,快速失敗,直接走降級邏輯。Open狀態(tài)5秒后會進(jìn)入half-open狀態(tài)
3.half-open:半開狀態(tài),放行一次請求,根據(jù)執(zhí)行結(jié)果來判斷接下來的操作
請求成功:則切換到closed狀態(tài)
請求失敗:則切換到open狀態(tài)
13 你們項(xiàng)目中有做過服務(wù)降級嘛 ?

引用FallbackFactory
@FeignClient(value = "task-service",fallbackFactory = TaskServiceFallbackFactory.class)
public interface TaskService {? ?}