一、 sentinel 主要特性
二、sentinel 的下載及安裝
https://github.com/alibaba/Sentinel/releases
下載 sentinel-dashboard-1.7.0.jar 前提是 java8環境OK,8080端口未被佔用。
啓動 sentinel , java -jar sentinel-dashboard-1.7.0.jar
訪問 localhost:8080 ,賬號密碼均爲 sentinel。
三 、創建項目
(1)向 pom文件中 添加相關依賴 :
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!-- 後續做持久化用到 -->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
</dependency>
<!-- sentinel -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
修改 application.yml 配置文件
server:
port: 8401
spring:
application:
name: cloudalibaba-sentinel-service
cloud:
nacos:
discovery: #Nacos註冊中心地址
server-addr: localhost:8848
sentinel:
transport: #dashboard地址
dashboard: localhost:8080
port: 8719 #默認端口,如果被佔用則從8719依次+1掃描
datasource:
dsl:
nacos:
server-addr: localhost:8848
dataId: cloudalibaba-sentinel-service
groupId: DEFAULT_GROUP
data_type: json
rule-type: flow
management:
endpoints:
web:
exposure:
include: "*"
編寫 controller
@RestController
@Slf4j
public class FlowLimitController {
@GetMapping("/testA")
public String testA(){
try {
TimeUnit.MILLISECONDS.sleep(800);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "---------testA";
}
@GetMapping("/testB")
public String testB(){
return "----------testB";
}
}
(2)啓動 nacos ,服務註冊到 nacos 中,然後啓動 sentinel 8080,最後啓動微服務,發現 sentinel 中空空如也,因爲 sentinel採用的是 懶加載,當訪問過了一次接口之後 纔會有監控數據展示到 控制檯上。
四、流控規則
直接 - 》 快速失敗 : 選擇 qps 時,當一秒內請求數達到閾值就會直接響應失敗,當選擇線程數時候,一秒內,超過一個線程訪問testA接口時,就會直接響應失敗。
關聯 -》 快速失敗
當請求 關聯 資源接口 B流量過大時,接口A直接快速響應失敗。
(3)Warm Up
如下例子: 單機閾值爲10,預熱時長5s, 一開始 qps 爲 10/ 3 = 3,慢慢的過了5s之後 qps 就會變爲10.
秒殺系統:在開啓的瞬間,會有很多流量上來,很有可能把系統打死, 預熱方式就是爲了保護系統,慢慢的把流量放進來,慢慢的把閾值增長到設置的閾值。
均勻排隊:
五、服務降級
六、熱點key限流
@GetMapping("/testHotKey")
@SentinelResource(value = "testHotKey",blockHandler = "deal_testHotKey")
public String testHotKey(@RequestParam(value = "p1",required = false) String p1,
@RequestParam(value = "p2", required = false) String p2) {
return "-------testHotKey";
}
public String deal_testHotKey(String p1, String p2,
BlockException exception){
return "----deal_testHotKey,o(╥﹏╥)o";
}
表示訪問testHotKey的資源,帶有第一個參數的情況下,並且閾值在1秒內達到了1次就會限流,自動調用 blockHandler 的值對應的方法並返回數據。相當於 將 返回的服務降級信息進行了自定義。
參數例外項: 當進行了如下配置的時候,代表p1 !=5 的情況下,每秒1次就會達到閾值,但是當p1 = 5的情況下,閾值每秒可以達到 200 ,注意熱點參數的類型必須是 基本類型或者String
@SentinelResource 處理的是Sentinel 控制檯配置的違規情況,由blockHandler 配置的方法進行兜底處理。
RuntimeException
int age = 10 /0 , java運行時爆出的java運行時異常,@SentinelResource 不會處理,
@SentinelResource 主管配置出錯,運行出錯該走異常走異常。
七、系統規則
針對整個系統的 第一道 防線
八、服務降級處理提取類
package springcloud.controller;
import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.springcloud.entities.CommonResult;
import com.springcloud.entities.Payment;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import springcloud.myhandler.CustomerBlockHandler;
@RestController
public class RateLimitController {
@GetMapping("/byResource")
@SentinelResource(value = "byResource",blockHandler = "handleException")
public CommonResult byResource(){
return new CommonResult(200, "按資源名稱限流測試ok", new Payment(2020L, "serial001"));
}
public CommonResult handleException(BlockException exception) {
return new CommonResult(444, exception.getClass().getCanonicalName() + "\t 服務不可用");
}
@GetMapping("/rateLimit/byUrl")
@SentinelResource(value = "byUrl",blockHandlerClass = CustomerBlockHandler.class,
blockHandler = "handlerException")
public CommonResult byUrl(){
return new CommonResult(200,"按url限流測試OK", new Payment(2020L, "serial001"));
}
//CustomerBlockHandler
@GetMapping("/rateLimit/CustomerBlockHandler")
@SentinelResource(value = "CustomerBlockHandler",blockHandlerClass = CustomerBlockHandler.class,
blockHandler = "handlerException2")
public CommonResult CustomerBlockHandler(){
return new CommonResult(200,"按客戶自定義限流測試OK", new Payment(2020L, "serial003"));
}
}
package springcloud.myhandler;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.springcloud.entities.CommonResult;
import com.springcloud.entities.Payment;
public class CustomerBlockHandler {
public static CommonResult handlerException(BlockException exception) {
return new CommonResult(4444, "按客戶自定義,global handlerException", new Payment(2020L, "serial0003"));
}
public static CommonResult handlerException2(BlockException exception) {
return new CommonResult(4444, "按客戶自定義2,global handlerException", new Payment(2020L, "serial0003"));
}
}
使業務和代碼 耦合度解耦,避免了代碼的膨脹。
九、服務熔斷 異常忽略 exceptionsToIgnore
十、熔斷框架比較
十一、sentinel 持久化規則
一旦我們重啓應用,sentinel 規則將消失,生產環境需要將配置規則進行持久化。
將限流配置規則持久化進nacos 保存,只要不刪除nacos中對 限流的配置規則,就不會消失。
主要需要用到 以下依賴:
修改 pom.xml
<!-- 後續做持久化用到 -->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
</dependency>
修改 application.yml配置文件
在 nacos 中添加 規則配置:
配置解析:
[{
"resource": "/rateLimit/byUrl",
"limitApp": "default",
"grade":1,
"count": 1,
"strategy":0,
"controlBehavior":0,
"clusterMode": false
}]
resource : 資源名稱
limitApp: 來源應用,
grade: 閾值類型,0表示線程數,1表示QPS
count: 單機閾值,
strategy: 流控模式,0表示直接,1表示關聯,2表示鏈路
controlBehavior: 流控效果,0表示快速失敗,1表示Warm Up ,2表示排隊等待
clusterMode: 是否集羣
服務停止之後,發現sentinel 中的 鏈路配置的限流又消失了,但是不用擔心,多次請求一下 在nacos 中配置了限流的 資源名稱,此時就會發現鏈路配置的限流數據又出現了。實現了限流配置的持久化。