目錄
二. Docker部署Sentinel Dashboard
- 5. 網關流控客戶端標識
- 7. Nacos添加網關流控規(guī)則
- 9. 自定義網關流控異常
六. Sentinel整合Feign熔斷降級
一. Sentinel概念
1. 什么是Sentinel?
Sentinel是阿里中間件團隊研發(fā)面向分布式服務架構的輕量級高可用流量控制組件,主要以流量為切入點蝴光,從限流她渴、流量整形、熔斷降級蔑祟、系統(tǒng)負載保護惹骂、熱點防護等多個維度來幫助開發(fā)者保障微服務的穩(wěn)定性。于2012年誕生做瞪,后續(xù)在阿里巴巴集團內部迅速發(fā)展对粪,成為基礎技術模塊右冻,覆蓋了所有的核心場景,Sentinel也因此積累了大量的流量歸整場景及生產實踐著拭。最終在2018年7月宣布對外界開源纱扭。
Sentinel的基本概念:
- 資源: Sentinel 的關鍵概念,可以是Java應用程序中任何內容儡遮,通過Sentinel API定義的代碼乳蛾,能夠被Sentinel保護起來,大部份情況下鄙币,可以使用方法簽名肃叶,URL,甚至服務名稱作為資源名
- 規(guī)則: 圍繞資源的實時狀態(tài)設定的規(guī)則十嘿,可以包括流量控制規(guī)則因惭、熔斷降級規(guī)則以及系統(tǒng)保護規(guī)則。所有規(guī)則可以動態(tài)實時調整绩衷。
Sentinel分為兩個部分:
- 控制臺(Dashboard)基于 Spring Boot 開發(fā)蹦魔,打包后可以直接運行,不需要額外的 Tomcat 等應用容器咳燕,也就是sentinel-dashboard-1.8.1.jar勿决。
- 核心庫(Java 客戶端)不依賴任何框架/庫,能夠運行于所有 Java 運行時環(huán)境招盲,同時對 Dubbo / Spring Cloud 等框架也有較好的支持低缩。
2. Sentinel功能特性
從上圖可知Sentinel的功能特性很多以及應用場景非常廣泛,以下就 限流
曹货、 熔斷降級
這幾個常見的功能特性以及意義進行簡要說明
限流:限流同時也叫做流量控制表制,原理是監(jiān)控應用流量的QPS或并發(fā)線程數等指標,當達到指定的閾值時對流量進行控制控乾,以避免被瞬時的流量高峰沖垮么介,從而保障應用的高可用性。
熔斷降級:除了流量控制以外蜕衡,及時對調用鏈路中的不穩(wěn)定因素進行熔斷也是Sentinel的使命之一壤短。由于調用關系的復雜性,如果調用鏈路中的某個資源不穩(wěn)定慨仿,最終會導致請求發(fā)生堆積久脯,進而導致級聯錯誤。Sentinel當檢測到調用鏈路中某個資源出現不穩(wěn)定的表現(請求響應時間長或異常比例升高)镰吆,則對這個資源的調用進行限制帘撰,讓請求快速失敗,避免影響到其他資源而導致級聯故障万皿。
- 熔斷: 拒絕流量訪問摧找,當系統(tǒng)恢復正常時關閉熔斷核行。
- 降級: 將次要服務降級,停止服務蹬耘,將系統(tǒng)資源放出來給核心功能
3. Sentinel VS Hystrix
以下摘自Sentinel官方文檔芝雪,詳情點擊 Sentinel 與 Hystrix 的對比
Sentinel | Hystrix | |
---|---|---|
隔離策略 | 信號量隔離 | 線程池隔離/信號量隔離 |
熔斷降級策略 | 基于響應時間或失敗比率 | 基于失敗比率 |
實時指標實現 | 滑動窗口· | 滑動窗口(基于 RxJava) |
規(guī)則配置 | 支持多種數據源 | 支持多種數據源 |
擴展性 | 多個擴展點 | 插件的形式 |
基于注解的支持 | 支持 | 支持 |
限流 | 基于 QPS,支持基于調用關系的限流 | 有限的支持 |
流量整形 | 支持慢啟動综苔、勻速器模式 | 不支持 |
系統(tǒng)負載保護 | 支持 | 不支持 |
控制臺 | 開箱即用惩系,可配置規(guī)則、查看秒級監(jiān)控如筛、機器發(fā)現等 | 不完善 |
常見框架的適配 | Servlet堡牡、Spring Cloud、Dubbo杨刨、gRPC 等 | Servlet晤柄、Spring Cloud Netflix |
Sentinel 和 Hystrix 的原則是一致的,但是在限制手段上拭嫁,Sentinel和Hystrix采取了完全不一樣的方法。
-
Hystrix: 通過線程池隔離抓于,來對依賴(在Sentinel的概念對應
資源
)進行了隔離做粤。好處在于資源之間做到最徹底的隔離,缺點是除了增加了線程切換的成本捉撮,還需要預先給各個資源做線程池大小的分配怕品。 - Sentinel : 通過并發(fā)線程數進行限制和響應時間對資源進行降級兩種手段。
二. Docker部署Sentinel Dashboard
1. 拉取鏡像
docker pull bladex/sentinel-dashboard
2. 啟動容器
docker run --name sentinel -d -p 8858:8858 -d bladex/sentinel-dashboard
3. 訪問測試
訪問: http://IP:8858
用戶名/密碼:sentinel/sentinel
三. Sentinel網關流控
1. 網關流控定義
Sentinel支持對Spring Cloud Gateway巾遭、Zuul等主流的API Gataway 進行限流肉康,作用在網關的流控稱之為 網關流控
,其實現原理請點擊 網關限流 進入官方Wiki查看灼舍。
這里只把原理圖從官方文檔摘出來吼和,需多關注圖中提到的模塊名和幾個類名,因為都是 核心 級別的存在骑素。
規(guī)則類型 gw-flow
和 gw-api-group
為網關流控規(guī)則炫乓,具體類型請查看規(guī)則類型枚舉 RuleType
/**
* flow 流控規(guī)則
*/
FLOW("flow", FlowRule.class),
/**
* degrade 降級規(guī)則
*/
DEGRADE("degrade", DegradeRule.class),
/**
* param flow 熱點規(guī)則
*/
PARAM_FLOW("param-flow", ParamFlowRule.class),
/**
* system 系統(tǒng)規(guī)則
*/
SYSTEM("system", SystemRule.class),
/**
* authority 授權規(guī)則
*/
AUTHORITY("authority", AuthorityRule.class),
/**
* gateway flow 網關限流規(guī)則
*/
GW_FLOW("gw-flow","com.alibaba.csp.sentinel.adapter.gateway.common.rule.GatewayFlowRule"),
/**
* api 用戶自定義的 API 定義分組,可以看做是一些 URL 匹配的組合
*/
GW_API_GROUP("gw-api-group","com.alibaba.csp.sentinel.adapter.gateway.common.api.ApiDefinition");
2. 網關流控規(guī)則
Field | 說明 | 默認值 |
---|---|---|
resource | 資源名稱献丑,網關route或自定義API分組名稱(注:網關route這里的值不是route.id,可調試 | |
resourceMode | 限流資源類型末捣,網關route【0】或自定義API分組【1】(詳細查看 GatewayFlowRule 和 SentinelGatewayConstants ) |
網關route |
grade | 限流閾值類型,QPS【1】或線程數【0】 | QPS |
count | 限流閾值创橄,QPS閾值或線程數值 | |
intervalSec | 統(tǒng)計時間間隔箩做,單位秒 | 1秒 |
controlBehavior | 流控效果,目前支持快速失敗【0】和勻速排隊【1】 | 快速失敗 |
burst | 應對突發(fā)請求時額外允許的請求數目 | |
maxQueueingTimeoutMs | 勻速排隊模式下的最長排隊時間妥畏,單位毫秒邦邦,僅在勻速排隊模式下生效 | |
paramItem | 參數屬性配置安吁,parseStrategy:提取參數策略(0:Clien IP,1:Remote HOST圃酵,2:Header柳畔,3:請求參數,4:Cookie)郭赐;fieldName:若提取策略是Header模式或者URL參數模式薪韩,則需要指定header名稱或URL參數名稱;pattern:參數值的匹配模式捌锭;matchStrategy:參數值的匹配策略俘陷,支持精確匹配,子串匹配和正則匹配观谦。 |
3. 導入依賴
<!-- Sentinel流量控制拉盾、熔斷降級 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-sentinel-gateway</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<!-- Sentinel規(guī)則持久化至Nacos配置 -->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
</dependency>
4. 網關配置
先放在本地Spring Boot配置文件bootstrap-dev.yml中,后面測試通過把后再把Sentinel配置放至Nacos
spring:
cloud:
nacos:
# 注冊中心
discovery:
server-addr: http://localhost:8848
# 配置中心
config:
server-addr: ${spring.cloud.nacos.discovery.server-addr}
file-extension: yaml
sentinel:
enabled: true # sentinel開關
eager: true
transport:
dashboard: localhost:8080 # Sentinel控制臺地址
client-ip: localhost
datasource:
# 網關限流規(guī)則豁状,gw-flow為key捉偏,隨便定義
gw-flow:
nacos:
server-addr: ${spring.cloud.nacos.discovery.server-addr}
dataId: ${spring.application.name}-gw-flow-rules # 流控規(guī)則配置文件名:youlai-gateway-gw-flow-rules
groupId: SENTINEL_GROUP
data-type: json
rule-type: gw-flow
# 自定義API分組,gw-api-group為key泻红,隨便定義
gw-api-group:
nacos:
server-addr: ${spring.cloud.nacos.discovery.server-addr}
dataId: ${spring.application.name}-gw-api-group-rules # 流控規(guī)則配置文件名:youlai-gateway-gw-api-group-rules
groupId: SENTINEL_GROUP
data-type: json
rule-type: gw-api-group
這里解釋下配置中的datasource夭禽,因為在Sentinel添加流控規(guī)則之后,如果重啟服務谊路,之前配置的規(guī)則就會消失讹躯,所以這里需要持久化Sentinel配置,從上面的配置可以看出選擇的是Nacos缠劝。不過這里先別急在Nacos添加網關流控規(guī)則潮梯,下文在測試確認需求后配置。
5. 網關流控客戶端標識
網關流控和普通流控有很多區(qū)別惨恭,其中網關流控類型是 gw-flow
秉馏,普通流控類型是 flow
怎么標識流控是網關類型呢?
很多博客文章都沒有著重此點脱羡,因為前陣子糾結于網關流控的面板和普通流控的面板不一致而去搜相關的資料沃饶,最后還是在Sentinel官方文檔中找到此開關,就是需要在 youlai-gateway
網關應用添加JVM啟動參數轻黑。
# 注:通過 Spring Cloud Alibaba Sentinel 自動接入的 API Gateway 整合則無需此參數
-Dcsp.sentinel.app.type=1
具體如下圖:
6. 測試需求制定
在做好上面Sentinel Dashboard部署以及Spring Cloud Gateway整合Sentinel工作之后糊肤,Sentinel的兩個部分(控制臺和Java客戶端)也就齊活了,那么接下來就進入測試氓鄙。
下圖簡單的描述了OAuth2認證接口的流程馆揉,用戶請求網關,網關(youlai-gateway)根據請求標識轉發(fā)至認證中心抖拦,認證中心(youlai-auth)需要從系統(tǒng)服務(youlai-admin)獲取數據庫的用戶信息再和請求攜帶的用戶信息進行密碼判讀升酣,成功則返回token給用戶舷暮。
針對以上的OAuth2認證流程,提出來一個需求:
假設認證中心服務的QPS上限為10噩茄,系統(tǒng)服務的QPS上限為5下面,如何通過Sentinel實現限流控制?
溫馨提示:留意下上圖中的紅線部分绩聘,你認為網關的流控是否能限制到與其間接相關的系統(tǒng)服務youlai-admin嗎沥割?
7. Nacos添加網關流控規(guī)則
進入Nacos控制臺,添加網關流控規(guī)則凿菩,具體內容參考網關流控字段說明机杜。
需要注意的是 資源名稱resource不是路由中配置的route的id ,在開啟Sentinel時調試SentinelGatewayFilter#filter方法可以看到自動生成的是固定前綴ReactiveCompositeDiscoveryClient_拼接應用名稱${spring.application.name}衅谷,所以在配置文件中一定要按照自動生成的規(guī)則配置resource的值椒拗。填寫網關路由route的id,Sentinel的網關流控是無法生效的获黔。
上面網關流控規(guī)則中蚀苛,限制了認證中心youlai-auth的QPS上限為10,系統(tǒng)服務youlai-admin的QPS上限為5玷氏。
至于為什么這么設定堵未,因為有個猜想需要驗證,網關流控是否只能限制和直接關聯的youlai-auth预茄,而不能限制間接相關的youlai-admin兴溜。
如果通過的QPS是10侦厚,那說明網關流控不能控制間接相關youlai-admin耻陕,如果通過的QPS是5,則說明網關流控能控制間接相關的youlai-admin刨沦,至于結果诗宣,先留個懸念吧,看下文的測試結果想诅。
已添加的網關流控規(guī)則如下圖:
在Nacos添加了網關流控規(guī)則之后召庞,會同步到Sentinel,進入Sentinel控制臺查看
8. 網關流控測試
在完成上述步驟之后来破,接下來就進入真正的測試環(huán)節(jié)篮灼。
添加線程組
測試計劃(鼠標右擊)->添加->線程(用戶)->線程組
因為youlai-auth的QPS處理上限為10,所以這里的線程數大于10即可看到被限制的請求
添加HTTP請求
OAuth2登錄線程組(鼠標右擊)->添加->取樣器->HTTP請求
接口是通過網關轉發(fā)到認證中心的認證接口獲取token
添加察看結果樹
因為要看請求的響應徘禁,所以這里添加察看結果樹诅诱。
OAuth2登錄線程組(鼠標右擊)->添加->監(jiān)聽器->察看結果樹
啟動線程組測試
啟動線程組,每秒15次認證請求送朱,需要注意的是娘荡,如果測試計劃有多個線程組干旁,需禁用除了測試之外的其他線程組。
點擊 察看結果樹
查看請求的情況
進入Sentinel控制臺炮沐,查看實時監(jiān)控
可以看到1秒15次請求争群,因為流控設置的QPS上限是10,所以10次通過大年,被Sentinel拒絕了5次换薄。
這個結果也直接說明了網關流控并不是萬能的,不能限制OAuth2認證請求中與其間接相關 youlai-admin
的微服務鲜戒,因為在網關流控設置了 youlai-admin
的QPS上線為5专控,但最后整條鏈路成功的卻是10。既然 網關流控
無法應對此類場景遏餐,是否還有其他的辦法來做到呢伦腐?當然有: 普通流控
。
9. 自定義網關流控異常
上面Sentinel限流的默認異常響應如下
{"code":429,"message":"Blocked by Sentinel: ParamFlowException"}
假如想自定義網關流控異常響應失都,該如何實現呢柏蘑?
可以通過在GatewayCallbackManager上通過setBlockHandler方法注冊回調實現,當請求被限流后粹庞,實現自定義的異常響應咳焚。
自定義異常代碼:
>@PostConstruct
private void initBlockHandler() {
BlockRequestHandler blockRequestHandler = (exchange, t) ->
ServerResponse.status(HttpStatus.OK)
.contentType(MediaType.APPLICATION_JSON)
.body(BodyInserters.fromValue(ResultCode.FLOW_LIMITING.toString()));
GatewayCallbackManager.setBlockHandler(blockRequestHandler);
}
JMeter中查看被限流的響應,可以看到已按照自定義的響應異常返回庞溜,其中 B0210
是Java開發(fā)手冊上的關于 系統(tǒng)限流
的錯誤碼
四. Sentinel普通流控
1. 普通流控定義
/**
* flow 流控規(guī)則革半,詳情查看RuleType
*/
FLOW("flow", FlowRule.class)
作用在網關的流控稱之為 網關流控
,相對的作用在除網關之外的微服務流控這里稱為 普通流控
在上一個章節(jié)中流码,發(fā)現網關流控并不是萬能的又官,像認證中心 youlai-auth
調用系統(tǒng)服務 youlai-admin
這種微服務相互調用而不走網關的情況,網關流控表示無能為力漫试,但不可否認的是網關流控確實能夠應對大多數場景的流控六敬。
所以在像上文中的網關流控無能為力的案例,則需要普通流控的救場驾荣。
2. 普通流控的規(guī)則
Field | 說明 | 默認值 |
---|---|---|
resource | 資源名外构,資源名是限流規(guī)則的作用對象 | |
count | 限流閾值 | |
grade | 限流閾值類型,QPS 【1】或線程數模式【0】 | QPS 模式 |
limitApp | 流控針對的調用來源 |
default 播掷,代表不區(qū)分調用來源 |
strategy | 判斷的根據是資源自身审编,還是根據其它關聯資源 ( refResource ),還是根據鏈路入口 |
根據資源本身 |
controlBehavior | 流控效果(直接拒絕 / 排隊等待 / 慢啟動模式) | 直接拒絕 |
3. 導入依賴
<!-- Sentinel流量控制歧匈、熔斷降級 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<!-- Sentinel規(guī)則持久化至Nacos配置 -->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
</dependency>
4. 微服務配置
spring:
application:
name: youlai-admin
cloud:
nacos:
discovery:
server-addr: http://localhost:8848
config:
server-addr: ${spring.cloud.nacos.discovery.server-addr}
file-extension: yaml
sentinel:
enabled: true
eager: true # 取消控制臺懶加載垒酬,項目啟動即連接Sentinel
transport:
client-ip: localhost
dashboard: localhost:8080
datasource:
# 限流規(guī)則,flow為key,隨便定義
flow:
nacos:
server-addr: ${spring.cloud.nacos.discovery.server-addr}
dataId: ${spring.application.name}-flow-rules
groupId: SENTINEL_GROUP
data-type: json
rule-type: flow
5. Nacos添加流控規(guī)則
進入Nacos控制臺伤溉,添加規(guī)則配置文件实束,接著上文的案例猬仁,在認證的時候,youlai-auth需通過feign調用youlai-admin根據用戶名獲取用戶信息。
進入Sentinel控制臺查看悬嗓,除了剛在Nacos添加的規(guī)則之外洋访,還可以看到普通流控面板和網關流控面板的區(qū)別
6. 普通流控測試
經過網關流控限制只能有10條請求到y(tǒng)oulai-auth银择,接下來youlai-auth調用youlai-admin鏈路中邮旷,因為限制了youlai-admin的QPS上限為5,所以最終應該是只有5條請求是有效的伏伯¢俣矗看測試結果:
7. 自定義異常
上面被限流后的異常信息,顯然不是想要的说搅,那么如何自定義普通流控異常呢炸枣?
解決方案:實現 BlockExceptionHandler
接口
@Component
public class DefaultBlockExceptionHandler implements BlockExceptionHandler {
@Override
public void handle(HttpServletRequest request, HttpServletResponse response, BlockException e) throws Exception {
response.setStatus(HttpStatus.ok().status());
response.setCharacterEncoding("UTF-8");
response.setContentType("application/json;charset=utf-8");
if(e instanceof FlowException){
// objectMapper.writeValue 用于將java對象轉位JSON格式返回調用方
new ObjectMapper().writeValue(response.getWriter(), Result.failed(ResultCode.FLOW_LIMITING));
}
}
}
為了測試普通流控,首先關閉網關流控弄唧,排除一些異常干擾
添加獲取當前登錄用戶信息的HTTP請求
因為此HTTP接口需要認證适肠,所以需要在請求頭添加token。鼠標右擊HTTP請求->添加->配置元件->HTTP信息頭管理
HTTP信息頭管理器添加token
執(zhí)行線程組候引,查看自定義異常生效
五. Sentinel熔斷降級
1. 熔斷降級概述
微服務架構都是分布式的侯养,不同服務相互調用,組成復雜的調用鏈路澄干。復雜的鏈路上某一環(huán)不穩(wěn)定逛揩,就可能層層級聯,最終導致整個鏈路都不可用麸俘。因此需要對不穩(wěn)定的弱依賴服務調用進行熔斷降級辩稽,暫時切斷不穩(wěn)定的調用,避免局部不穩(wěn)定因素導致正題的雪崩疾掰。熔斷降級作為保護自身的手段搂誉,通常在客戶端(調用端)進行配置徐紧。
2. 熔斷策略
Sentinel提供了三種熔斷策略:
- 慢調用比例 : 請求響應時間大于設置的RT(即最大的響應時間)則統(tǒng)計為慢調用静檬。觸發(fā)此熔斷策略的條件需要滿足兩個條件,一是單位統(tǒng)計時長(statIntervalMs)內請求數大于設置的最小請求數并级,二是慢調用的比例大于閾值拂檩,接下來在熔斷時長的范圍內請求會自動的被熔斷。過了熔斷時長后嘲碧,熔斷器進入 探測恢復狀態(tài) (HALF-OPEN狀態(tài))稻励,若接下來的一個請求響應時間小于設置的慢調用RT則結束熔斷,若大于設置的慢調用RT則會再次被熔斷。
- 異常比例 :當單位統(tǒng)計時長請求數大于設置的最小請求數望抽,并且異常的比例大于閾值加矛,則接下來的熔斷時長內請求會被自動熔斷。
- 異常數 :當單位統(tǒng)計時長內的異常數目超過閾值之后會自動進行熔斷煤篙。
3. 熔斷降級規(guī)則
熔斷降級規(guī)則(DegradeRule)包含下面幾個重要的屬性:
Field | 說明 | 默認值 |
---|---|---|
resource | 資源名斟览,即規(guī)則的作用對象 | |
grade | 熔斷策略,支持慢調用比例/異常比例/異常數策略 | 慢調用比例 |
count | 慢調用比例模式下為慢調用臨界 RT(超出該值計為慢調用)辑奈;異常比例/異常數模式下為對應的閾值 | |
timeWindow | 熔斷時長苛茂,單位為 s | |
minRequestAmount | 熔斷觸發(fā)的最小請求數,請求數小于該值時即使異常比率超出閾值也不會熔斷(1.7.0 引入) | 5 |
statIntervalMs | 統(tǒng)計時長(單位為 ms)鸠窗,如 60*1000 代表分鐘級(1.8.0 引入) | 1000 ms |
slowRatioThreshold | 慢調用比例閾值妓羊,僅慢調用比例模式有效(1.8.0 引入) |
4. 微服務配置
<pre class="prettyprint hljs yaml" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; overflow-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">spring:
cloud:
sentinel:
# 降級規(guī)則,degrade為降級key稍计,隨便取名
degrade:
nacos:
server-addr: {spring.application.name}-degrade-rules
groupId: SENTINEL_GROUP
data-type: json
rule-type: degrade
復制代碼</pre>
5. Nacos添加熔斷降級規(guī)則
方便看到異常熔斷的效果躁绸,選擇了 異常數 的熔斷策略,畢竟數數比計算比例簡單多了臣嚣。資源名為getCurrentUser是怎么回事涨颜,不急下文提到〖肭颍總之這里的配置的大概意思就是說針對getCurrentUser資源庭瑰,如果請求該接口出現了異常,則進行熔斷抢埋,熔斷時長為5秒弹灭。
6. 熔斷異常模擬
先模擬一段在運行時發(fā)生異常的代碼,在獲取當前登錄用戶信息的接口埋個雷吧揪垄,注意到@SentinelResource注解中的value值getCurrentUser穷吮,也就是資源名稱,聯系上文饥努,降級規(guī)則就是針對這個接口的方法捡鱼。和上面在普通流控測試使用的是請求的路徑不同,這里顯示指定了資源名稱和降級規(guī)則配置去做匹配酷愧。
@SentinelResource注解中的屬性除了定義資源名的屬性值value驾诈,還有兩個屬性有關降級處理分別是blockHandlerClass和blockHandler。意思是在單位時間接口異常數超過設置的閾值后進入熔斷溶浴,在熔斷時長(上面降級規(guī)則中設置的是5秒)范圍內乍迄,再有請求過來訪問該接口時,不會再走接口方法體內的邏輯士败。因為前面幾次接口出現異常闯两,那么敢斷定接下來短時間內大概率還是會發(fā)生異常,所以索性就把后續(xù)的請求攔截避免,這也是熔斷的意義漾狼。
在5秒的熔斷時長內重慢,如果再有請求訪問該接口則會走降級的邏輯,也就是上圖中指定的UserBlockHandler#handleGetCurrentUserBlock降級處理方法逊躁。
7. 熔斷降級測試
在測試前伤锚,需要關閉網關那邊流控,排除一些異常情況下的干擾志衣。還有為了方便在JMeter查看結果屯援,臨時關閉全局異常處理器GlobalExceptionHandler。
還是拿上一節(jié)配置好的測試普通流控的線程組念脯, 獲取登錄用戶的信息 來作為熔斷降級的測試案例狞洋,先看一下線程組的設置:
線程數為10,達到了熔斷降級 最小請求數 (規(guī)則配置的5)的要求
獲取登陸用戶信息的接口信息
請求頭添加token
測試線程組配置好之后看看使用不使用熔斷降級和使用熔斷降級的區(qū)別:
- 不使用熔斷降級
配置中關閉Sentinel
<pre class="prettyprint hljs yaml" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; overflow-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">sentinel:
enabled: false
復制代碼</pre>
發(fā)現了嗎绿店?這種請求異常處理模式頭鐵啊吉懊,即使撞了南墻也不會回頭,下次繼續(xù)撞假勿,下下次繼續(xù)撞借嗽。ok,你沒關系转培,那你有考慮一直被你撞的墻(服務器)了沒恶导?
- 使用熔斷降級
配置中開啟Sentinel
<pre class="prettyprint hljs yaml" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; overflow-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">sentinel:
enabled: true
復制代碼</pre>
通過日志可以看到進入主線代碼的只有一次,后續(xù)的請求直接進入降級支線浸须。
過了熔斷時長5秒后惨寿,熔斷器進入 探測恢復狀態(tài) (HALF-OPEN狀態(tài)),這時候如果一個請求到主線沒異常删窒,關閉熔斷器裂垦,讓后續(xù)的請求都到主線過來;如果還是異常肌索,打開熔斷器蕉拢。
六. Sentinel整合Feign熔斷降級
1. Feign與Sentinel整合意義
在微服務架構中,聲明式調用Feign在微服務之間調用充當重要的角色诚亚,在使用Feign的過程中如果為了系統(tǒng)的健壯性晕换,一定會考慮如果因目標服務異常調用失敗后的處理。
說到這里亡电,相信對微服務有些了解的童鞋對下面的代碼很熟悉:
上面兩張圖反應了Feign客戶端在遠程調用目標服務失敗后届巩,繼而選擇了降級的邏輯硅瞧,像做人一樣隨時要給自己留一條后路份乒,也就是穩(wěn),折射到程序亦是如此。這里只是一個降級的自定義異常返回或辖,實際情況根據業(yè)務而定瘾英。
看到上面的代碼,Feign在設計上就支持了降級的處理颂暇。這時候相信大家都會有一個疑問缺谴,Feign本身已經支持降級,那還需要Sentinel做什么耳鸯?
換句話說可能會好理解一點湿蛔,Sentinel給Feign帶來了什么好處?
這個問題其實不難理解县爬,先直接從字面上切入阳啥。
Feign是能夠做到降級,Sentinel能夠實現熔斷降級财喳,突顯出來也就是 熔斷
這一詞察迟,其中 熔斷
的具體表象是怎樣的?舉個栗子說明:
假如客戶端a通過feign調用b服務100次耳高,此時b服務故障
-
沒有熔斷
a的第1次請求走到b服務跟前扎瓶,看著b躺在地上沒動靜,響應給客戶端a說b沒動靜泌枪,讓客戶端a自己看著辦吧概荷。后面如此往復99次,每次a都需要走到b的面前然后再響應給客戶端a碌燕,并告知b故障了乍赫。
-
有熔斷
a的第1次請求走到b服務跟前,看著b躺在地上沒動靜陆蟆,這時候a就比較機智雷厂,判斷b服務沒有一時半刻是起不來了,就響應給客戶端a并說這一時半刻鐘的請求你自己看著處理吧叠殷,沒有必要再到b面前改鲫,后面的99次請求就不會再到服務b那里了,省時省力林束。
想通過上面的舉例說明熔斷的意義和作用像棘,因為Feign已經支持了降級,那再搭配上Sentinel的熔斷壶冒,豈不是如虎添翼缕题?
接下來將通過 有來項目
中的實例,認證中心【youlai-auth】在登錄時需要遠程feign調用系統(tǒng)服務【youlai-admin】的根據用戶名獲取用戶信息的接口胖腾,來說明Sentinel如何整合Feign實現熔斷降級及熔斷降級的魅力烟零。
2. 導入依賴
youlai-auth添加Sentinel和Nacos持久化規(guī)則依賴
<pre class="prettyprint hljs xml" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; overflow-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
</dependency>
復制代碼</pre>
3. 微服務配置
youlai-auth開啟Feign對Sentinel的支持
<pre class="prettyprint hljs yaml" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; overflow-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">spring:
application:
name: youlai-auth
cloud:
sentinel:
enabled: true
eager: true # 取消控制臺懶加載瘪松,項目啟動即連接Sentinel
transport:
client-ip: localhost
dashboard: localhost:8080
datasource:
# 降級規(guī)則
degrade:
nacos:
server-addr: {spring.application.name}-degrade-rules
groupId: SENTINEL_GROUP
data-type: json
rule-type: degrade
Feign開啟對Sentinel支持
feign:
sentinel:
enabled: true
復制代碼</pre>
4. 熔斷降級規(guī)則
在Nacos控制臺添加youlai-auth的降級規(guī)則
<pre class="prettyprint hljs xquery" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; overflow-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">[
{
"resource": "GET:http://youlai-admin/api.admin/v1/users/username/{username}",
"grade": 2,
"count": 1,
"timeWindow": 5
}
]
復制代碼</pre>
注意資源名稱的生成規(guī)則,上面配置的意思是如果單位時間內出現了1次異常數锨阿,那沒接下來5秒的時間窗口范圍內的請求宵睦,因為熔斷器打開,請求直接走降級邏輯墅诡。
5. 熔斷降級測試
首先要模擬系統(tǒng)服務的根據用戶名獲取用戶信息的接口異常壳嚎,具體如下圖:
配置JMeter線程組,單位時間1s內執(zhí)行10個請求末早,具體配置在普通流控有說明烟馅,這里不做贅述。
結果在youlai-auth確實執(zhí)行了10次請求然磷,因為目標服務的異常走了降級的邏輯
但是真正進入youlai-admin的根據用戶名獲取用戶信息的接口方法卻只有1次焙糟,后續(xù)的9次請求直接走feign客戶端的降級邏輯
上面的測試結果驗證了Feign整合Sentinel之后實現了熔斷和降級,至此Feign不再孤軍奮戰(zhàn)样屠。
七. 結語
本文就Sentinel的流控穿撮、熔斷降級從實戰(zhàn)的角度去逐一驗證。網關流控痪欲、普通流控能夠在有限的資源能力保障系統(tǒng)的穩(wěn)定運行悦穿,熔斷降級能夠在系統(tǒng)故障時提供兜底的處理邏輯保證系統(tǒng)的健壯性,支持降級的Feign整合Sentinel之后get到熔斷的技能业踢,至此熔斷降級雙劍合璧栗柒。
以前覺得微服務的限流、熔斷降級是可有可無的存在知举,所以在開源項目中一直遲遲沒有做相關的整合瞬沦,當真正理解這其中的利害關系之后,微服務離不開這些雇锡。
當然本文提到的Sentinel功能的冰山一角逛钻,像限流延伸的還有熱點key、IP限流锰提、參數限流等等曙痘,具體選擇使用根據場景,功能豐富立肘,總會有你需要的边坤。而且容易上手,是一個很不錯的框架谅年,內部的實現原理和還有算法很有必要去了解深入下茧痒。
如果有問題,歡迎加我微信(微信號:haoxianrui)
八. 附錄
本文涉及的源碼地址:
平臺 | 地址 |
---|---|
github | github.com/hxrui/youla… |
gitee | gitee.com/youlaitech/… |
文中的Sentinel規(guī)則配置已放置在項目document/nacos/SENTINEL_GROUP.zip融蹂,導入到Nacos控制臺即可
當然你也可以本地啟動Sentinel控制臺旺订,已經把官方的jar包放置在項目youlai-middleware/setinel/sentinel-dashboard-1.8.1.jar
<pre class="prettyprint hljs nginx" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; overflow-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">cd youlai-middleware/setinel
java -jar sentinel-dashboard-1.8.1.jar
復制代碼</pre>
本地訪問 http://localhost:8080即可進入Sentinel控制臺
歡迎大家加入開源有來項目交流群弄企,一起參與開源項目的開發(fā)。