一、Sentinel簡(jiǎn)介
隨著微服務(wù)的流行,服務(wù)和服務(wù)之間的穩(wěn)定性變得越來(lái)越重要。Sentinel 以流量為切入點(diǎn),從流量控制、熔斷降級(jí)、系統(tǒng)負(fù)載保護(hù)等多個(gè)維度保護(hù)服務(wù)的穩(wěn)定性。
1、sentinel的特征
- 豐富的應(yīng)用場(chǎng)景: Sentinel 承接了阿里巴巴近 10 年的雙十一大促流量的核心場(chǎng)景,例如秒殺(即突發(fā)流量控制在系統(tǒng)容量可以承受的范圍)、消息削峰填谷、集群流量控制、實(shí)時(shí)熔斷下游不可用應(yīng)用等
- 完備的實(shí)時(shí)監(jiān)控: Sentinel 同時(shí)提供實(shí)時(shí)的監(jiān)控功能。您可以在控制臺(tái)中看到接入應(yīng)用的單臺(tái)機(jī)器秒級(jí)數(shù)據(jù),甚至 500 臺(tái)以下規(guī)模的集群的匯總運(yùn)行情況
-
廣泛的開(kāi)源生態(tài): Sentinel 提供開(kāi)箱即用的與其它開(kāi)源框架/庫(kù)的整合模塊,例如與 Spring Cloud、Dubbo、gRPC 的整合。您只需要引入相應(yīng)的依賴并進(jìn)行簡(jiǎn)單的配置即可快速地接入 Sentinel
-完善的 SPI 擴(kuò)展點(diǎn): Sentinel 提供簡(jiǎn)單易用、完善的 SPI 擴(kuò)展接口。您可以通過(guò)實(shí)現(xiàn)擴(kuò)展接口來(lái)快速地定制邏輯。例如定制規(guī)則管理、適配動(dòng)態(tài)數(shù)據(jù)源等
2、sentinel的主要特性
sentinel的開(kāi)源生態(tài)
sentinel 的架構(gòu)圖
3、sentinel的主要優(yōu)勢(shì)和特性
- 輕量級(jí),核心庫(kù)無(wú)多余依賴,性能損耗小
- 方便接入,開(kāi)源生態(tài)廣泛
- 豐富的流量控制場(chǎng)景
- 易用的控制臺(tái),提供實(shí)時(shí)監(jiān)控、機(jī)器發(fā)現(xiàn)、規(guī)則管理等能力
- 完善的擴(kuò)展性設(shè)計(jì),提供多樣化的 SPI 接口,方便用戶根據(jù)需求給 Sentinel 添加自定義的邏輯
4、sentinel與spring cloud Hystrix 對(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) | 開(kāi)箱即用,可配置規(guī)則、查看秒級(jí)監(jiān)控、機(jī)器發(fā)現(xiàn)等 | 不完善 |
常見(jiàn)框架的適配 | Servlet、Spring Cloud、Dubbo、gRPC 等 | Servlet、Spring Cloud Netflix |
5、sentinel分為兩個(gè)部分
- 核心庫(kù)(Java 客戶端): 不依賴任何框架/庫(kù),能夠運(yùn)行于所有 Java 運(yùn)行時(shí)環(huán)境,同時(shí)對(duì) Dubbo / Spring Cloud 等框架也有較好的支持
- 控制臺(tái)(Dashboard): 基于 Spring Boot 開(kāi)發(fā),打包后可以直接運(yùn)行,不需要額外的 Tomcat 等應(yīng)用容器
二、Sentinel安裝與使用
1、Sentinel控制臺(tái)的下載
下載地址:https://github.com/alibaba/Sentinel/releases/tag/1.8.3
我們選擇1.8.3版本,直接下載jar包
放到指定文件夾中
2、Sentinel控制臺(tái)的啟動(dòng)
cmd 啟動(dòng)jar包
java -jar sentinel-dashboard-1.8.3.jar
2、訪問(wèn)
瀏覽器輸入:localhost:8080
賬號(hào)密碼 默認(rèn)都是 sentinel
3、為服務(wù)打開(kāi)sentinel的監(jiān)控
引入sentinel依賴
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
<version>${spring-cloud-alibaba.version}</version>
</dependency>
專欄的上一篇文章已經(jīng)為項(xiàng)目引入了sentinel的依賴,以及介紹了feign的使用 感興趣的可以跳轉(zhuǎn)
手把手教你搭建springcloud alibaba微服務(wù)–openfeign
yml文件添加sentinel相關(guān)配置
server:
port: 9090
spring:
application:
name: mdx-shop-user
cloud:
nacos:
discovery:
server-addr: localhost:8848
namespace: mdx
group: mdx
sentinel:
transport:
dashboard: localhost:8080 #配置Sentinel dashboard地址
feign:
sentinel:
enabled: true
啟動(dòng)user服務(wù)并訪問(wèn)user服務(wù)的測(cè)試接口
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
private UserService userService;
@GetMapping("getOrderNo")
public String getOrderNo(String userId,String tenantId,HttpServletRequest request){
return userService.getOrderNo(userId,tenantId,request);
}
}
瀏覽器訪問(wèn)
http://localhost:9090/user/getOrderNo?userId=mdx123456&tenantId=123
然后查看sentinel控制臺(tái)
發(fā)現(xiàn)已經(jīng)監(jiān)控到了我們服務(wù)的接口
三、Sentinel的控制規(guī)則
1、流控規(guī)則
1.1、流控規(guī)則的各個(gè)屬性
- 資源名: 唯一名稱,默認(rèn)請(qǐng)求路徑,表示對(duì)該資源進(jìn)行流控
- 針對(duì)來(lái)源: Sentinel可以針對(duì)調(diào)用者進(jìn)行限流,填寫(xiě)微服務(wù)名,默認(rèn)default(不區(qū)分來(lái)源)
- 閾值類型/單擊閾值:
QPS:(每秒鐘的請(qǐng)求數(shù)量):當(dāng)調(diào)用該api的QPS達(dá)到閾值時(shí),進(jìn)行限流
線程數(shù):當(dāng)調(diào)用該線程數(shù)達(dá)到閾值的時(shí)候,進(jìn)行限流 - 是否集群:不需要集群
- 流控模式:
直接: api達(dá)到限流條件時(shí),直接限流
關(guān)聯(lián): 當(dāng)關(guān)聯(lián)的資源達(dá)到閾值時(shí),就限流自己
鏈路: 只記錄指定鏈路上的流量(指定資源從入口資源進(jìn)來(lái)的流量,如果達(dá)到閾值,就進(jìn)行限流)【api級(jí)別的針對(duì)來(lái)源】 - 流控效果:
快速失?。?直接失敗,拋異常
Warm Up: 根據(jù)codeFactor(冷加載因子,默認(rèn)3)的值,從閾值/codeFctor,經(jīng)過(guò)預(yù)熱時(shí)長(zhǎng),才達(dá)到設(shè)置的QPS閾值
排隊(duì)等待: 勻速排隊(duì),讓請(qǐng)求以勻速的速度通過(guò),閾值類型必須設(shè)置為QPS,否則無(wú)效
1.2、新增流控規(guī)則
資源名稱就是我們的接口訪問(wèn)路徑
然后我們一秒一次訪問(wèn)一下接口(正常)
http://localhost:9090/user/getOrderNo?userId=mdx123456&tenantId=123
可以看到正常返回?cái)?shù)據(jù)
接下來(lái)我們快速請(qǐng)求接口,一秒鐘點(diǎn)擊多次
發(fā)現(xiàn)已經(jīng)被限流了
1.3、流控規(guī)則–關(guān)聯(lián)流控模式
我們模擬一下流控模式中的關(guān)聯(lián)模式
關(guān)聯(lián): 當(dāng)關(guān)聯(lián)的資源達(dá)到閾值時(shí),就限流自己,也就是說(shuō)關(guān)聯(lián)的資源(接口),QPS為1時(shí),一秒內(nèi)被多次請(qǐng)求的時(shí)候,自己的接口就會(huì)被限流。
我們?cè)趗ser服務(wù)中創(chuàng)建一個(gè)關(guān)聯(lián)接口 /user/sentinelB
@GetMapping("sentinelB")
public String sentinelB(){
return "我是關(guān)聯(lián)接口";
}
然后修改一下流控規(guī)則
我們用jmeter模擬一下請(qǐng)求sentinelB接口
一秒3個(gè)請(qǐng)求并循環(huán)
在這期間我們?cè)L問(wèn)/user/getOrderNo接口
發(fā)現(xiàn)被限流了
2、@SentinelResource注解的使用
2.1、@SentinelResource的屬性
- value:作用指定資源名稱,必填
- entryType:entry類型,標(biāo)記流量的方向,指明是出口流量,還是入口流量;取值 IN/OUT ,默認(rèn)是OUT。非必填
-
blockHandler:處理BlockException的函數(shù)名稱,函數(shù)要求為
必須是public
返回類型與原方法一致
參數(shù)類型需要和原方法相匹配,并在最后加上BlockException類型的參數(shù)
默認(rèn)需和原方法在同一個(gè)類中,如果希望使用其他類的函數(shù),可配置blockHandlerClass,并指定blockHandlerClass里面的方法 -
blockHandlerClass:存放blockHandler的類。對(duì)應(yīng)的處理函數(shù)必須static修飾,否則無(wú)法解析。函數(shù)要求為:
必須是public
返回類型與原方法一致
參數(shù)類型需要和原方法相匹配,并在最后加上BlockException類型的參數(shù) -
fallback:用于在拋出異常的時(shí)候提供fallback處理邏輯。fallback函數(shù)可以針對(duì)所有類型的異常(除了execptionsToIgnore 里面排除掉的異常類型)進(jìn)行處理,函數(shù)要求為:
返回類型與原方法一致
參數(shù)類型需要和原方法相匹配,Sentinel 1.6版本之后,也可在方法最后加上Throwable類型的參數(shù)
默認(rèn)需和原方法在同一個(gè)類中,若希望使用其他類的函數(shù),可配置fallbackClass,并指定fallbackClass里面的方法 - fallbackClass:存放fallback的類。對(duì)應(yīng)的處理函數(shù)必須static修飾,否則無(wú)法解析,其他要求:同fallback。
-
defaultFallback:用于通用的 fallback 邏輯。默認(rèn)fallback函數(shù)可以針對(duì)所有類型的異常(除了 exceptionsToIgnore 里面排除掉的異常類型)進(jìn)行處理。若同時(shí)配置了 fallback 和 defaultFallback,以fallback為準(zhǔn)。函數(shù)要求:
返回類型與原方法一致
方法參數(shù)列表為空,或者有一個(gè)Throwable類型的參數(shù)
默認(rèn)需要和原方法在同一個(gè)類中,若希望使用其他類的函數(shù),可配置fallbackclass,并指定fallbackClass里面的方法。 - exceptionsToIgnore:指定排除掉哪些異常。排除的異常不會(huì)計(jì)入異常統(tǒng)計(jì),也不會(huì)進(jìn)入fallback邏輯,而是原樣拋出
- exceptionsToTrace:需要trace的異常
2.2、按照資源名稱的方式限流,并對(duì)限流流進(jìn)行友好處理
我們修改一下/user/getOrderNo接口的代碼,增加@SentinelResource注解,并做后續(xù)處理
演示代碼:
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
private UserService userService;
@GetMapping("getOrderNo")
@SentinelResource(value = "getOrderNoResource",blockHandler = "getOrderNoBlockHandler",blockHandlerClass = UserController.class)
public String getOrderNo(String userId, String tenantId, HttpServletRequest request){
return userService.getOrderNo(userId,tenantId,request);
}
/**
* 限流后續(xù)操作方法
* @param e
* @return
*/
public static String getOrderNoBlockHandler(String userId, String tenantId, HttpServletRequest request,BlockException e){
String msg = "不好意思,前方擁擠,請(qǐng)您稍后再試";
return msg;
}
}
其中 getOrderNoResource 為資源名稱,getOrderNoBlockHandler 為兜底方法的方法名稱,blockHandlerClass = UserController.class 這個(gè)是兜底方法所在的類, 與資源方法在同一個(gè)類中 這屬性可以省去,這里只是演示
注意:返回類型與原方法一致,參數(shù)類型需要和原方法相匹配,并在最后加上BlockException類型的參數(shù)
然后再修改一下流控規(guī)則,把資源名稱換成我們注解中的 getOrderNoResource
快速訪問(wèn)我們的接口,http://localhost:9090/user/getOrderNo?userId=mdx123456&tenantId=123
發(fā)現(xiàn)返回的信息已經(jīng)變成我們兜底方法自定義的返回提示了
3、熔斷規(guī)則
3.1、熔斷規(guī)則的幾種策略
- 慢調(diào)用比例 (SLOW_REQUEST_RATIO):選擇以慢調(diào)用比例作為閾值,需要設(shè)置允許的慢調(diào)用 RT(即最大的響應(yīng)時(shí)間),請(qǐng)求的響應(yīng)時(shí)間大于該值則統(tǒng)計(jì)為慢調(diào)用。當(dāng)單位統(tǒng)計(jì)時(shí)長(zhǎng)(statIntervalMs)內(nèi)請(qǐng)求數(shù)目大于設(shè)置的最小請(qǐng)求數(shù)目,并且慢調(diào)用的比例大于閾值,則接下來(lái)的熔斷時(shí)長(zhǎng)內(nèi)請(qǐng)求會(huì)自動(dòng)被熔斷。經(jīng)過(guò)熔斷時(shí)長(zhǎng)后熔斷器會(huì)進(jìn)入探測(cè)恢復(fù)狀態(tài)(HALF-OPEN 狀態(tài)),若接下來(lái)的一個(gè)請(qǐng)求響應(yīng)時(shí)間小于設(shè)置的慢調(diào)用 RT 則結(jié)束熔斷,若大于設(shè)置的慢調(diào)用 RT 則會(huì)再次被熔斷
- 異常比例 (ERROR_RATIO):當(dāng)單位統(tǒng)計(jì)時(shí)長(zhǎng)(statIntervalMs)內(nèi)請(qǐng)求數(shù)目大于設(shè)置的最小請(qǐng)求數(shù)目,并且異常的比例大于閾值,則接下來(lái)的熔斷時(shí)長(zhǎng)內(nèi)請(qǐng)求會(huì)自動(dòng)被熔斷。經(jīng)過(guò)熔斷時(shí)長(zhǎng)后熔斷器會(huì)進(jìn)入探測(cè)恢復(fù)狀態(tài)(HALF-OPEN 狀態(tài)),若接下來(lái)的一個(gè)請(qǐng)求成功完成(沒(méi)有錯(cuò)誤)則結(jié)束熔斷,否則會(huì)再次被熔斷。異常比率的閾值范圍是 [0.0, 1.0],代表 0% - 100%
- 異常數(shù) (ERROR_COUNT):當(dāng)單位統(tǒng)計(jì)時(shí)長(zhǎng)內(nèi)的異常數(shù)目超過(guò)閾值之后會(huì)自動(dòng)進(jìn)行熔斷。經(jīng)過(guò)熔斷時(shí)長(zhǎng)后熔斷器會(huì)進(jìn)入探測(cè)恢復(fù)狀態(tài)(HALF-OPEN 狀態(tài)),若接下來(lái)的一個(gè)請(qǐng)求成功完成(沒(méi)有錯(cuò)誤)則結(jié)束熔斷,否則會(huì)再次被熔斷
3.2、新建一個(gè)熔斷規(guī)則
我們先寫(xiě)一個(gè)新的接口并且睡眠一秒,使用注解資源名稱的形式,并創(chuàng)建自定義兜底方法
方法接口地址 /user/sentinelA
@GetMapping("/sentinelA")
@SentinelResource(value = "sentinelAResource" , fallback = "sentinelAResource", fallbackClass = UserSentinelResourceHandler.class)
public String sentinelA(){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("我是sentinelA");
return "我是sentinelA";
}
創(chuàng)建單獨(dú)的handler類來(lái)處理兜底方法
@Component
public class UserSentinelResourceHandler {
public static String sentinelAResource(Throwable throwable){
System.out.println("觸發(fā)熔斷,服務(wù)不可用");
return "觸發(fā)熔斷,服務(wù)不可用";
}
}
接著我們?cè)诳刂婆_(tái)新建一個(gè)熔斷規(guī)則(使用慢調(diào)用比例的策略)
我們對(duì)以上添加的熔斷規(guī)則解釋一下:
在 2 秒的統(tǒng)計(jì)時(shí)間(統(tǒng)計(jì)時(shí)長(zhǎng))內(nèi),對(duì)資源接口的請(qǐng)求數(shù)大于 5 (最小請(qǐng)求數(shù)),請(qǐng)求響應(yīng)時(shí)間(最大 RT)大于200毫秒的請(qǐng)求占比超過(guò)比例閾值 0.1 ,則下一個(gè)請(qǐng)求開(kāi)始觸發(fā)熔斷,熔斷時(shí)長(zhǎng)是 5 秒,也就是 5 秒內(nèi),熔斷器是打開(kāi)狀態(tài),這期間的請(qǐng)求都會(huì)觸發(fā)熔斷,5秒過(guò)后熔斷器關(guān)閉,此時(shí)熔斷器會(huì)進(jìn)入探測(cè)恢復(fù)狀態(tài)(HALF-OPEN 狀態(tài)),若接下來(lái)的一個(gè)請(qǐng)求響應(yīng)時(shí)間小于設(shè)置的慢調(diào)用 RT 則結(jié)束熔斷,若大于設(shè)置的慢調(diào)用 RT 則會(huì)再次被熔斷。
RT(平均響應(yīng)時(shí)間): 當(dāng)1s內(nèi)持續(xù)進(jìn)入5個(gè)請(qǐng)求,且對(duì)應(yīng)請(qǐng)求的平均響應(yīng)時(shí)間(秒級(jí))均超過(guò)閾值,那么在接下來(lái)的時(shí)間窗口期內(nèi),對(duì)該方法的調(diào)用都會(huì)自動(dòng)的熔斷。注意Sentinel默認(rèn)統(tǒng)計(jì)的RT上限是4900ms,超出此閾值的都會(huì)算作4900ms,若需要更改上限可以通過(guò)啟動(dòng)配置項(xiàng)-Dcsp.sentinel.statistic.max.rt=xxx來(lái)配置
然后我們測(cè)試一下
模擬下并發(fā),一秒十個(gè)請(qǐng)求循環(huán)調(diào)用
我們發(fā)現(xiàn)觸發(fā)閾值之后 已經(jīng)觸發(fā)了熔斷機(jī)制,如下
3、熱點(diǎn)規(guī)則
熱點(diǎn)即經(jīng)常訪問(wèn)的數(shù)據(jù)。很多時(shí)候我們希望統(tǒng)計(jì)某個(gè)熱點(diǎn)數(shù)據(jù)中訪問(wèn)頻次最高的數(shù)據(jù),并對(duì)其訪問(wèn)進(jìn)行限制,比如對(duì)某個(gè)商品id進(jìn)行限制,或者對(duì)某個(gè)用戶id進(jìn)行限制
3.1、熱點(diǎn)規(guī)則屬性
參數(shù)索引:方法中參數(shù)的索引第幾個(gè)參數(shù)
單機(jī)閾值:每秒達(dá)到單機(jī)閾值的數(shù)量就會(huì)觸發(fā)兜底方法
4.1、新建一個(gè)熱點(diǎn)規(guī)則
我們先創(chuàng)建一個(gè)測(cè)試方法,使用注解資源名稱的形式,并創(chuàng)建自定義兜底方法
/**
* 測(cè)試centinel熱點(diǎn)規(guī)則限流
* @param userId
* @param shopId
* @return
*/
@GetMapping("/hotspot")
@SentinelResource(value = "hotspotResource" , blockHandler = "hotspotResource", blockHandlerClass = UserSentinelResourceHandler.class)
public String hotspot(@RequestParam(value = "userId" ,required = false) String userId,
@RequestParam(value = "shopId" ,required = false) String shopId){
System.out.println("我是hotspot");
return "我是hotspot";
}
兜底方法
public static String hotspotResource(String userId, String shopId,BlockException blockException){
System.out.println("您被認(rèn)為惡意訪問(wèn),觸發(fā)熱點(diǎn)限流");
return "您被認(rèn)為惡意訪問(wèn),觸發(fā)熱點(diǎn)限流";
}
然后我們?cè)诳刂婆_(tái)新建熱點(diǎn)規(guī)則
其中參數(shù)索引 0 代表的就是userId這個(gè)參數(shù)
我們?cè)L問(wèn)一下接口
先訪問(wèn)帶shopId的(一秒內(nèi)多次訪問(wèn)) http://localhost:9090/user/hotspot?shopId=4
正常返回
再訪問(wèn)下帶userId參數(shù)的(一秒內(nèi)多次訪問(wèn)) http://localhost:9090/user/hotspot?userId=4
返回降級(jí)函數(shù)的內(nèi)容
4、系統(tǒng)規(guī)則
系統(tǒng)保護(hù)規(guī)則是從應(yīng)用級(jí)別的入口流量進(jìn)行控制,從單臺(tái)機(jī)器的 load、CPU 使用率、平均 RT、入口 QPS 和并發(fā)線程數(shù)等幾個(gè)維度監(jiān)控應(yīng)用指標(biāo),讓系統(tǒng)盡可能跑在最大吞吐量的同時(shí)保證系統(tǒng)整體的穩(wěn)定性
如果配置了系統(tǒng)規(guī)則,所有的接口都會(huì)被限流
這里系統(tǒng)規(guī)則就不演示了,關(guān)于sentinel還有很多規(guī)則,策略和屬性,大家有興趣可以自行研究下。
關(guān)于sentinel的使用篇就到這里了。
創(chuàng)作不易,點(diǎn)個(gè)贊吧??
最后的最后送大家一句話
白駒過(guò)隙,滄海桑田
與君共勉
上一篇文章
springcloud alibaba微服務(wù) – openfeign的使用(保姆級(jí))
下一篇文章
springcloud alibaba – seata原理和使用文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-603352.html
文末送福利啦~
1、Java(SE、JVM)、算法數(shù)據(jù)結(jié)構(gòu)、數(shù)據(jù)庫(kù)(Mysql、redis)、Maven、Netty、RocketMq、Zookeeper、多線程、IO、SSM、Git、Linux、Docker、Web前端相關(guān)學(xué)習(xí)筆記
2、2023最新BATJ大廠面試題集
3、本教程項(xiàng)目源碼
領(lǐng)取方式:關(guān)注下方公主號(hào),回復(fù):【筆記】、【面試】、【mdx-shop】獲取相關(guān)福利。
文章持續(xù)更新,可以關(guān)注下方公眾號(hào)或者微信搜一搜「 最后一支迷迭香 」獲取項(xiàng)目源碼、干貨筆記、面試題集,第一時(shí)間閱讀,獲取更完整的鏈路資料。文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-603352.html
到了這里,關(guān)于SpringCloud Alibaba微服務(wù)-- Sentinel的使用(保姆級(jí))的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!