
(1)理論基礎
http://sentinelguard.io/zh-cn/docs/introduction.html
隨著微服務的流行,服務和服務之間的穩(wěn)定性變得越來越重要。Sentinel 是面向分布式、多語言異構化服務架構的流量治理組件,主要以流量為切入點,從流量路由、流量控制、流量整形、熔斷降級、系統(tǒng)自適應過載保護、熱點流量防護等多個維度來幫助開發(fā)者保障微服務的穩(wěn)定性。
資源
資源是 Sentinel 的關鍵概念。它可以是 Java 應用程序中的任何內容,例如,由應用程序提供的服務,或由應用程序調用的其它應用提供的服務,甚至可以是一段代碼。在接下來的文檔中,我們都會用資源來描述代碼塊。
只要通過 Sentinel API 定義的代碼,就是資源,能夠被 Sentinel 保護起來。大部分情況下,可以使用方法簽名,URL,甚至服務名稱作為資源名來標示資源。
規(guī)則
圍繞資源的實時狀態(tài)設定的規(guī)則,可以包括流量控制規(guī)則、熔斷降級規(guī)則以及系統(tǒng)保護規(guī)則。所有規(guī)則可以動態(tài)實時調整。
流量控制
流量控制在網(wǎng)絡傳輸中是一個常用的概念,它用于調整網(wǎng)絡包的發(fā)送數(shù)據(jù)。然而,從系統(tǒng)穩(wěn)定性角度考慮,在處理請求的速度上,也有非常多的講究。任意時間到來的請求往往是隨機不可控的,而系統(tǒng)的處理能力是有限的。我們需要根據(jù)系統(tǒng)的處理能力對流量進行控制。Sentinel 作為一個調配器,可以根據(jù)需要把隨機的請求調整成合適的形狀
熔斷降級
什么是熔斷降級
除了流量控制以外,降低調用鏈路中的不穩(wěn)定資源也是 Sentinel 的使命之一。由于調用關系的復雜性,如果調用鏈路中的某個資源出現(xiàn)了不穩(wěn)定,最終會導致請求發(fā)生堆積。這個問題和 Hystrix 里面描述的問題是一樣的。
Sentinel 和 Hystrix 的原則是一致的: 當調用鏈路中某個資源出現(xiàn)不穩(wěn)定,例如,表現(xiàn)為 timeout,異常比例升高的時候,則對這個資源的調用進行限制,并讓請求快速失敗,避免影響到其它的資源,最終產(chǎn)生雪崩的效果。
(2)配置
(1)啟動服務
java -jar -Dserver.port=9100 sentinel-dashboard-1.8.5.jar
(2)pom依賴
? ? ? ? <!--SpringCloud ailibaba sentinel -->
? ? ? ? <dependency>
? ? ? ? ? ? <groupId>com.alibaba.cloud</groupId>
? ? ? ? ? ? <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
? ? ? ? ? ? <version>2021.1</version>
? ? ? ? </dependency>
(3)yml配置
spring:
? cloud:
? ? sentinel:
? ? ? eager: true #服務啟動直接建立心跳連接
? ? ? transport:
? ? ? ? port: 8719 # 假如被占用了會自動從8719開始依次+1掃描。直至找到未被占用的端口,默認8719
? ? ? ? dashboard: 127.0.0.1:9100 # 指定控制臺服務的地址
feign:
? client:
? ? config:
? ? ? # 默認的超時時間設置
? ? ? default:
? ? ? ? connectTimeout: 5000
? ? ? ? readTimeout: 5000
? ? ? # 在指定的 FeignClient 設置超時時間,覆蓋默認的設置
? ? ? nacos-provider:
? ? ? ? connectTimeout: 1000
? ? ? ? readTimeout: 1000
? ? ? ? loggerLevel: full
? # 激活 Sentinel
? sentinel:
? ? enabled: true
(4)解決循環(huán)依賴問題:
spring:
? main:
? ? allow-circular-references: true
(3)項目應用
@RestController
public class A {
? ? // 流控測試:QPS
? ? // 流控模式:直接、關聯(lián)、鏈路
? ? // 流控效果:快速失敗、Warm up、排隊等待
? ? @RequestMapping("m1")
? ? public String m1(){
? ? ? ? System.out.println("m1...................................");
? ? ? ? return "m1";
? ? }
? ? // 流控測試:并發(fā)線程數(shù)
? ? @RequestMapping("m2")
? ? public String m2(){
? ? ? ? System.out.println("m2...................................");
? ? ? ? return "m2";
? ? }
}
/*
特別注意:
feign:
? sentinel:
? ? enabled: true
*/
@RestController
public class B {
? ? // 熔斷規(guī)則慢調用比例測試
? ? // RT500、比例閾值1、熔斷時長5、最小請求數(shù)1、統(tǒng)計時長1000
? ? @RequestMapping("m3")
? ? @SentinelResource(value = "m3", blockHandler = "test3")
? ? public String m3() throws InterruptedException {
? ? ? ? Thread.sleep(1000);
? ? ? ? System.out.println("m3...................................");
? ? ? ? return "m3";
? ? }
? ? String test3(BlockException e){
? ? ? ? System.out.println(e);
? ? ? ? return "慢調用熔斷降級";
? ? }
? ? // 熔斷規(guī)則異常數(shù)測試
? ? // 比例閾值1、熔斷時長5、最小請求數(shù)2、統(tǒng)計時長1000
? ? @RequestMapping("m4")
? ? @SentinelResource(value = "m4", blockHandler = "test4")
? ? public String m4(){
? ? ? ? int i = 4 / 0;
? ? ? ? System.out.println("m4...................................");
? ? ? ? return "m4";
? ? }
? ? String test4(BlockException e){
? ? ? ? System.out.println(e);
? ? ? ? return "異常數(shù)熔斷降級";
? ? }
}