Spring Cloud Alibaba(三)Sentinel之熔斷降級

本項(xiàng)目演示如何使用 Sentinel 完成 Spring Cloud 應(yīng)用的熔斷降級調(diào)用。

Sentinel 是阿里巴巴開源的分布式系統(tǒng)的流量防衛(wèi)組件,Sentinel 把流量作為切入點(diǎn),從流量控制,熔斷降級,系統(tǒng)負(fù)載保護(hù)等多個(gè)維度保護(hù)服務(wù)的穩(wěn)定性。

OpenFeign是一款聲明式、模板化的HTTP客戶端, Feign可以幫助我們更快捷、優(yōu)雅地調(diào)用HTTP API,需要了解OpenFeign使用基礎(chǔ),可以參考cloud-feign示例源碼。

本項(xiàng)目服務(wù)注冊中心使用nacos,服務(wù)提供者使用Spring Cloud Alibaba(一) 如何使用nacos服務(wù)注冊和發(fā)現(xiàn)創(chuàng)建的ali-nacos-provider服務(wù)

Sentinel介紹

隨著微服務(wù)的流行,服務(wù)和服務(wù)之間的穩(wěn)定性變得越來越重要。Sentinel 以流量為切入點(diǎn),從流量控制、熔斷降級、系統(tǒng)負(fù)載保護(hù)等多個(gè)維度保護(hù)服務(wù)的穩(wěn)定性。

Sentinel 具有以下特征:

1.豐富的應(yīng)用場景

Sentinel 承接了阿里巴巴近 10 年的雙十一大促流量的核心場景,例如秒殺(即突發(fā)流量控制在系統(tǒng)容量可以承受的范圍)、消息削峰填谷、集群流量控制、實(shí)時(shí)熔斷下游不可用應(yīng)用等。

2.完備的實(shí)時(shí)監(jiān)控

Sentinel 同時(shí)提供實(shí)時(shí)的監(jiān)控功能。您可以在控制臺中看到接入應(yīng)用的單臺機(jī)器秒級數(shù)據(jù),甚至 500 臺以下規(guī)模的集群的匯總運(yùn)行情況。

3.廣泛的開源生態(tài)

Sentinel 提供開箱即用的與其它開源框架/庫的整合模塊,例如與 Spring Cloud、Dubbo、gRPC 的整合。您只需要引入相應(yīng)的依賴并進(jìn)行簡單的配置即可快速地接入 Sentinel。

4.完善的 SPI 擴(kuò)展點(diǎn)

Sentinel 提供簡單易用、完善的 SPI 擴(kuò)展接口。您可以通過實(shí)現(xiàn)擴(kuò)展接口來快速地定制邏輯。例如定制規(guī)則管理、適配動態(tài)數(shù)據(jù)源等。

Sentinel 分為兩個(gè)部分
核心庫(Java 客戶端)不依賴任何框架/庫,能夠運(yùn)行于所有 Java 運(yùn)行時(shí)環(huán)境,同時(shí)對 Dubbo / Spring Cloud 等框架也有較好的支持。

控制臺(Dashboard)基于 Spring Boot 開發(fā),打包后可以直接運(yùn)行,不需要額外的 Tomcat 等應(yīng)用容器。

Sentinel主要特性



Sentinel開源生態(tài)



熔斷降級

對調(diào)用鏈路中不穩(wěn)定的資源進(jìn)行熔斷降級是保障高可用的重要措施之一。由于調(diào)用關(guān)系的復(fù)雜性,如果調(diào)用鏈路中的某個(gè)資源不穩(wěn)定,最終會導(dǎo)致請求發(fā)生堆積。Sentinel 熔斷降級會在調(diào)用鏈路中某個(gè)資源出現(xiàn)不穩(wěn)定狀態(tài)時(shí)(例如調(diào)用超時(shí)或異常比例升高),對這個(gè)資源的調(diào)用進(jìn)行限制,讓請求快速失敗,避免影響到其它的資源而導(dǎo)致級聯(lián)錯(cuò)誤。當(dāng)資源被降級后,在接下來的降級時(shí)間窗口之內(nèi),對該資源的調(diào)用都自動熔斷(默認(rèn)行為是拋出 DegradeException)

降級策略

平均響應(yīng)時(shí)間 (DEGRADE_GRADE_RT):當(dāng) 1s 內(nèi)持續(xù)進(jìn)入 5 個(gè)請求,對應(yīng)時(shí)刻的平均響應(yīng)時(shí)間(秒級)均超過閾值(count,以 ms 為單位),那么在接下的時(shí)間窗口(DegradeRule 中的 timeWindow,以 s 為單位)之內(nèi),對這個(gè)方法的調(diào)用都會自動地熔斷(拋出 DegradeException)。

異常比例 (DEGRADE_GRADE_EXCEPTION_RATIO):當(dāng)資源的每秒請求量 >= 5,并且每秒異??倲?shù)占通過量的比值超過閾值(DegradeRule 中的 count)之后,資源進(jìn)入降級狀態(tài)。

異常數(shù) (DEGRADE_GRADE_EXCEPTION_COUNT):當(dāng)資源近 1 分鐘的異常數(shù)目超過閾值之后會進(jìn)行熔斷。

熔斷降級代碼實(shí)現(xiàn)

服務(wù)提供方

創(chuàng)建ali-nacos-provider項(xiàng)目

首先, 依賴nacos 注冊中心

<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>

定義服務(wù)提供方接口

@RestController
@Slf4j
public class HelloController {
    @GetMapping(value = "/hello/{str}", produces = "application/json")
    public String hello(@PathVariable String str) {
        log.info("-----------收到消費(fèi)者請求-----------");
        log.info("收到消費(fèi)者傳遞的參數(shù):" + str);
        String result = "我是服務(wù)提供者,見到你很高興==>" + str;
        log.info("提供者返回結(jié)果:" + result);
        return result;
    }
}
服務(wù)提消費(fèi)方

創(chuàng)建ali-nacos-sentinel-feign項(xiàng)目

1.首先,pom.xml添加依賴

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
        </dependency>
    </dependencies>






2.定義FeignClient,及其降級配置

定義FeignClient

package com.easy.ansFeign.service;

import com.easy.ansFeign.fallback.HelloServiceFallbackFactory;

import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;

@FeignClient(name = "ali-nacos-provider", fallbackFactory = HelloServiceFallbackFactory.class)
public interface HelloService {

    /**
     * 調(diào)用服務(wù)提供方的輸出接口.
     *
     * @param str 用戶輸入
     * @return hello result
     */
    @GetMapping("/hello/{str}")
    String hello(@PathVariable("str") String str);
}
定義fallback 工廠,獲取異常

@Component
public class HelloServiceFallbackFactory implements FallbackFactory<HelloServiceFallback> {

    @Override
    public HelloServiceFallback create(Throwable throwable) {
        return new HelloServiceFallback(throwable);
    }
}
定義具體的fallback 實(shí)現(xiàn)

public class HelloServiceFallback implements HelloService {

    private Throwable throwable;

    HelloServiceFallback(Throwable throwable) {
        this.throwable = throwable;
    }

    /**
     * 調(diào)用服務(wù)提供方的輸出接口.
     *
     * @param str 用戶輸入
     * @return
     */
    @Override
    public String hello(String str) {
        return "服務(wù)調(diào)用失敗,降級處理。異常信息:" + throwable.getMessage();
    }
}
測試入口

@RestController
public class TestController {

    @Autowired
    private HelloService helloService;

    @GetMapping("/hello-feign/{str}")
    public String feign(@PathVariable String str) {
        return helloService.hello(str);
    }
}

使用示例

示例關(guān)聯(lián)項(xiàng)目
在Spring Cloud Alibaba(一) 如何使用nacos服務(wù)注冊和發(fā)現(xiàn)基礎(chǔ)上,我們新建了ali-nacos-sentinel-feign項(xiàng)目,并調(diào)用ali-nacos-provider項(xiàng)目用作該示例的服務(wù)提供方,有以下二個(gè)項(xiàng)目做測試。

ali-nacos-provider:服務(wù)提供者,服務(wù)名:ali-nacos-provider,端口:9000

ali-nacos-sentinel-feign:服務(wù)消費(fèi)者,服務(wù)名:ali-nacos-sentinel-feign,端口:9102


運(yùn)行示例測試

首先要啟動服務(wù)注冊中心 nacos、ali-nacos-provider服務(wù)及ali-nacos-sentinel-feign服務(wù)

訪問地址:http://

localhost:9102/hello-feign/yuntian

返回

我是服務(wù)提供者,見到你很高興==>yuntian
復(fù)制代碼
表示我們的服務(wù)成功調(diào)用到了

關(guān)閉ali-nacos-provider服務(wù),訪問:http://

localhost:9102/hello-feign/yuntian

返回

服務(wù)調(diào)用失敗,降級處理。
異常信息:
com.netflix.client.ClientException:
Load balancer does not have available server for client: ali-nacos-provider
表示執(zhí)行了我們預(yù)定的回調(diào),服務(wù)成功降級了。

作者:碼出宇宙

歡迎關(guān)注微信公眾號 :碼出宇宙

掃描添加好友邀你進(jìn)技術(shù)交流群,加我時(shí)注明【姓名+公司(學(xué)校)+職位】