簡介
上一篇博客中,針對 @SentinelResources 註解,做了個簡單的測試Demo,這一篇文章重點說明總結 @SentinelResources 的詳細使用和配置。
《Sentinel實現熔斷、限流、降級》
與HystrixCommand相比
@HystrixCommand 和 @SentinelResources 註解的功效總體而言是類似的。
springcloud 第一代不在迭代更新,阿里團隊在springcloud第一代的基礎上,做了一層封裝,原則上還是使用大局化配置。
簡單案例
之前的配置主要根據 URL
的形式進行流控
、限流
的配置和使用,本次依據 @SentinelResources 註解實現資源名稱
方式進行配置操作。
新建一個處理類。
import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.fastjson.JSONObject;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class ResourcesController {
@RequestMapping("/resources1")
@SentinelResource(value = "resources1",blockHandler = "handler")
public JSONObject resources1(){
JSONObject json = new JSONObject();
json.put("code",200);
json.put("msg","請求成功!");
return json;
}
public JSONObject handler(BlockException e){
JSONObject json = new JSONObject();
json.put("code",300);
json.put("msg","請求降級!");
return json;
}
}
啓動項目,當不配置 流控規則
時,快速請求訪問:
配置流控規則
:
請求測試:
異常回執配置
在Hystrix 中,出現異常後,會進入降級處理流程,但在 Sentinel 中出現異常,並不會進入降級處理操作。
異常測試
增加新的測試代碼邏輯:
// ================= 異常操作
@RequestMapping("/resources2")
@SentinelResource(value = "resources2",blockHandler = "handler2")
public JSONObject resources2(){
int a = 10/0;
JSONObject json = new JSONObject();
json.put("code",200);
json.put("msg","請求成功!");
return json;
}
public JSONObject handler2(BlockException e){
JSONObject json = new JSONObject();
json.put("code",300);
json.put("msg","請求降級!");
return json;
}
異常降級處理操作流程
採取@SentinelResources 註解中的
fallback
屬性配置異常降級流程。
// ================= 異常操作
@RequestMapping("/resources2")
@SentinelResource(value = "resources2",
blockHandler = "handler2",
fallback = "fallback2")
public JSONObject resources2(){
int a = 10/0;
JSONObject json = new JSONObject();
json.put("code",200);
json.put("msg","請求成功!");
return json;
}
public JSONObject fallback2(){
JSONObject json = new JSONObject();
json.put("code",300);
json.put("msg","fallback2 請求降級!");
return json;
}
public JSONObject handler2(BlockException e){
JSONObject json = new JSONObject();
json.put("code",300);
json.put("msg","請求降級!");
return json;
}
深層次的思考
@SentinelResources 註解中,每次進行配置流控降級處理操作時,都需要指定一個或多個
blockHandler
;或者出現異常降級時,一個處理方法指定一個fallback
。
能否有一種全局化的配置,只需要進行調用即可呢?
答案是有的,可以採取專門定義一個 blockHandler
類和fallback
類的方式。
定義兩個類,分別爲 blockHandler
類和fallback
類。
其中,blockHandler
類的處理方法有
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.fastjson.JSONObject;
public class HandlerGlobal {
public static JSONObject handler1(String msg,BlockException e){
JSONObject json = new JSONObject();
json.put("code",300);
json.put("msg","請求降級!----1");
return json;
}
public static JSONObject handler2(String msg,BlockException e){
JSONObject json = new JSONObject();
json.put("code",300);
json.put("msg","請求降級!----2");
return json;
}
}
fallback
類的處理方法有:
import com.alibaba.fastjson.JSONObject;
public class Fallback {
public static JSONObject fallback1(String msg){
JSONObject json = new JSONObject();
json.put("code",300);
json.put("msg","fallback1 請求降級!");
return json;
}
public static JSONObject fallback2(String msg){
JSONObject json = new JSONObject();
json.put("code",300);
json.put("msg","fallback2 請求降級!");
return json;
}
}
處理類上的引用案例:
//============全局化調用
@RequestMapping("/resources3")
@SentinelResource(value = "resources3",
blockHandlerClass = HandlerGlobal.class ,
blockHandler = "handler2",
fallbackClass = Fallback.class,
fallback = "fallback1")
public JSONObject resources3(String msg){
if("1".equalsIgnoreCase(msg)){
int a = 10/0;
}
JSONObject json = new JSONObject();
json.put("code",200);
json.put("msg","請求成功!");
return json;
}
重啓項目,並配置流控規則
請求測試:
增加異常邏輯,請求測試:
[注意:] 幾個需要注意的地方
1、Sentinel 的
blockHandler
處理方法中,必須攜帶參數BlockException e
,否則無法指向。
2、全局化的blockHandler
處理方法,必須爲static
。
3、全局化的fallback
處理方法,必須爲static
。
4、blockHandler
和fallback
兩個方法中的攜帶參數
必須和請求類
的保持一致!
@SentinelResources中的其他參數
- value
資源名稱,必需項(不能爲空) - entryType
entry 類型,可選項(默認爲EntryType.OUT
) - blockHandler / blockHandlerClass
blockHandler 對應處理 BlockException 的函數名稱,可選項。
blockHandler 函數訪問範圍需要是public
,返回類型需要與原方法相匹配
,參數類型需要和原方法相匹配
並且最後加一個額外的參數,類型爲 BlockException
。
blockHandler 函數默認需要和原方法在同一個類中。
若希望使用其他類的函數,則可以指定 blockHandlerClass 爲對應的類的 Class 對象,注意對應的函數必需爲static
函數,否則無法解析。 - fallback / fallbackClass
fallback 函數名稱,可選項,用於在拋出異常的時候提供 fallback 處理邏輯。
fallback 函數可以針對所有類型的異常(除了 exceptionsToIgnore 裏面排除掉的異常類型)進行處理。
- fallback 函數簽名和位置要求:
返回值類型
必須與原函數返回值類型一致;方法參數
列表需要和原函數一致,或者可以額外多一個 Throwable 類型
的參數用於接收對應的異常。- fallback 函數默認需要和原方法在同一個類中。若希望使用其他類的函數,則可以指定 fallbackClass 爲對應的類的 Class 對象,注意對應的函數必需爲
static
函數,否則無法解析。
- defaultFallback
默認的 fallback 函數名稱,可選項,通常用於通用的 fallback 邏輯(即可以用於很多服務或方法)。
默認 fallback 函數可以針對所有類型的異常(除了 exceptionsToIgnore 裏面排除掉的異常類型)進行處理。
若同時配置了 fallback 和 defaultFallback,則只有 fallback 會生效
。
- defaultFallback 函數簽名要求:
返回值類型
必須與原函數返回值類型一致;方法參數
列表需要爲空,或者可以額外多一個 Throwable 類型的參數用於接收對應的異常。- defaultFallback 函數默認需要和原方法在同一個類中。若希望使用其他類的函數,則可以指定 fallbackClass 爲對應的類的 Class 對象,注意對應的函數必需爲
static
函數,否則無法解析。
- exceptionsToIgnore
用於指定哪些異常被排除掉,不會計入異常統計中,也不會進入 fallback 邏輯中,而是會原樣拋出。