一、整合 OpenFeign 進行降級
1.1、引入依賴
<dependencies>
<!-- Nacos 服務註冊與發現 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!--1.新增 openfeign 依賴-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<!-- sentinel 依賴 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
</dependencies>
服務提供方的介面為
@RestController
@RequestMapping("/stock")
public class StockController {
@RequestMapping("/reduce2")
public String reduce2() {
int a = 1 / 0;
System.out.println("扣減庫存!");
return "扣減庫存:" + port;
}
}
1.2、加上 openfeign 介面的實現類
@Component
public class StockFeignServiceFallback implements StockFeignService{
@Override
public String reduce2() {
return "降級了";
}
}
1.3、application.yml,啟動 feign 對 sentinel 的整合
feign:
sentinel:
# openfeign 整合 sentinel
enabled: true
1.4、在 openfeign 介面上配置 fallback 的實現類
@FeignClient(value = "stock-server",path = "stock",contextId = "orderFeignSentinel",fallback = StockFeignServiceFallback.class)
public interface StockFeignService {
// 宣告需要呼叫的 rest 介面對應的方法
@RequestMapping("/reduce2")
String reduce2();
}
啟動服務,看到此時服務提供方和呼叫方都已註冊到 nacos 了。
請求介面http://localhost:8041/order/add
,發現針對遠端服務進行了降級
二、熱點引數限流(熱點識別流控)
熱點即經常訪問的資料,很多時候我們希望統計某個熱點資料中訪問頻次最高的資料,並對其訪問進行限制。常用的場景如熱點商品的訪問/操作控制,使用者/IP 防刷等。實現原理為熱點淘汰策略(LRU)+ Token Bucket 流控。
熱點引數限流會統計傳入引數中的熱點引數,並根據配置的限流閾值與模式,對包含熱點引數的資源呼叫進行限流。
熱點引數限流可以看做是一種特殊的流量控制, 僅對包含熱點引數的資源呼叫生效。
準備介面
/**
* 熱點規則,必須使用 @SentinelResource,是對引數 id 進行流控的
*/
@RequestMapping("/get/{id}")
@SentinelResource(value = "getById",blockHandler = "HotBlockHandler")
public String getById(@PathVariable("id")Integer id) {
System.out.println("正常訪問");
return "正常訪問";
}
public String HotBlockHandler(@PathVariable("id")Integer id,BlockException e) {
return "熱點異常處理";
}
單機閾值:
1.假設引數大部分值都是熱點引數,那麼單機閾值主要針對熱點引數進行流控,後續額外對普通的引數值進行流控。
2.假設大部值都是普通流量,則與上面相反。
配置熱點引數規則注意:資源名必須是@SentinelResource(value="資源名")中配置的資源名,熱點規則依賴於註解
假設這個引數,大部分情況下都是普通流量,只有少部分值是熱點流量
先針對普通流量,QPS 設定為 10,然後進行編輯
然後對額外的熱點流量進行流控設定,設定 QPS 為 2
發現,訪問 id 為 2時,只有超過 QPS 10 時,才會觸發流控,但是訪問 id 為 1 時,訪問 QPS 超過 2就出現流控了
三、系統規則
在實際的生產環境中,可能會有如下問題
容量評估不到位,某個大流量介面限流配置不合理或沒有配置,導致系統崩潰,來不及進行處理。
突然發現機器的Load和CPU usage等開始飈高,但卻沒有辦法很快的確認到是什麼原因造成的,也來不及處理。
當其中一-臺機器掛了之後,本該由這臺機器處理的流量被負載均衡到另外的機器上,另外的機器也被打掛了,引起系統雪崩。
這時,我們希望有個全域性的兜底防護,即使缺乏容量評估也希望有一定的保護機制。即結合系統指標和服務容量,自適應動態調整流量
Sentinel 系統自適應限流從整體維度對應用入口流量進行控制,結合應用的Load、CPU 使用率、總體平均RT、入口 QPS 和併發執行緒數等幾個維度的監控指標,透過自適應的流控策略,讓系統的入口流量和系統的負載達到一個平衡, 讓系統儘可能跑在最大吞吐量的同時保證系統整體的穩定性。
- Load自適應(僅對LinuxUnix-like機器生效):系統的 load1 作為啟發指標,進行自適應系統保護。當系統 load1 超過設定的啟發值,且系統當前的併發執行緒數超過估算的系統容量時才會觸發系統保護(BBR階段)。系統容量由系統的maxQps * minRt 估算得出。設定參考值一般是CPU cores * 2.5.
- CPU usage (1.5.0+ 版本) : 當系統CPU使用率超過閾值即觸發系統保護(取值範圍0.0-1.0) ,比較靈敏。
- 平均RT:當單臺機器上所有入口流量的平均RT達到閾值即觸發系統保護,單位是毫秒。
- 併發執行緒數:當單臺機器上所有入口流量的併發執行緒數達到閾值即觸發系統保護。
- 入口QPS:當單臺機器上所有入口流量的 QPS 達到閾值即觸發系統保護。
可以看到系統負載基本在 15% 以上,設定系統保護為 cpu 閾值 20%
訪問介面可以看到
四、規則持久化
可以看到之前的無論是流控、降級、熱點規則等,只要服務重啟,就會丟失
sentinel 規則的推送有三種模式
推動模式 | 說明 | 優點 | 缺點 |
---|---|---|---|
原始模式 | API 將規則推送至客戶端並直接更新到記憶體中,擴充寫資料來源(WritableDataSource) | 簡單,無任何依賴 | 不保證一致性:規則儲存在記憶體中,重啟即消失,嚴重不建議用於生產環境 |
Pull模式 | 擴充寫資料來源(WritableDataSource),客戶端主動向某個規則管理中心定期輪詢拉取規則,這個規則中心可以是 RDBMS,檔案等 | 簡單,無任何依賴,規則持久化 | 不保證一致性;實時性不保證,拉取過於頻繁可能有效能問題 |
Push模式 | 擴充讀資料來源(ReadableDataSource),規則中心統一推送,客戶端透過註冊監聽的方式時刻監聽變化,比如使用 Nacos、Zookeeper等配置中心。這種方式有更好的實時性和一致性保證。生產環境一般採用 push 模式的資料來源 | 規則持久化;一致性;快速 | 引入第三方依賴 |
4.1 原始模式
如果不做任何修改,Dashboard 的推送雖則方式是透過 API 將規則推送至客戶端並直接更新到記憶體中
這種做法的好處是簡單,無依賴;壞處是應用重啟,規則就會消失,僅用於簡單測試,不能用於生產環境。
4.2、拉模式
pull模式的資料來源(如本地檔案、RDBMS 等)一般是可寫入的。 使用時需要在客戶端註冊資料來源:將對應的讀資料來源註冊至對應的 RuleManager,將寫資料來源註冊至transport的 WritableDataSourceRegistry 中。
4.3、推模式
生產環境下一般更常用的是 push模式的資料來源。對於push模式的資料來源,如遠端配置中心(ZooKeeper, Nacos, Apollo等等), 推送的操作不應由 Sentinel 客戶端進行,而應該經控制檯統一進行管理,直接進行推送,資料來源僅負責獲取配置中心推送的配置並更新到本地。因此推送規則正確做法應該是配置中心控制檯/Sentinel控制檯→配置中心→Sentinel資料來源→Sentinel,而不是經 Sentinel 資料來源推送至配置中心。這樣的流程就非常清晰了
官方 demo:sentinel-demo-nacos-datasource
引入依賴
<dependencies>
<!--sentinel 啟動器-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
</dependency>
</dependencies>
nacos 中建立如下配置
nacos 配置中心配置流控規則
系統規則
[
{
"resource": "order/flow",
"controlBehavior": 0,
"count": 2,
"grade": 1,
"limitApp": "default",
"strategy": 0
}
]
[
{
"avgRt": 10,
"highestSystemLoad": 5.0,
"maxTrhead": 10,
"qps": 20.0
}
]
application.yml 配置檔案內容如下
server:
port: 8070
spring:
application:
name: order-sentinel
cloud:
sentinel:
transport:
dashboard: 192.168.33.62:8858
clientIp: 192.168.33.27
# 預設將呼叫鏈路收斂
web-context-unify: false
datasource:
# 可以自定義
flow-rule:
nacos:
server-addr: 192.168.33.62:8847
username: kunjuee
password: we753951.
data-id: order-sentinel-flow-rule
rule-type: flow
system:
nacos:
server-addr: 192.168.33.62:8847
username: kunjuee
password: we753951.
data-id: order-sentinel-system-rule
rule-type: system
流控規則
系統規則
本作品採用《CC 協議》,轉載必須註明作者和本文連結