Sentinel以流量爲切入點,以流量控制、熔斷降級、系統負載保護等多個維度保護服務的穩定性。包括核心的獨立類庫、監控臺、豐富的使用場景。
使用場景:秒殺(即突發流量控制在系統容量可以承受的範圍)、消息削峯填谷、實時熔斷下游不可用應用等。
實時監控,開源生態(開箱即用且與其他開源框架/庫的整合模塊),完善的SPI擴展點(實現擴展,快速定製邏輯,如定製規則邏輯、適配數據流等)
- 資源管理:應用服務器腳本、靜態頁面、API接口、文件圖片等
- 規則配置:允許資源(一般API接口)通過的請求次數,IP黑白名單,應用服務等
- 測試效果:QPS(單臺服務器每秒能處理查詢次數);TPS(每秒處理的事務數,傾向整個過程)
Sentinel分爲兩部分:
- 核心庫(JAVA客戶端)不依賴任何框架/庫
- 控制檯(Dashboard)基於Spring boot開發,打包直接運行(不需要額外tomcat等應用容器,該模塊目前基於Spring boot運行)
# 下面開始整合框架:Nacos註冊中心、Feign服務、Sentinel哨兵、Sentinel控制檯
一、Sentinel入門介紹
# 搭建2.2.5.RELEASE(與上一文搭建Nacos選了1.4.1版本)sentinel按下圖選擇的1.8.0版本,下載地址:https://github.com/alibaba/Sentinel/releases
下載到本地後,執行 javaw -jar sentinel-dashboard-1.8.0.jar 默認端口8080( 如果8080端口被佔用,可以自定義啓動端口java -jar xxx.jar --server.port=8888
)linux 後臺啓動可以執行 nohup java -jar xxx.jar >log.log &
指定日誌文件位置和後臺掛起啓動
啓動成功後訪問地址:http://ip:port 默認用戶名密碼:sentinel
二、搭建Sentinel項目
現在創建一個cloudalbb-sentinel-ribbon1020項目,項目裏基本依賴和配置如下:
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
server:
port: 1020
spring:
application:
name: sentinel-ribbon1020
cloud:
nacos:
discovery:
server-addr: localhost:8848 #nacos集羣,使用的是域名
sentinel:
transport:
dashboard: localhost:8080 #配置sentinel dashboard地址
port: 8719 #默認8719端口
service-url:
nacos-service: http://nacos-provider
1、只配置單個blockHandler限流降速處理方法配置
@GetMapping("/request/pay/{id}")
@SentinelResource(value = "fallback",blockHandler = "blockHandler") //blockHandler只負責sentinel控制檯配置違規
public CommonResult<Order> reqToPay(@PathVariable("id") Long id){
CommonResult<Order> result = restTemplate.getForObject(serverURL+"/order/"+id, CommonResult.class);
return result;
}
public CommonResult<Order> blockHandler(@PathVariable("id") Long id, BlockException exception){
// 不同的異常返回不同的提示語
String reason = "";
if (exception instanceof FlowException) {
reason = "接口限流了";
} else if (exception instanceof DegradeException) {
reason = "服務降級了";
} else if (exception instanceof ParamFlowException) {
reason = "熱點參數限流了";
} else if (exception instanceof SystemBlockException) {
reason = "觸發系統保護規則";
} else if (exception instanceof AuthorityException) {
reason = "授權規則不通過";
}
Order order = new Order(id, "默認值");
return new CommonResult<Order>(521, "收到請求id:"+id+",sentinel-blockHandler"+reason+":"+exception.getMessage(), order);
}
將nacos-provider和sentinel-ribbon2010兩個項目啓動,然後配置流量降速,最後訪問一下
2、加個blockHandlerClass限流降級處理類配置
爲了提高代碼的可讀性及解耦,將自定義限流降速方法寫入一個限流降速級類中,需要時再調用(所有的方法均爲static靜態方法,參數必須帶上BlockException,否則找不到響應方法), blockHandler 函數訪問範圍需要是 public,返回類型需要與原方法相匹配,參數類型需要和原方法相匹配並且最後加一個額外的參數,類型爲 BlockException ,blockHandler 函數默認需要和原方法在同一個類中。若希望使用其他類的函數,則可以指定 blockHandlerClass 爲對應的類的 Class 對象,注意對應的函數必需爲 static 函數,否則無法解析
@GetMapping("/request/pay/{id}")
@SentinelResource(value = "fallback",blockHandler = "blockHandler",blockHandlerClass = BlockHandler.class) //blockHandler只負責sentinel控制檯配置違規
public CommonResult<Order> reqToPay(@PathVariable("id") Long id){
CommonResult<Order> result = restTemplate.getForObject(serverURL+"/order/"+id, CommonResult.class);
return result;
}
3、只配置單個fallback熔斷降級方法配置
defaultFallback,默認的 fallback 函數名稱,可選項,通常用於通用的 fallback 邏輯(即可以用於很多服務或方法)。默認 fallback 函數可以針對所有類型的異常(除了 exceptionsToIgnore 裏面排除掉的異常類型)進行處理。若同時配置了 fallback 和 defaultFallback,則只有 fallback 會生效。
@GetMapping("/request/pay/{id}")
@SentinelResource(value = "fallback",fallback = "handlerFallback") //fallback只負責業務異常
public CommonResult<Order> reqToPay(@PathVariable("id") Long id){
CommonResult<Order> result = restTemplate.getForObject(serverURL+"/order/"+id, CommonResult.class);
int test = 10/0;
return result;
}
public CommonResult<Order> handlerFallback(@PathVariable("id") Long id, Throwable throwable){
Order order = new Order(id, "默認值");
return new CommonResult<Order>(520, "收到請求id:"+id+",業務異常:"+throwable.getMessage(), order);
}
4、加個fallbackClass熔斷降級處理類配置
@GetMapping("/request/pay/{id}")
@SentinelResource(value = "fallback",fallback = "handlerFallback",fallbackClass=CustomerFallback.class) //fallback只負責業務異常
public CommonResult<Order> reqToPay(@PathVariable("id") Long id){
CommonResult<Order> result = restTemplate.getForObject(serverURL+"/order/"+id, CommonResult.class);
int test = 10/0;
return result;
}
public CommonResult<Order> handlerFallback(@PathVariable("id") Long id, Throwable throwable){
Order order = new Order(id, "默認值");
return new CommonResult<Order>(520, "收到請求id:"+id+",業務異常:"+throwable.getMessage(), order);
}
5、blockHandler和fallback可以同時配置,不再贅述
exceptionsToIgnore,用於指定哪些異常被排除掉,不會計入異常統計中,也不會進入 fallback 邏輯中,而是會原樣拋出。
@GetMapping("/request/pay/{id}")
// blockHandler/blockHandlerClass流速降級,fallback/fallbackClass熔斷降速
// @SentinelResource(value="fallback") //無配置
// @SentinelResource(value = "fallback",fallback = "handlerFallback") //fallback只負責業務異常
// @SentinelResource(value = "fallback",fallback = "customerFallback",fallbackClass = CustomerFallback.class) //獨立的業務異常處理
// @SentinelResource(value = "fallback",defaultFallback = "defaultFallback") //通常用於通用的 fallback 邏輯(即可以用於很多服務或方法)
// @SentinelResource(value = "fallback",defaultFallback = "customerDefaultFallback",fallbackClass = DefaultFallBack.class) //通常用於通用的 fallback 邏輯(即可以用於很多服務或方法)
// @SentinelResource(value = "fallback",blockHandler = "blockHandler") //blockHandler只負責sentinel控制檯配置違規
@SentinelResource(value = "fallback",fallback = "handlerFallback",blockHandler = "blockHandler", exceptionsToIgnore = {IllegalArgumentException.class} ) //異常被排除掉,不會進入fallback邏輯中,而是會原樣拋出。
public CommonResult<Order> reqToPay(@PathVariable("id") Long id){
CommonResult<Order> result = restTemplate.getForObject(serverURL+"/order/"+id, CommonResult.class);
int test = 10/0;
return result;
}
三、集成Spring Cloud OpenFeign
Service層進行註解配置:
@FeignClient(value = "nacos-provider",fallback = PaymentFallbackServiceImpl.class)
@Component
public interface PaymentService {
@GetMapping("/order/{id}")
public CommonResult<Order> getOrderById(@PathVariable("id")Long id);
}
@Component
public class PaymentFallbackServiceImpl implements PaymentService {
@Override
public CommonResult<Order> getOrderById(Long id) {
return new CommonResult<>(444,"服務降級返回,OrderFallbackService",new Order(id,"errorSerial"));
}
}
四、集成RestTemplate
@Bean
@LoadBalanced
@SentinelRestTemplate(blockHandler = "handleException", blockHandlerClass = ExceptionUtil.class)
public RestTemplate restTemplate() {
return new RestTemplate();
}
@SentinelRestTemplate 註解的屬性支持限流(blockHandler, blockHandlerClass)和降級(fallback, fallbackClass)的處理。
其中 blockHandler 或 fallback 屬性對應的方法必須是對應 blockHandlerClass 或 fallbackClass 屬性中的靜態方法。