????歡迎來到我的CSDN主頁!????
??我是Java方文山,一個(gè)在CSDN分享筆記的博主。????
??推薦給大家我的專欄《Spring Cloud》。????
??點(diǎn)擊這里,就可以查看我的主頁啦!????
Java方文山的個(gè)人主頁
??如果感覺還不錯(cuò)的話請給我點(diǎn)贊吧!????
??期待你的加入,一起學(xué)習(xí),一起進(jìn)步!????
目錄
前言
服務(wù)雪崩效應(yīng)
一、常見的容錯(cuò)方案
二、Sentinel入門
1.什么是Sentinel
2.Sentinel 分為兩個(gè)部分
3.微服務(wù)集成Sentinel
三、安裝Sentinel控制臺(tái)
實(shí)現(xiàn)一個(gè)接口的限流
四、Sentinel規(guī)則
流控規(guī)則
①簡單配置
②配置流控模式
③鏈路流控模式
配置流控效果
五、Feign整合Sentinel
前言
在微服務(wù)架構(gòu)中,我們將業(yè)務(wù)拆分成一個(gè)個(gè)的服務(wù),服務(wù)與服務(wù)之間可以相互調(diào)用,但是由于網(wǎng)絡(luò)原因或者自身的原因,服務(wù)并不能保證服務(wù)的100%可用,如果單個(gè)服務(wù)出現(xiàn)問題,調(diào)用這個(gè)服務(wù)就會(huì)出現(xiàn)網(wǎng)絡(luò)延遲,此時(shí)若有大量的網(wǎng)絡(luò)涌入,會(huì)形成任務(wù)堆積,最終導(dǎo)致服務(wù)癱瘓(雪崩)。
接下來,我們來模擬一個(gè)高并發(fā)的場景
①編寫java代碼
@Slf4j
@RestController
@RequestMapping("/order")
public class OrderController {
@Autowired
private IFeignProductService feignProductService;
@RequestMapping("/findByParameter")
public String findByParameter(String name,Double price){
log.info("服務(wù)消費(fèi)者日志:name={},price={}",name,price);
return feignProductService.findByParameter(name,price);
}
}
②修改配置文件中tomcat的并發(fā)數(shù)
1秒鐘20個(gè)請求,最大連接數(shù)10,最大等待數(shù)10,最大線程數(shù)2,相當(dāng)于一個(gè)線程1s能處理5個(gè)請求(2個(gè)處理10個(gè)請求)
server:
port: 8091
tomcat:
max-threads: 2 #最大線程數(shù)
max-connections: 10 #最大連接數(shù)
accept-count: 10 #最大線程等待數(shù)
如果我1s發(fā)送5個(gè)以上的請求,此時(shí)會(huì)發(fā)現(xiàn), 由于order方法囤積了大量請求, 導(dǎo)致message方法的訪問出現(xiàn)了問題,這就是服務(wù)雪崩的雛形。
服務(wù)雪崩效應(yīng)
在分布式系統(tǒng)中,由于網(wǎng)絡(luò)原因或自身的原因,服務(wù)一般無法保證 100% 可用。如果一個(gè)服務(wù)出現(xiàn)了 問題,調(diào)用這個(gè)服務(wù)就會(huì)出現(xiàn)線程阻塞的情況,此時(shí)若有大量的請求涌入,就會(huì)出現(xiàn)多條線程阻塞等 待,進(jìn)而導(dǎo)致服務(wù)癱瘓。 由于服務(wù)與服務(wù)之間的依賴性,故障會(huì)傳播,會(huì)對(duì)整個(gè)微服務(wù)系統(tǒng)造成災(zāi)難性的嚴(yán)重后果,這就是 服務(wù)故障的 “雪崩效應(yīng)” 。
雪崩發(fā)生的原因多種多樣,有不合理的容量設(shè)計(jì),或者是高并發(fā)下某一個(gè)方法響應(yīng)變慢,亦或是某 臺(tái)機(jī)器的資源耗盡。我們無法完全杜絕雪崩源頭的發(fā)生,只有做好足夠的容錯(cuò),保證在一個(gè)服務(wù)發(fā)生問 題,不會(huì)影響到其它服務(wù)的正常運(yùn)行。也就是"雪落而不雪崩"。 ?
一、常見的容錯(cuò)方案
要防止雪崩的擴(kuò)散,我們就要做好服務(wù)的容錯(cuò),容錯(cuò)說白了就是保護(hù)自己不被豬隊(duì)友拖垮的一些措 施, 下面介紹常見的服務(wù)容錯(cuò)思路和組件。 常見的容錯(cuò)思路 常見的容錯(cuò)思路有隔離、超時(shí)、限流、熔斷、降級(jí)這幾種,下面分別介紹一下。
-
隔離 它是指將系統(tǒng)按照一定的原則劃分為若干個(gè)服務(wù)模塊,各個(gè)模塊之間相對(duì)獨(dú)立,無強(qiáng)依賴。當(dāng)有故障發(fā)生時(shí),能將問題和影響隔離在某個(gè)模塊內(nèi)部,而不擴(kuò)散風(fēng)險(xiǎn),不波及其它模塊,不影響整體的系統(tǒng)服務(wù)。常見的隔離方式有:線程池隔離和信號(hào)量隔離。
-
超時(shí) 在上游服務(wù)調(diào)用下游服務(wù)的時(shí)候,設(shè)置一個(gè)最大響應(yīng)時(shí)間,如果超過這個(gè)時(shí)間,下游未作出反應(yīng),就斷開請求,釋放掉線程。
-
限流 限流就是限制系統(tǒng)的輸入和輸出流量已達(dá)到保護(hù)系統(tǒng)的目的。為了保證系統(tǒng)的穩(wěn)固運(yùn)行,一旦達(dá)到 的需要限制的閾值,就需要限制流量并采取少量措施以完成限制流量的目的。
-
熔斷 在互聯(lián)網(wǎng)系統(tǒng)中,當(dāng)下游服務(wù)因訪問壓力過大而響應(yīng)變慢或失敗,上游服務(wù)為了保護(hù)系統(tǒng)整 體的可用性,可以暫時(shí)切斷對(duì)下游服務(wù)的調(diào)用。這種犧牲局部,保全整體的措施就叫做熔斷。
服務(wù)熔斷一般有三種狀態(tài):
- 熔斷關(guān)閉狀態(tài)(Closed) 服務(wù)沒有故障時(shí),熔斷器所處的狀態(tài),對(duì)調(diào)用方的調(diào)用不做任何限制
- 熔斷開啟狀態(tài)(Open) 后續(xù)對(duì)該服務(wù)接口的調(diào)用不再經(jīng)過網(wǎng)絡(luò),直接執(zhí)行本地的fallback方法
- 半熔斷狀態(tài)(Half-Open) 嘗試恢復(fù)服務(wù)調(diào)用,允許有限的流量調(diào)用該服務(wù),并監(jiān)控調(diào)用成功率。如果成功率達(dá)到預(yù)期,則說明服務(wù)已恢復(fù),進(jìn)入熔斷關(guān)閉狀態(tài);如果成功率仍舊很低,則重新進(jìn)入熔斷啟動(dòng)狀態(tài)。
-
降級(jí) 降級(jí)其實(shí)就是為服務(wù)提供一個(gè)托底方案,一旦服務(wù)無法正常調(diào)用,就使用托底方案。
常見的容錯(cuò)組件
-
Hystrix Hystrix是由Netflix開源的一個(gè)延遲和容錯(cuò)庫,用于隔離訪問遠(yuǎn)程系統(tǒng)、服務(wù)或者第三方庫,防止 級(jí)聯(lián)失敗,從而提升系統(tǒng)的可用性與容錯(cuò)性。
-
Resilience4J Resilicence4J一款非常輕量、簡單,并且文檔非常清晰、豐富的熔斷工具,這也是Hystrix官方推 薦的替代產(chǎn)品。不僅如此,Resilicence4j還原生支持Spring Boot 1.x/2.x,而且監(jiān)控也支持和 prometheus等多款主流產(chǎn)品進(jìn)行整合。
-
Sentinel Sentinel 是阿里巴巴開源的一款斷路器實(shí)現(xiàn),本身在阿里內(nèi)部已經(jīng)被大規(guī)模采用,非常穩(wěn)定。
下面是三個(gè)組件在各方面的對(duì)比:
Sentinel | Hystrix | |
---|---|---|
隔離策略 | 信號(hào)量隔離 | 線程池隔離/信號(hào)量隔離 |
熔斷降級(jí)策略 | 基于響應(yīng)時(shí)間或失敗比率 | 基于失敗比率 |
實(shí)時(shí)指標(biāo)實(shí)現(xiàn) | 滑動(dòng)窗口 | 滑動(dòng)窗口(基于 RxJava) |
規(guī)則配置 | 支持多種數(shù)據(jù)源 | 支持多種數(shù)據(jù)源 |
擴(kuò)展性 | 多個(gè)擴(kuò)展點(diǎn) | 插件的形式 |
基于注解的支持 | 即將支持 | 支持 |
限流 | 基于 QPS,支持基于調(diào)用關(guān)系的限流 | 不支持 |
流量整形 | 支持慢啟動(dòng)、勻速器模式 | 不支持 |
系統(tǒng)負(fù)載保護(hù) | 支持 | 不支持 |
控制臺(tái) | 開箱即用,可配置規(guī)則、查看秒級(jí)監(jiān)控、機(jī)器發(fā)現(xiàn)等 | 不完善 |
常見框架的適配 | Servlet、Spring Cloud、Dubbo、gRPC 等 | Servlet、Spring Cloud Netflix |
二、Sentinel入門
1.什么是Sentinel
Sentinel (分布式系統(tǒng)的流量防衛(wèi)兵) 是阿里開源的一套用于服務(wù)容錯(cuò)的綜合性解決方案。它以流量 為切入點(diǎn), 從流量控制、熔斷降級(jí)、系統(tǒng)負(fù)載保護(hù)等多個(gè)維度來保護(hù)服務(wù)的穩(wěn)定性。 Sentinel 具有以下特征:
-
豐富的應(yīng)用場景:Sentinel 承接了阿里巴巴近 10 年的雙十一大促流量的核心場景, 例如秒殺(即 突發(fā)流量控制在系統(tǒng)容量可以承受的范圍)、消息削峰填谷、集群流量控制、實(shí)時(shí)熔斷下游不可用應(yīng)用等。
-
完備的實(shí)時(shí)監(jiān)控:Sentinel 提供了實(shí)時(shí)的監(jiān)控功能。通過控制臺(tái)可以看到接入應(yīng)用的單臺(tái)機(jī)器秒 級(jí)數(shù)據(jù), 甚至 500 臺(tái)以下規(guī)模的集群的匯總運(yùn)行情況。
-
廣泛的開源生態(tài):Sentinel 提供開箱即用的與其它開源框架/庫的整合模塊, 例如與 Spring Cloud、Dubbo、gRPC 的整合。只需要引入相應(yīng)的依賴并進(jìn)行簡單的配置即可快速地接入 Sentinel。
-
完善的 SPI 擴(kuò)展點(diǎn):Sentinel 提供簡單易用、完善的 SPI 擴(kuò)展接口。您可以通過實(shí)現(xiàn)擴(kuò)展接口來快速地定制邏輯。例如定制規(guī)則管理、適配動(dòng)態(tài)數(shù)據(jù)源等。
2.Sentinel 分為兩個(gè)部分
-
核心庫(Java 客戶端)不依賴任何框架/庫,能夠運(yùn)行于所有 Java 運(yùn)行時(shí)環(huán)境,同時(shí)對(duì) Dubbo / Spring Cloud 等框架也有較好的支持。
-
控制臺(tái)(Dashboard)基于 Spring Boot 開發(fā),打包后可以直接運(yùn)行,不需要額外的 Tomcat 等 應(yīng)用容器。
3.微服務(wù)集成Sentinel
為微服務(wù)集成Sentinel非常簡單, 只需要加入Sentinel的依賴即可,在需要的模塊pom.xml中加入下面依賴
<!--sentinel-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
網(wǎng)關(guān)gateway集成sentinel,需還另添加以下依賴
<dependency>
? <groupId>com.alibaba.cloud</groupId>
? <artifactId>spring-cloud-alibaba-sentinel-gateway</artifactId>
</dependency>
另外編寫一個(gè)Controller測試使用
(我這里就直接用我之前講解組件所寫的生產(chǎn)服務(wù)和消費(fèi)服務(wù)做模擬,以下是我生產(chǎn)服務(wù)的代碼)
@RestController
public class ProduceController {
@RequestMapping("/run")
public String run() {
return "??";
}
}
三、安裝Sentinel控制臺(tái)
Sentinel 提供一個(gè)輕量級(jí)的控制臺(tái), 它提供機(jī)器發(fā)現(xiàn)、單機(jī)資源實(shí)時(shí)監(jiān)控以及規(guī)則管理等功能。
①下載jar包,解壓到文件夾 Releases · alibaba/Sentinel · GitHub
②啟動(dòng)控制臺(tái)
# 直接使用jar命令啟動(dòng)項(xiàng)目(控制臺(tái)本身是一個(gè)SpringBoot項(xiàng)目)
java -Dserver.port=9999 -Dcsp.sentinel.dashboard.server=localhost:9999 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard-1.7.0.jar
#參考1
java -jar sentinel-dashboard-1.8.1.jar --server.port=8080
#參考2
java -Dserver.port=8080 -Dcsp.sentinel.dashboard.server=localhost:8080 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard-1.8.1.jar
③修改shop-order ,在里面加入有關(guān)控制臺(tái)的配置
? sentinel:
? ? transport:
? ? ? port: 8719
? ? ? dashboard: localhost:9999
? ? eager: true
? ? web-context-unify: false
④通過瀏覽器訪問localhost:9999進(jìn)入控制臺(tái) ( 默認(rèn)用戶名密碼是 sentinel/sentinel )
?補(bǔ)充:
了解控制臺(tái)的使用原理 Sentinel的控制臺(tái)其實(shí)就是一個(gè)SpringBoot編寫的程序。我們需要將我們的微服務(wù)程序注冊到控制臺(tái)上,即在微服務(wù)中指定控制臺(tái)的地址, 并且還要開啟一個(gè)跟控制臺(tái)傳遞數(shù)據(jù)的端口, 控制臺(tái)也可以通過此端口調(diào)用微服務(wù)中的監(jiān)控程序獲取微服務(wù)的各種信息。
實(shí)現(xiàn)一個(gè)接口的限流
1 通過控制臺(tái)為message1添加一個(gè)流控規(guī)則
2 通過控制臺(tái)快速頻繁訪問, 觀察效果
四、Sentinel規(guī)則
流控規(guī)則
流量控制,其原理是監(jiān)控應(yīng)用流量的QPS(每秒查詢率) 或并發(fā)線程數(shù)等指標(biāo),當(dāng)達(dá)到指定的閾值時(shí) 對(duì)流量進(jìn)行控制,以避免被瞬時(shí)的流量高峰沖垮,從而保障應(yīng)用的高可用性。 第1步: 點(diǎn)擊簇點(diǎn)鏈路,我們就可以看到訪問過的接口地址,然后點(diǎn)擊對(duì)應(yīng)的流控按鈕,進(jìn)入流控規(guī)則配置頁面。新增流控規(guī)則界面如下:
資源名:唯一名稱,默認(rèn)是請求路徑,可自定義 針對(duì)來源:指定對(duì)哪個(gè)微服務(wù)進(jìn)行限流,默認(rèn)指default,意思是不區(qū)分來源,全部限制 閾值類型/單機(jī)閾值:
-
QPS(每秒請求數(shù)量): 當(dāng)調(diào)用該接口的QPS達(dá)到閾值的時(shí)候,進(jìn)行限流
-
線程數(shù):當(dāng)調(diào)用該接口的線程數(shù)達(dá)到閾值的時(shí)候,進(jìn)行限流
是否集群:暫不需要集群 接下來我們以QPS為例來研究限流規(guī)則的配置。
①簡單配置
我們先做一個(gè)簡單配置,設(shè)置閾值類型為QPS,單機(jī)閾值為3。即每秒請求量大于3的時(shí)候開始限流。 接下來,在流控規(guī)則頁面就可以看到這個(gè)配置。
然后快速訪問/order/message1 接口,觀察效果。此時(shí)發(fā)現(xiàn),當(dāng)QPS > 3的時(shí)候,服務(wù)就不能正常響應(yīng),而是返回Blocked by Sentinel (flow limiting)結(jié)果。
②配置流控模式
點(diǎn)擊上面設(shè)置流控規(guī)則的編輯按鈕,然后在編輯頁面點(diǎn)擊高級(jí)選項(xiàng),會(huì)看到有流控模式一欄。
sentinel共有三種流控模式,分別是:
直接(默認(rèn)):接口達(dá)到限流條件時(shí),開啟限流
關(guān)聯(lián):當(dāng)關(guān)聯(lián)的資源達(dá)到限流條件時(shí),開啟限流 [適合做應(yīng)用讓步]
鏈路:當(dāng)從某個(gè)接口過來的資源達(dá)到限流條件時(shí),開啟限流
?下面呢分別演示三種模式:
直接流控模式 直接流控模式是最簡單的模式,當(dāng)指定的接口達(dá)到限流條件時(shí)開啟限流。上面案例使用的就是直接流控模式。
關(guān)聯(lián)流控模式 關(guān)聯(lián)流控模式指的是,當(dāng)指定接口關(guān)聯(lián)的接口達(dá)到限流條件時(shí),開啟對(duì)指定接口開啟限流。
第1步:配置限流規(guī)則, 將流控模式設(shè)置為關(guān)聯(lián),關(guān)聯(lián)資源設(shè)置為的 /run2。
第3步:通過produce軟件向/run2連續(xù)發(fā)送請求,注意QPS一定要大于3
第4步:訪問/run2,會(huì)發(fā)現(xiàn)已經(jīng)被限流
③鏈路流控模式
鏈路模式是Sentinel流量控制框架中的一種模式,用于對(duì)特定的請求鏈路進(jìn)行限流。在一個(gè)復(fù)雜的系統(tǒng)中,請求可能會(huì)經(jīng)過多個(gè)服務(wù)或接口的調(diào)用鏈,而其中的某一個(gè)接口可能會(huì)成為整個(gè)鏈路的瓶頸,導(dǎo)致系統(tǒng)性能下降或者不可用。鏈路模式允許在該接口的流量達(dá)到限制條件時(shí)進(jìn)行限流,以保護(hù)整個(gè)鏈路的穩(wěn)定性。
第1步: 編寫一個(gè)service,在里面添加一個(gè)方法message
@Service
class OrderServiceImpl2 {
@SentinelResource("message")
public void message() {
System.out.println("message");
}
}
第2步: 在Controller中聲明兩個(gè)方法,分別調(diào)用service中的方法message
@RestController
@Slf4j
public class OrderController5 {
@Autowired
private OrderServiceImpl2 orderService;
@RequestMapping("/order/message1")
public String message1() {
orderService.message();
return "message1";
}
@RequestMapping("/order/message2")
public String message2() {
orderService.message();
return "message2";
}
}
第3步:配置文件中將spring.cloud.sentinel.web-context-unify=true即可開啟收斂
在 Web 應(yīng)用中,同一個(gè)請求可能會(huì)有多種不同的 URL 地址和 HTTP 方法,例如 GET /user 和 POST /user 是兩個(gè)不同的請求,但它們都是對(duì)用戶資源的操作。如果不統(tǒng)一這些請求,會(huì)導(dǎo)致資源的重復(fù)計(jì)數(shù),從而影響限流效果。因此,通過設(shè)置
web-context-unify
為true
,Sentinel 可以將這些不同的請求統(tǒng)一為同一個(gè)資源,并對(duì)其進(jìn)行流量控制。
?第4步: 控制臺(tái)配置限流規(guī)則
?第5步: 分別通過/order/message1 和/order/message2 訪問, 發(fā)現(xiàn)1沒問題, 2的被限流了
配置流控效果
- 快速失?。J(rèn)): 直接失敗,拋出異常,不做任何額外的處理,是最簡單的效果
- Warm Up:它從開始閾值到最大QPS閾值會(huì)有一個(gè)緩沖階段,一開始的閾值是最大QPS閾值的 1/3,然后慢慢增長,直到最大閾值,適用于將突然增大的流量轉(zhuǎn)換為緩步增長的場景。
- 排隊(duì)等待:讓請求以均勻的速度通過,單機(jī)閾值為每秒通過數(shù)量,其余的排隊(duì)等待; 它還會(huì)讓設(shè) 置一個(gè)超時(shí)時(shí)間,當(dāng)請求超過超時(shí)間時(shí)間還未處理,則會(huì)被丟棄。
?
五、Feign整合Sentinel
①導(dǎo)入依賴
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
? ②在配置文件中開啟Feign對(duì)Sentinel的支持
# 開啟feign對(duì)sentinel的支持
feign:
sentinel:
enabled: true
? ?③創(chuàng)建容錯(cuò)類
@Component
public class FeignUserServiceImpl implements FeignUserService {
//容錯(cuò)類要求必須實(shí)現(xiàn)被容錯(cuò)的接口,并為每個(gè)方法實(shí)現(xiàn)容錯(cuò)方案
@Override
public String getByPath(String account) {
//寫入到自己的數(shù)據(jù)估值表中
//程序員看到就會(huì)來處理
return "容錯(cuò)類啟動(dòng)......";
}
}
④為被容器的接口指定容錯(cuò)類
@FeignClient(value = "produce" ,fallback = FeignUserServiceImpl.class)
@Primary
public interface FeignUserService {
@RequestMapping("/user/{account}")
public String getByPath(@PathVariable(value = "account") String account);
}
在Spring Cloud中,使用Feign進(jìn)行服務(wù)間的調(diào)用時(shí),可以通過設(shè)置fallback屬性來指定當(dāng)請求失敗或超時(shí)時(shí)的容錯(cuò)處理類。fallback屬性是一個(gè)接口的實(shí)現(xiàn)類,它會(huì)在調(diào)用失敗時(shí)被觸發(fā),以提供一個(gè)備用的處理邏輯。?
當(dāng)我們正常調(diào)用localhost:8084/test01的時(shí)候就會(huì)響應(yīng)相應(yīng)的結(jié)果
如果我們訪問的模塊服務(wù)宕機(jī)了就會(huì)跳轉(zhuǎn)到我們的容錯(cuò)類
?
我們?nèi)蒎e(cuò)類就會(huì)將請求信息進(jìn)行保存等待我們模塊服務(wù)正常后重新發(fā)送請求?
?
到這里我的分享就結(jié)束了,歡迎到評(píng)論區(qū)探討交流??!
??如果覺得有用的話還請點(diǎn)個(gè)贊吧 ??文章來源:http://www.zghlxwxcb.cn/news/detail-819095.html
文章來源地址http://www.zghlxwxcb.cn/news/detail-819095.html
到了這里,關(guān)于【Spring Cloud】Sentinel流量限流和熔斷降級(jí)的講解的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!