Springcloud-alibaba-sentinel
sentinel是什麼:
先熔斷再降級
隨着微服務的流行,服務和服務之間的穩定性變得越來越重要。Sentinel 以流量爲切入點,從流量控制、熔斷降級、系統負載保護等多個維度保護服務的穩定性。
Sentinel 具有以下特徵:
豐富的應用場景:Sentinel 承接了阿里巴巴近 10 年的雙十一大促流量的核心場景,例如秒殺(即突發流量控制在系統容量可以承受的範圍)、消息削峯填谷、集羣流量控制、實時熔斷下游不可用應用等。
**完備的實時監控:**Sentinel 同時提供實時的監控功能。您可以在控制檯中看到接入應用的單臺機器秒級數據,甚至 500 臺以下規模的集羣的彙總運行情況。
**廣泛的開源生態:**Sentinel 提供開箱即用的與其它開源框架/庫的整合模塊,例如與 Spring Cloud、Dubbo、gRPC 的整合。您只需要引入相應的依賴並進行簡單的配置即可快速地接入 Sentinel。
**完善的 SPI 擴展點:**Sentinel 提供簡單易用、完善的 SPI 擴展接口。您可以通過實現擴展接口來快速地定製邏輯。例如定製規則管理、適配動態數據源等。
Sentinel主要特徵:
### 使用去官網下載:
啓動Sentinel的控制檯:
但是要注意,8080端口要保證不被佔用
我也不知道爲什麼要跟tomcat的端口有衝突
訪問:賬號密碼都是sentinel
進來了就這樣:
新建一個服務8401:
添加pom:
<dependencies>
<dependency>
<groupId>com.zx.springcloud</groupId>
<artifactId>cloud-api-commons</artifactId>
<version>${project.version}</version>
</dependency>
<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>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>4.6.3</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
添加yml:
server:
port: 8401
spring:
application:
name: cloudalibaba-sentinel-service
cloud:
nacos:
discovery:
server-addr: localhost:8848
sentinel:
transport:
dashboard: localhost:8080
port: 8719 #默認8719,假如被佔用了會自動從8719開始依次+1掃描。直至找到未被佔用的端口
management:
endpoints:
web:
exposure:
include: '*'
創建一個啓動類:
在創建一個controller層用於測試:
啓動查看:
什麼也沒有。查看也沒找到。看了官網明白了,說的是sentinel使用的是來加載模式。必須使用的時候纔有,那就使用一次測試一下
再刷新Sentinel:出來了!!!
實時監控:
簇點鏈路:
流控規則:
●資源名:唯-名稱,默認請求路徑
●針對來源: Sentine可以針對調用者進行限流,填寫微服務名,默認default (不區分來源)
●閾值類型/單機閾值:
。QPS (每秒鐘的請求數量) :當調用該ap的QPS達到閾值的時候,進行限流
。線程數:當調用該api的線程數達到閾值的時候,進行限流
●是否集羣:不需要集羣
●流控模式:
。直接: api達到限流條件時,直接限流
。關聯:當關聯的資源達到閾值時,就限流自己
。鏈路:只記錄指定鏈路上的流量(指定資源從入口資源進來的流量,如果達到閾值,就進行限流) [api級
別的針對來源]
●流控效果:
。快速失敗:直接失敗,拋異常
。Warm Up:根據codeFactor (冷加載因子,默認3)的值,從閾值/codeFactor, 經過預熱時長,才達到設置的QPS閾值
。排隊等待:勻速排隊,讓請求以勻速的速度通過,閾值類型必須設置爲QPS,則無效
配置一下流控:
規則是訪問testA的時候是一秒一次,超過就失敗
狂點:失敗了
改造一下testA
再修改一下流控:
QPS改成線程數:(在門外)
狂點:
線程數就是相當於在同一時間達到一定的值時會進行阻斷。(關門打狗)
關聯:修改下配置,意思就是B不行了,然後導致A掛了,這樣的好處就是在分佈式中各種服務時相關的,如果把B看成時支付接口,那A就是下單接口,意思就是B如果支付接口的壓力大了,那麼就告訴A先別下單這麼猛了
用postman測試一下:
20個線程0.3秒一次
啓動後訪問A:
能看到A失敗了,當B訪問完成後再次訪問A:
能看到A又能訪問了
鏈路:看文檔的意思就是當B調用超過2次時,就對A限流
訪問剛剛的postman訪問B,能看到A被限流了
修改了一下規則就能訪問到A了
Warm up:詳細看官網:https://github.com/alibaba/Sentinel/wiki/%E9%99%90%E6%B5%81—%E5%86%B7%E5%90%AF%E5%8A%A8:
反正我看着有點懵逼.我的理解就是當一個程序一直時正常運行的時候沒問題,當瞬間的併發量太高了有可能會崩,這個時候就有了預熱,就跟溫水煮青蛙一樣。慢慢的加溫:
這個配置的意思我理解的就是單機閾值10,然後有個默認值是3,預熱值是5,系統初始化的閥值爲10/ 3約等於3,即閥值剛開始爲3;然後過了5秒後閥值才慢慢升高恢復到10,那就是給5秒的時間閾值從3過度到10
測試:
狂點,超過每秒3次報錯,經過五秒按一樣的手速:
能看到按一樣的手速也能成功了
這個的運用感覺能用到秒殺系統上,因爲場景很符合的,都是到點瞬間訪問
排隊等待:不管怎麼併發都勻速通過,超過就超時重試,閾值必須是QPS配置:
一秒10個,理論啓動後應該是每秒過1個線程,啓動訪問:
可以看到時間,確實是一秒一個
降級規則:
RT(秒級):
平均響應時間( DEGRADE GRADE_ RT): 當1s內持續進入5個請求,對應時刻的平均響應時間(秒級)均超過閾值( count,以ms爲單位),那麼在接下的時間窗口( DegradeRule中的timeNindow,以s爲單位)之內,對這個方法的調用都會自動地熔斷(拋出DegradeException)。 注意Sentinel默認統計的RT上限是4900 ms,超出此閾值的都會算作4900 ms,若需要變更此上限可以通過啓動配置項-Dcsp. sentinel. statistic. max.rt-=xx來配置。
新增一個testD方法:
訪問:
用jemter設置一個1秒請求10個,訪問:開始不行,過了一秒纔行
異常比例(秒級):
異常比例( DEGRADE GRADE_ EXCEPTION _RATIO):當資源的每秒請求量>= 5,並且每秒異常總數佔通過量的比值超過閾值( DegradeRule中的count )之後,資源進入降級狀態,即在接下的時count )之後,資源進入降級狀態,即在接下的時回。異常比率的閾值範圍是[9.0, 1.0], 代表0%- 100%。
異常數(分鐘級):
異常數(分鐘統計)超過閾值時r觸發降級;時間窗口結束後,關閉降級
說白了就是配置過後訪問達到錯誤次數後就會啓動熔斷保護是系統避免更多的損失
熱點Key限流
根據官方的意思就是可以把網站的熱點訪問詞用來作爲限流的條件,
@SentinelResource和Hystrix的那個註解是差不多的意思,都是當出錯了後可以使用其他的方法用來兜底
編寫代碼:
配置熱點參數:每秒超過一次就會出現熔斷並使用容錯的方法
訪問:
提高點擊速度:
就會觸發熱點規則
如果沒有再java配置裏說明容錯的方法,一旦超過配置的值就會出現Error Page的頁面,對用戶不友好
參數例外項:上面普通的參數當P的值等於1時,會被限流,但是設置了參數例外項後,當它的值等於某一個特定的值時,它的閾值就可以其他的期望值或者不被限流
支持的類型:
設置當第0個參數的值爲5時,閾值能達到200:
測試:p1等於a時:超過一秒一個會被限流:
當p1等於5時:狂點也不會報錯,因爲我再怎麼點也不會超過一秒200次
運行時異常:
所以,@SentinelResource只是管理sentinel配置時出錯的地方,java代碼出錯不會管
系統規則:
●Load 自適應(僅對Linux/Unix-like 機器生效) :系統的load1作爲啓發指標,進行自適應系統保護。當系統load1超過設定的啓發值,且系統當前的併發線程數超過估算的系統容量時纔會觸發系統保護(BBR 階段)。系統容量由系統的maxQps * nminRt估算得出。設定參考值一般是CPU cores * 2.5。
●CPU usage (1.5.0+版本) :當系統CPU使用率超過閾值即觸發系統保護(取值範圍0.0-1.0),比較靈敏。(cpu的使用率)
●平均RT: 當單臺機器上所有入口流量的平均RT達到閾值即觸發系統保護,單位是毫秒。
●併發線程數:當單臺機器上所有入口流量的併發線程數達到閾值即觸發系統保護。
●入口QPS:當單臺機器上所有入口流量的QPS達到閾值即觸發系統保護。
配置:
訪問:疫苗一次沒問題,但是狂點就會限流了
每個方法都會這樣
@SentinelResource
新增測試類:
通過資源名稱
@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 服務不可用");
}
訪問成功:
配置流控:
訪問:
出現異常了時一個alibaba的流限流的異常類
關閉sentinel:
流控規則沒了o.o,說明時臨時的
通過url地址
訪問:
配置:
再次訪問:
自定義一個類,處理全局的容錯方法
訪問:
配置:
訪問,超過閾值就會使用自定義的容錯方法:
參數:
fallBack:java代碼運行時異常所返回的頁面或者結果
handler:sentinel所使用的返回結果或兜底的方法
@RestController
@Slf4j
public class CircleBreakerController {
public static final String SERVICE_URL = "http://nacos-payment-provider";
@Resource
private RestTemplate restTemplate;
@RequestMapping("/consumer/fallback/{id}")
//@SentinelResource(value = "fallback") //沒有配置
//@SentinelResource(value = "fallback",fallback = "handlerFallback") //fallback只負責業務異常
//@SentinelResource(value = "fallback",blockHandler = "blockHandler") //blockHandler只負責sentinel控制檯配置違規
@SentinelResource(value = "fallback",fallback = "handlerFallback",blockHandler = "blockHandler",
exceptionsToIgnore = {IllegalArgumentException.class})
public CommonResult<Payment> fallback(@PathVariable Long id) {
CommonResult<Payment> result = restTemplate.getForObject(SERVICE_URL + "/paymentSQL/"+id, CommonResult.class,id);
if (id == 4) {
throw new IllegalArgumentException ("IllegalArgumentException,非法參數異常....");
}else if (result.getData() == null) {
throw new NullPointerException ("NullPointerException,該ID沒有對應記錄,空指針異常");
}
return result;
}
//fallback
public CommonResult handlerFallback(@PathVariable Long id,Throwable e) {
Payment payment = new Payment(id,"null");
return new CommonResult<>(444,"兜底異常handlerFallback,exception內容 "+e.getMessage(),payment);
}
//blockHandler
public CommonResult blockHandler(@PathVariable Long id,BlockException blockException) {
Payment payment = new Payment(id,"null");
return new CommonResult<>(445,"blockHandler-sentinel限流,無此流水: blockException "+blockException.getMessage(),payment);
}
}
大部分情況下fallBack和BlockHandler同時配置, BlockHandler會優先使用
sentinel持久化:
添加pom:
修改yml:
配置nacos:
再次啓動8401服務,能發現已經有規則
我們訪問一下url:超過閾值就會限流並返回sentinel的規則
然後關閉8401sentinel服務:發現規則沒有了,
再次啓動8401sentinel:
訪問retaLimit.byUrl再看sentinel:
能發現又出現了流控規則,所以持久化成功了
感覺唯一的一點不好就是需要寫配置文件到nacos裏,雖然能持久化了,但是沒有在sentinel裏直接配置方便直觀,還需要背許多的配置規則