Spring Cloud & Alibaba 實戰 | 第十二篇: 微服務整合Sentinel的流控、熔斷降級,賦能擁有降級功能的Feign新技能熔斷,實現熔斷降級雙劍合璧(JMeter模擬測試)

一. Sentinel概念

1. 什麼是Sentinel?

Sentinel是阿里中間件團隊研發麵向分散式服務架構的輕量級高可用流量控制組件,主要以流量為切入點,從限流、流量整形、熔斷降級、系統負載保護、熱點防護等多個維度來幫助開發者保障微服務的穩定性。於2012年誕生,後續在阿里巴巴集團內部迅速發展,成為基礎技術模組,覆蓋了所有的核心場景,Sentinel也因此積累了大量的流量歸整場景及生產實踐。最終在2018年7月宣布對外界開源。

Sentinel的基本概念:

  • 資源: Sentinel 的關鍵概念,可以是Java應用程式中任何內容,通過Sentinel API定義的程式碼,能夠被Sentinel保護起來,大部份情況下,可以使用方法簽名,URL,甚至服務名稱作為資源名
  • 規則:圍繞資源的實時狀態設定的規則,可以包括流量控制規則、熔斷降級規則以及系統保護規則。所有規則可以動態實時調整。

Sentinel分為兩個部分:

  • 控制台(Dashboard)基於 Spring Boot 開發,打包後可以直接運行,不需要額外的 Tomcat 等應用容器,也就是sentinel-dashboard-1.8.1.jar。
  • 核心庫(Java 客戶端)不依賴任何框架/庫,能夠運行於所有 Java 運行時環境,同時對 Dubbo / Spring Cloud 等框架也有較好的支援。

2. Sentinel功能特性

從上圖可知Sentinel的功能特性很多以及應用場景非常廣泛,以下就限流熔斷降級這幾個常見的功能特性以及意義進行簡要說明

限流:限流同時也叫做流量控制,原理是監控應用流量的QPS或並發執行緒數等指標,當達到指定的閾值時對流量進行控制,以避免被瞬時的流量高峰衝垮,從而保障應用的高可用性。

熔斷降級:除了流量控制以外,及時對調用鏈路中的不穩定因素進行熔斷也是Sentinel的使命之一。由於調用關係的複雜性,如果調用鏈路中的某個資源不穩定,最終會導致請求發生堆積,進而導致級聯錯誤。Sentinel當檢測到調用鏈路中某個資源出現不穩定的表現(請求響應時間長或異常比例升高),則對這個資源的調用進行限制,讓請求快速失敗,避免影響到其他資源而導致級聯故障。

  • 熔斷: 拒絕流量訪問,當系統恢復正常時關閉熔斷。
  • 降級:將次要服務降級,停止服務,將系統資源放出來給核心功能

3. Sentinel VS Hystrix

以下摘自Sentinel官方文檔,詳情點擊 Sentinel 與 Hystrix 的對比

Sentinel Hystrix
隔離策略 訊號量隔離 執行緒池隔離/訊號量隔離
熔斷降級策略 基於響應時間或失敗比率 基於失敗比率
實時指標實現 滑動窗口· 滑動窗口(基於 RxJava)
規則配置 支援多種數據源 支援多種數據源
擴展性 多個擴展點 插件的形式
基於註解的支援 支援 支援
限流 基於 QPS,支援基於調用關係的限流 有限的支援
流量整形 支援慢啟動、勻速器模式 不支援
系統負載保護 支援 不支援
控制台 開箱即用,可配置規則、查看秒級監控、機器發現等 不完善
常見框架的適配 Servlet、Spring Cloud、Dubbo、gRPC 等 Servlet、Spring Cloud Netflix

Sentinel 和 Hystrix 的原則是一致的,但是在限制手段上,Sentinel和Hystrix採取了完全不一樣的方法。

  • Hystrix: 通過執行緒池隔離,來對依賴(在Sentinel的概念對應資源)進行了隔離。好處在於資源之間做到最徹底的隔離,缺點是除了增加了執行緒切換的成本,還需要預先給各個資源做執行緒池大小的分配。
  • Sentinel : 通過並發執行緒數進行限制和響應時間對資源進行降級兩種手段。

二. Docker部署Sentinel Dashboard

1. 拉取鏡像

docker pull bladex/sentinel-dashboard

2. 啟動容器

docker run --name sentinel -d -p 8858:8858 -d bladex/sentinel-dashboard

3. 訪問測試

訪問://IP:8858

用戶名/密碼:sentinel/sentinel

image-20210404135319822

三. Sentinel網關流控

1. 網關流控定義

Sentinel支援對Spring Cloud Gateway、Zuul等主流的API Gataway 進行限流,作用在網關的流控稱之為網關流控,其實現原理請點擊網關限流進入官方Wiki查看。

這裡只把原理圖從官方文檔摘出來,需多關注圖中提到的模組名和幾個類名,因為都是核心級別的存在。

規則類型gw-flowgw-api-group為網關流控規則,具體類型請查看規則類型枚舉RuleType

/**
* flow 流控規則
*/
FLOW("flow", FlowRule.class),
/**
* degrade 降級規則
*/
DEGRADE("degrade", DegradeRule.class),
/**
* param flow 熱點規則
*/
PARAM_FLOW("param-flow", ParamFlowRule.class),
/**
* system 系統規則
*/
SYSTEM("system", SystemRule.class),
/**
* authority 授權規則
*/
AUTHORITY("authority", AuthorityRule.class),
/**
* gateway flow 網關限流規則
*/
GW_FLOW("gw-flow","com.alibaba.csp.sentinel.adapter.gateway.common.rule.GatewayFlowRule"),
/**
* api 用戶自定義的 API 定義分組,可以看做是一些 URL 匹配的組合
*/
GW_API_GROUP("gw-api-group","com.alibaba.csp.sentinel.adapter.gateway.common.api.ApiDefinition");

image-20210408141627006

2. 網關流控規則

Field 說明 默認值
resource 資源名稱,網關route或自定義API分組名稱(註:網關route這裡的值不是route.id,可調試
resourceMode 限流資源類型,網關route【0】或自定義API分組【1】(詳細查看GatewayFlowRuleSentinelGatewayConstants 網關route
grade 限流閾值類型,QPS【1】或執行緒數【0】 QPS
count 限流閾值,QPS閾值或執行緒數值
intervalSec 統計時間間隔,單位秒 1秒
controlBehavior 流控效果,目前支援快速失敗【0】和勻速排隊【1】 快速失敗
burst 應對突發請求時額外允許的請求數目
maxQueueingTimeoutMs 勻速排隊模式下的最長排隊時間,單位毫秒,僅在勻速排隊模式下生效
paramItem 參數屬性配置,parseStrategy:提取參數策略(0:Clien IP,1:Remote HOST,2:Header,3:請求參數,4:Cookie);fieldName:若提取策略是Header模式或者URL參數模式,則需要指定header名稱或URL參數名稱;pattern:參數值的匹配模式;matchStrategy:參數值的匹配策略,支援精確匹配,子串匹配和正則匹配。

3. 導入依賴

<!-- Sentinel流量控制、熔斷降級 -->
<dependency>
	<groupId>com.alibaba.cloud</groupId>
	<artifactId>spring-cloud-alibaba-sentinel-gateway</artifactId>
</dependency>
<dependency>
	<groupId>com.alibaba.cloud</groupId>
	<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<!-- Sentinel規則持久化至Nacos配置 -->
<dependency>
	<groupId>com.alibaba.csp</groupId>
	<artifactId>sentinel-datasource-nacos</artifactId>
</dependency>

4. 網關配置

先放在本地Spring Boot配置文件bootstrap-dev.yml中,後面測試通過把後再把Sentinel配置放至Nacos

spring:
  cloud:
    nacos:
      # 註冊中心
      discovery:
        server-addr: //localhost:8848
      # 配置中心
      config:
        server-addr: ${spring.cloud.nacos.discovery.server-addr}
        file-extension: yaml
    sentinel:
      enabled: true # sentinel開關
      eager: true
      transport:
        dashboard: 192.168.1.188:8858
        client-ip: localhost
      datasource:
        # 網關限流規則,gw-flow為key,隨便定義
        gw-flow:
          nacos:
            server-addr: ${spring.cloud.nacos.discovery.server-addr}
            dataId: ${spring.application.name}-gw-flow-rules # 流控規則配置文件名:youlai-gateway-gw-flow-rules
            groupId: SENTINEL_GROUP
            data-type: json
            rule-type: gw-flow
        # 自定義API分組,gw-api-group為key,隨便定義
        gw-api-group:
          nacos:
            server-addr: ${spring.cloud.nacos.discovery.server-addr}
            dataId: ${spring.application.name}-gw-api-group-rules # 流控規則配置文件名:youlai-gateway-gw-api-group-rules
            groupId: SENTINEL_GROUP
            data-type: json
            rule-type: gw-api-group

這裡解釋下配置中的datasource,因為在Sentinel添加流控規則之後,如果重啟服務,之前配置的規則就會消失,所以這裡需要持久化Sentinel配置,從上面的配置可以看出選擇的是Nacos。不過這裡先別急在Nacos添加網關流控規則,下文在測試確認需求後配置。

5. 網關流控客戶端標識

網關流控和普通流控有很多區別,其中網關流控類型是gw-flow,普通流控類型是flow

怎麼標識流控是網關類型呢?

很多部落格文章都沒有著重此點,因為前陣子糾結於網關流控的面板和普通流控的面板不一致而去搜相關的資料,最後還是在Sentinel官方文檔中找到此開關,就是需要在youlai-gateway網關應用添加JVM啟動參數。

# 註:通過 Spring Cloud Alibaba Sentinel 自動接入的 API Gateway 整合則無需此參數
-Dcsp.sentinel.app.type=1

具體如下圖:

image-20210408133502518

6. 測試需求制定

在做好上面Sentinel Dashboard部署以及Spring Cloud Gateway整合Sentinel工作之後,Sentinel的兩個部分(控制台和Java客戶端)也就齊活了,那麼接下來就進入測試。

下圖簡單的描述了OAuth2認證介面的流程,用戶請求網關,網關(youlai-gateway)根據請求標識轉發至認證中心,認證中心(youlai-auth)需要從系統服務(youlai-admin)獲取資料庫的用戶資訊再和請求攜帶的用戶資訊進行密碼判讀,成功則返回token給用戶。

針對以上的OAuth2認證流程,提出來一個需求:

假設認證中心服務的QPS上限為10,系統服務的QPS上限為5,如何通過Sentinel實現限流控制?

溫馨提示:留意下上圖中的紅線部分,你認為網關的流控是否能限制到與其間接相關的系統服務youlai-admin嗎?

7. Nacos添加網關流控規則

進入Nacos控制台,添加網關流控規則,具體內容參考網關流控欄位說明。

需要注意的是資源名稱resource不是路由中配置的route的id,在開啟Sentinel時調試SentinelGatewayFilter#filter方法可以看到自動生成的是固定前綴ReactiveCompositeDiscoveryClient_拼接應用名稱${spring.application.name},所以在配置文件中一定要按照自動生成的規則配置resource的值。填寫網關路由route的id,Sentinel的網關流控是無法生效的。

image-20210410094637495

上面網關流控規則中,限制了認證中心youlai-auth的QPS上限為10,系統服務youlai-admin的QPS上限為5。

至於為什麼這麼設定,因為有個猜想需要驗證,網關流控是否只能限制和直接關聯的youlai-auth,而不能限制間接相關的youlai-admin。

如果通過的QPS是10,那說明網關流控不能控制間接相關youlai-admin,如果通過的QPS是5,則說明網關流控能控制間接相關的youlai-admin,至於結果,先留個懸念吧,看下文的測試結果。

已添加的網關流控規則如下圖:

image-20210410094826077

在Nacos添加了網關流控規則之後,會同步到Sentinel,進入Sentinel控制台查看

image-20210410144417922

8. 網關流控測試

在完成上述步驟之後,接下來就進入真正的測試環節。

添加執行緒組

測試計劃(滑鼠右擊)->添加->執行緒(用戶)->執行緒組

image-20210410104749030

因為youlai-auth的QPS處理上限為10,所以這裡的執行緒數大於10即可看到被限制的請求

image-20210410105330921

添加HTTP請求

OAuth2登錄執行緒組(滑鼠右擊)->添加->取樣器->HTTP請求

image-20210410105624953

介面是通過網關轉發到認證中心的認證介面獲取token

image-20210410110644266

添加察看結果樹

因為要看請求的響應,所以這裡添加察看結果樹。

OAuth2登錄執行緒組(滑鼠右擊)->添加->監聽器->察看結果樹

image-20210410112100659

啟動執行緒組測試

啟動執行緒組,每秒15次認證請求,需要注意的是,如果測試計劃有多個執行緒組,需禁用除了測試之外的其他執行緒組。

image-20210410135357237

點擊察看結果樹查看請求的情況

image-20210411184249307

進入Sentinel控制台,查看實時監控

image-20210411184545190

可以看到1秒15次請求,因為流控設置的QPS上限是10,所以10次通過,被Sentinel拒絕了5次。

這個結果也直接說明了網關流控並不是萬能的,不能限制OAuth2認證請求中與其間接相關youlai-admin的微服務,因為在網關流控設置了youlai-admin的QPS上線為5,但最後整條鏈路成功的卻是10。既然網關流控無法應對此類場景,是否還有其他的辦法來做到呢?當然有:普通流控

9. 自定義網關流控異常

上面Sentinel限流的默認異常響應如下

{"code":429,"message":"Blocked by Sentinel: ParamFlowException"}

假如想自定義網關流控異常響應,該如何實現呢?

可以通過在GatewayCallbackManager上通過setBlockHandler方法註冊回調實現,當請求被限流後,實現自定義的異常響應。

image-20210411233958606

自定義異常程式碼:

@PostConstruct
private void initBlockHandler() {
    BlockRequestHandler blockRequestHandler = (exchange, t) ->
        ServerResponse.status(HttpStatus.OK)
        .contentType(MediaType.APPLICATION_JSON)
        .body(BodyInserters.fromValue(ResultCode.FLOW_LIMITING.toString()));
    GatewayCallbackManager.setBlockHandler(blockRequestHandler);
}

JMeter中查看被限流的響應,可以看到已按照自定義的響應異常返回,其中B0210 是Java開發手冊上的關於系統限流的錯誤碼

image-20210411234203870

四. Sentinel普通流控

1. 普通流控定義

/**
* flow 流控規則,詳情查看RuleType
*/
FLOW("flow", FlowRule.class)

作用在網關的流控稱之為網關流控,相對的作用在除網關之外的微服務流控這裡稱為普通流控

在上一個章節中,發現網關流控並不是萬能的,像認證中心youlai-auth調用系統服務youlai-admin這種微服務相互調用而不走網關的情況,網關流控表示無能為力,但不可否認的是網關流控確實能夠應對大多數場景的流控。

所以在像上文中的網關流控無能為力的案例,則需要普通流控的救場。

2. 普通流控的規則

Field 說明 默認值
resource 資源名,資源名是限流規則的作用對象
count 限流閾值
grade 限流閾值類型,QPS 【1】或執行緒數模式【0】 QPS 模式
limitApp 流控針對的調用來源 default,代表不區分調用來源
strategy 判斷的根據是資源自身,還是根據其它關聯資源 (refResource),還是根據鏈路入口 根據資源本身
controlBehavior 流控效果(直接拒絕 / 排隊等待 / 慢啟動模式) 直接拒絕

3. 導入依賴

<!-- Sentinel流量控制、熔斷降級 -->
<dependency>
	<groupId>com.alibaba.cloud</groupId>
	<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<!-- Sentinel規則持久化至Nacos配置 -->
<dependency>
	<groupId>com.alibaba.csp</groupId>
	<artifactId>sentinel-datasource-nacos</artifactId>
</dependency>

4. 微服務配置

spring:
  application:
    name: youlai-admin
  cloud:
    nacos:
      discovery:
        server-addr: //localhost:8848
      config:
        server-addr: ${spring.cloud.nacos.discovery.server-addr}
        file-extension: yaml
    sentinel:
      enabled: true
      eager: true # 取消控制台懶載入,項目啟動即連接Sentinel
      transport:
        client-ip: localhost
        dashboard: localhost:8080
      datasource:
        # 限流規則,flow為key,隨便定義
        flow:
          nacos:
            server-addr: ${spring.cloud.nacos.discovery.server-addr}
            dataId: ${spring.application.name}-flow-rules
            groupId: SENTINEL_GROUP
            data-type: json
            rule-type: flow

5. Nacos添加流控規則

進入Nacos控制台,添加規則配置文件,接著上文的案例,在認證的時候,youlai-auth需通過feign調用youlai-admin根據用戶名獲取用戶資訊。

image-20210412221145722

進入Sentinel控制台查看,除了剛在Nacos添加的規則之外,還可以看到普通流控面板和網關流控面板的區別

image-20210412221507202

6. 普通流控測試

經過網關流控限制只能有10條請求到youlai-auth,接下來youlai-auth調用youlai-admin鏈路中,因為限制了youlai-admin的QPS上限為5,所以最終應該是只有5條請求是有效的。看測試結果:

image-20210412222948233

?

7. 自定義異常

上面被限流後的異常資訊,顯然不是想要的,那麼如何自定義普通流控異常呢?

解決方案:實現BlockExceptionHandler介面

@Component
public class DefaultBlockExceptionHandler implements BlockExceptionHandler {
    @Override
    public void handle(HttpServletRequest request, HttpServletResponse response, BlockException e) throws Exception {
        response.setStatus(HttpStatus.ok().status());
        response.setCharacterEncoding("UTF-8");
        response.setContentType("application/json;charset=utf-8");
        if(e instanceof FlowException){
            // objectMapper.writeValue 用於將java對象轉位JSON格式返回調用方
            new ObjectMapper().writeValue(response.getWriter(), Result.failed(ResultCode.FLOW_LIMITING));
        }
    }
}

為了測試普通流控,首先關閉網關流控,排除一些異常干擾

image-20210420234155626

添加獲取當前登錄用戶資訊的HTTP請求

image-20210420234021268

因為此HTTP介面需要認證,所以需要在請求頭添加token。滑鼠右擊HTTP請求->添加->配置元件->HTTP資訊頭管理

image-20210420234827348

HTTP資訊頭管理器添加token

image-20210420234709242

執行執行緒組,查看自定義異常生效

image-20210420234933142

五. Sentinel熔斷降級

1. 熔斷降級概述

微服務架構都是分散式的,不同服務相互調用,組成複雜的調用鏈路。複雜的鏈路上某一環不穩定,就可能層層級聯,最終導致整個鏈路都不可用。因此需要對不穩定的弱依賴服務調用進行熔斷降級,暫時切斷不穩定的調用,避免局部不穩定因素導致正題的雪崩。熔斷降級作為保護自身的手段,通常在客戶端(調用端)進行配置。

2. 熔斷策略

image-20210422235109981

Sentinel提供了三種熔斷策略:

  • 慢調用比例: 請求響應時間大於設置的RT(即最大的響應時間)則統計為慢調用。觸發此熔斷策略的條件需要滿足兩個條件,一是單位統計時長(statIntervalMs)內請求數大於設置的最小請求數,二是慢調用的比例大於閾值,接下來在熔斷時長的範圍內請求會自動的被熔斷。過了熔斷時長後,熔斷器進入探測恢復狀態(HALF-OPEN狀態),若接下來的一個請求響應時間小於設置的慢調用RT則結束熔斷,若大於設置的慢調用RT則會再次被熔斷。
  • 異常比例:當單位統計時長請求數大於設置的最小請求數,並且異常的比例大於閾值,則接下來的熔斷時長內請求會被自動熔斷。
  • 異常數:當單位統計時長內的異常數目超過閾值之後會自動進行熔斷。

3. 熔斷降級規則

熔斷降級規則(DegradeRule)包含下面幾個重要的屬性:

Field 說明 默認值
resource 資源名,即規則的作用對象
grade 熔斷策略,支援慢調用比例/異常比例/異常數策略 慢調用比例
count 慢調用比例模式下為慢調用臨界 RT(超出該值計為慢調用);異常比例/異常數模式下為對應的閾值
timeWindow 熔斷時長,單位為 s
minRequestAmount 熔斷觸發的最小請求數,請求數小於該值時即使異常比率超出閾值也不會熔斷(1.7.0 引入) 5
statIntervalMs 統計時長(單位為 ms),如 60*1000 代表分鐘級(1.8.0 引入) 1000 ms
slowRatioThreshold 慢調用比例閾值,僅慢調用比例模式有效(1.8.0 引入)

4. 微服務配置

spring:
  cloud:
    sentinel:
        # 降級規則,degrade為降級key,隨便取名
        degrade:
          nacos:
            server-addr: ${spring.cloud.nacos.discovery.server-addr}
            dataId: ${spring.application.name}-degrade-rules
            groupId: SENTINEL_GROUP
            data-type: json
            rule-type: degrade

5. Nacos添加熔斷降級規則

image-20210423005837408

方便看到異常熔斷的效果,選擇了異常數的熔斷策略,畢竟數數比計算比例簡單多了。資源名為getCurrentUser是怎麼回事,不急下文提到。總之這裡的配置的大概意思就是說針對getCurrentUser資源,如果請求該介面出現了異常,則進行熔斷,熔斷時長為5秒。

6. 熔斷異常模擬

先模擬一段在運行時發生異常的程式碼,在獲取當前登錄用戶資訊的介面埋個雷吧,注意到@SentinelResource註解中的value值getCurrentUser,也就是資源名稱,聯繫上文,降級規則就是針對這個介面的方法。和上面在普通流控測試使用的是請求的路徑不同,這裡顯示指定了資源名稱和降級規則配置去做匹配。

@SentinelResource註解中的屬性除了定義資源名的屬性值value,還有兩個屬性有關降級處理分別是blockHandlerClass和blockHandler。意思是在單位時間介面異常數超過設置的閾值後進入熔斷,在熔斷時長(上面降級規則中設置的是5秒)範圍內,再有請求過來訪問該介面時,不會再走介面方法體內的邏輯。因為前面幾次介面出現異常,那麼敢斷定接下來短時間內大概率還是會發生異常,所以索性就把後續的請求攔截避免,這也是熔斷的意義。

在5秒的熔斷時長內,如果再有請求訪問該介面則會走降級的邏輯,也就是上圖中指定的UserBlockHandler#handleGetCurrentUserBlock降級處理方法。

image-20210424155414631

7. 熔斷降級測試

在測試前,需要關閉網關那邊流控,排除一些異常情況下的干擾。還有為了方便在JMeter查看結果,臨時關閉全局異常處理器GlobalExceptionHandler。

還是拿上一節配置好的測試普通流控的執行緒組,獲取登錄用戶的資訊來作為熔斷降級的測試案例,先看一下執行緒組的設置:

執行緒數為10,達到了熔斷降級最小請求數(規則配置的5)的要求

獲取登陸用戶資訊的介面資訊

image-20210424183038021

請求頭添加token

image-20210424183053841

測試執行緒組配置好之後看看使用不使用熔斷降級和使用熔斷降級的區別:

  • 不使用熔斷降級

配置中關閉Sentinel

sentinel:
  enabled: false

image-20210424192227624

image-20210424192302313

發現了嗎?這種請求異常處理模式頭鐵啊,即使撞了南牆也不會回頭,下次繼續撞,下下次繼續撞。ok,你沒關係,那你有考慮一直被你撞的牆(伺服器)了沒?

  • 使用熔斷降級

配置中開啟Sentinel

sentinel:
  enabled: true

image-20210424203541357

通過日誌可以看到進入主線程式碼的只有一次,後續的請求直接進入降級支線。

image-20210424203649057

過了熔斷時長5秒後,熔斷器進入探測恢復狀態(HALF-OPEN狀態),這時候如果一個請求到主線沒異常,關閉熔斷器,讓後續的請求都到主線過來;如果還是異常,打開熔斷器。

六. Sentinel整合Feign熔斷降級

1. Feign與Sentinel整合意義

在微服務架構中,聲明式調用Feign在微服務之間調用充當重要的角色,在使用Feign的過程中如果為了系統的健壯性,一定會考慮如果因目標服務異常調用失敗後的處理。

說到這裡,相信對微服務有些了解的童鞋對下面的程式碼很熟悉:

image-20210428234713923

上面兩張圖反應了Feign客戶端在遠程調用目標服務失敗後,繼而選擇了降級的邏輯,像做人一樣隨時要給自己留一條後路,也就是穩,折射到程式亦是如此。這裡只是一個降級的自定義異常返回,實際情況根據業務而定。

看到上面的程式碼,Feign在設計上就支援了降級的處理。這時候相信大家都會有一個疑問,Feign本身已經支援降級,那還需要Sentinel做什麼?

換句話說可能會好理解一點,Sentinel給Feign帶來了什麼好處?

這個問題其實不難理解,先直接從字面上切入。

Feign是能夠做到降級,Sentinel能夠實現熔斷降級,突顯出來也就是熔斷這一詞,其中熔斷的具體表象是怎樣的?舉個栗子說明:

假如客戶端a通過feign調用b服務100次,此時b服務故障

  1. 沒有熔斷

    a的第1次請求走到b服務跟前,看著b躺在地上沒動靜,響應給客戶端a說b沒動靜,讓客戶端a自己看著辦吧。後面如此往複99次,每次a都需要走到b的面前然後再響應給客戶端a,並告知b故障了。

  2. 有熔斷

    a的第1次請求走到b服務跟前,看著b躺在地上沒動靜,這時候a就比較機智,判斷b服務沒有一時半刻是起不來了,就響應給客戶端a並說這一時半刻鐘的請求你自己看著處理吧,沒有必要再到b面前,後面的99次請求就不會再到服務b那裡了,省時省力。

想通過上面的舉例說明熔斷的意義和作用,因為Feign已經支援了降級,那再搭配上Sentinel的熔斷,豈不是如虎添翼?

接下來將通過有來項目中的實例,認證中心【youlai-auth】在登錄時需要遠程feign調用系統服務【youlai-admin】的根據用戶名獲取用戶資訊的介面,來說明Sentinel如何整合Feign實現熔斷降級及熔斷降級的魅力。

2. 導入依賴

youlai-auth添加Sentinel和Nacos持久化規則依賴

<!-- Sentinel流量控制、熔斷降級 -->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<!-- Sentinel規則持久化至Nacos配置 -->
<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-datasource-nacos</artifactId>
</dependency>

3. 微服務配置

youlai-auth開啟Feign對Sentinel的支援

spring:
  application:
    name: youlai-auth
  cloud:
    sentinel:
      enabled: true
      eager: true # 取消控制台懶載入,項目啟動即連接Sentinel
      transport:
        client-ip: localhost
        dashboard: localhost:8080
      datasource:
        # 降級規則
        degrade:
          nacos:
            server-addr: ${spring.cloud.nacos.discovery.server-addr}
            dataId: ${spring.application.name}-degrade-rules
            groupId: SENTINEL_GROUP
            data-type: json
            rule-type: degrade
# Feign開啟對Sentinel支援
feign:
  sentinel:
    enabled: true 

4. 熔斷降級規則

在Nacos控制台添加youlai-auth的降級規則

image-20210429004026068

[
	{
		"resource": "GET://youlai-admin/api.admin/v1/users/username/{username}",
		"grade": 2,
		"count": 1,
		"timeWindow": 5
	}
]

注意資源名稱的生成規則,上面配置的意思是如果單位時間內出現了1次異常數,那沒接下來5秒的時間窗口範圍內的請求,因為熔斷器打開,請求直接走降級邏輯。

5. 熔斷降級測試

首先要模擬系統服務的根據用戶名獲取用戶資訊的介面異常,具體如下圖:

image-20210429004501032

配置JMeter執行緒組,單位時間1s內執行10個請求,具體配置在普通流控有說明,這裡不做贅述。

image-20210429004727792

結果在youlai-auth確實執行了10次請求,因為目標服務的異常走了降級的邏輯

image-20210429005106210

但是真正進入youlai-admin的根據用戶名獲取用戶資訊的介面方法卻只有1次,後續的9次請求直接走feign客戶端的降級邏輯

image-20210429005234219

上面的測試結果驗證了Feign整合Sentinel之後實現了熔斷和降級,至此Feign不再孤軍奮戰。

七. 結語

本文就Sentinel的流控、熔斷降級從實戰的角度去逐一驗證。網關流控、普通流控能夠在有限的資源能力保障系統的穩定運行,熔斷降級能夠在系統故障時提供兜底的處理邏輯保證系統的健壯性,支援降級的Feign整合Sentinel之後get到熔斷的技能,至此熔斷降級雙劍合璧。

以前覺得微服務的限流、熔斷降級是可有可無的存在,所以在開源項目中一直遲遲沒有做相關的整合,當真正理解這其中的利害關係之後,微服務離不開這些。

當然本文提到的Sentinel功能的冰山一角,像限流延伸的還有熱點key、IP限流、參數限流等等,具體選擇使用根據場景,功能豐富,總會有你需要的。而且容易上手,是一個很不錯的框架,內部的實現原理和還有演算法很有必要去了解深入下。

如果有問題,歡迎加我微信(微訊號:haoxianrui)

八. 附錄

本文涉及的源碼地址:

平台 地址
github //github.com/hxrui/youlai-mall
gitee //gitee.com/youlaitech/youlai-mall

文中的Sentinel規則配置已放置在項目document/nacos/SENTINEL_GROUP.zip,導入到Nacos控制台即可

image-20210430005807348

當然你也可以本地啟動Sentinel控制台,已經把官方的jar包放置在項目youlai-middleware/setinel/sentinel-dashboard-1.8.1.jar

cd youlai-middleware/setinel
java -jar sentinel-dashboard-1.8.1.jar

image-20210430010126472

本地訪問 //localhost:8080即可進入Sentinel控制台

歡迎大家加入開源有來項目交流群,一起參與開源項目的開發。

image-20210430010820093