使用Sentinel API
Sentinel主要有三個核心Api:
SphU:定義資源,讓資源收到監控,保護資源
SphU 包含了 try-catch 風格的 API。用這種方式,當資源發生了限流之后會拋出 BlockException。這個時候可以捕捉異常,進行限流之后的邏輯處理。
String resourceName = "test_sentinel_api";
Entry test_sentinel_api = null;
// 定義一個Sentinel保護的資源
try {
test_sentinel_api = SphU.entry(resourceName);
...
}
// 若被保護的資源被限流或者降級
catch (BlockException e) {
e.printStackTrace();
return "限流,或者降級了";
}
finally {
if (test_sentinel_api != null) {
test_sentinel_api.exit();
}
}
PS:SphU.entry(xxx) 需要與 entry.exit() 方法成對出現,匹配調用,否則會導致調用鏈記錄異常,拋出 ErrorEntryFreeException 異常。
若 entry 的時候傳入了熱點參數,那么 exit 的時候也一定要帶上對應的參數(exit(count, args)),否則可能會有統計錯誤。這個時候不能使用 try-with-resources 的方式。
Tracer:異常統計
// 針對來源
String resourceName = "test_sentinel_api";
Entry test_sentinel_api = null;
// 定義一個Sentinel保護的資源
try {
test_sentinel_api = SphU.entry(resourceName);
if (StringUtils.isBlank(a)) {
throw new IllegalArgumentException("a不能為空");
}
return a;
}
// 若被保護的資源被限流或者降級
catch (BlockException e) {
e.printStackTrace();
return "限流,或者降級了";
}
catch (IllegalArgumentException e2) {
// 統計IllegalArgumentException
Tracer.trace(e2);
return "參數非法";
}
finally {
if (test_sentinel_api != null) {
test_sentinel_api.exit();
}
}
通過 Tracer.trace(ex) 來統計異常信息時,由於 try-with-resources 語法中 catch 調用順序的問題,會導致無法正確統計異常數,因此統計異常信息時也不能在 try-with-resources 的 catch 塊中調用 Tracer.trace(ex)。
ContextUtil:實現調用來源,實現調用
// 針對來源
String resourceName = "test_sentinel_api";
ContextUtil.enter(resourceName, "study01");
通過SentinelResource注解的方式
Sentinel 支持通過 @SentinelResource 注解定義資源並配置 blockHandler 和 fallback 函數來進行限流之后的處理。
@GetMapping("test_sentinel_resource")
@SentinelResource(
value = "test_sentinel_resource",
blockHandler = "block",
fallback = "fallback"
)
public String testSentinelResource(@RequestParam(required = false) String a) {
if (StringUtils.isBlank(a)) {
throw new IllegalArgumentException("a不能為空");
}
return a;
}
/**
* 處理限流或者降級
*/
public String block(String a, BlockException e) {
log.warn("限流,或者降級了", e);
return "限流,或者降級了 block";
}
public String fallback(String a, BlockException e) {
return "限流,或者降級了 fallback";
}
@SentinelResource同樣支持通過配置blockHandlerClass和fallbackClass配置類來進行限流后的處理
RestTemplate整合Sentinel
在初始化restTemplate的時候添加@SentinelRestTemplate注解就可以為RestTemplate整合Sentinel,代碼如下:
@Bean
@LoadBalanced
@SentinelRestTemplate
public RestTemplate restTemplate() {
return new RestTemplate();
}
可以通過配置resttemplate. sentinel.enabled來開啟或關閉整合,代碼如下:
resttemplate:
sentinel:
# 關閉、打開SentinelRestTemplate注解
enabled: true
Feign整合Sentinel
在配置文件中添加如下配置便可以為Feign整合Sentinel:
feign:
# feign整合sentinel
sentinel:
enabled: true
如果服務被限流或降級時,如果想要定制定制自己的處理邏輯,可以使用@FeignClient注解的fallback屬性;如果定制處理邏輯的同時,還想拿到異常的具體細節,可以使用fallbackFactory屬性,示例代碼如下:
@FeignClient(
name = "study02",
// 拿不到異常
fallback = CommentFeignClientFallback.class,
// 拿到異常
fallbackFactory = CommentFeignClientFallbackFactory.class
)
public interface CommentFeignClient {
@GetMapping("/find")
DemoComment find();
}
@Component
public class CommentFeignClientFallback implements CommentFeignClient {
/**
* 一旦被限流,就會進入這個方法
* @return
*/
@Override
public DemoComment find() {
DemoComment demoComment = new DemoComment();
return demoComment;
}
}
@Component
@Slf4j
public class CommentFeignClientFallbackFactory implements FallbackFactory<CommentFeignClient> {
@Override
public CommentFeignClient create(Throwable throwable) {
return new CommentFeignClient() {
@Override
public DemoComment find() {
DemoComment demoComment = new DemoComment();
return demoComment;
}
};
}
}