分布式組件-Sentinel-使用說明

什么是雪崩

由于網(wǎng)絡(luò)原因或者自身的原因孕索,服務(wù)并不能保證 100% 可用,如果單個(gè)服務(wù)出現(xiàn)問題躏碳,調(diào)用這個(gè)服務(wù)就會(huì)出現(xiàn)線程阻塞搞旭,此時(shí)若有大量的請(qǐng)求涌入,Servlet 容器的線程資源會(huì)被消耗完畢菇绵,導(dǎo)致服務(wù)癱瘓肄渗。服務(wù)與服務(wù)之間的依賴性,故障會(huì)傳播咬最,會(huì)對(duì)整個(gè)微服務(wù)系統(tǒng)造成災(zāi)難性的嚴(yán)重后果翎嫡,這就是服務(wù)故障的 “雪崩” 效應(yīng)。

解決方案

熔斷器模型

服務(wù)熔斷是指當(dāng)某個(gè)服務(wù)提供者無法正常為服務(wù)調(diào)用者提供服務(wù)時(shí)永乌,比如請(qǐng)求超時(shí)钝的、服務(wù)異常等翁垂,為了防止整個(gè)系統(tǒng)出現(xiàn)雪崩效應(yīng),暫時(shí)將出現(xiàn)故障的接口隔離出來,斷絕與外部接口的聯(lián)系尤莺,當(dāng)觸發(fā)熔斷之后够委,后續(xù)一段時(shí)間內(nèi)該服務(wù)調(diào)用者的請(qǐng)求都會(huì)直接失敗,直到目標(biāo)服務(wù)恢復(fù)正常窝爪。

熔斷降級(jí)參考指標(biāo)

服務(wù)降級(jí)需要有一個(gè)參考指標(biāo),一般來說有以下幾種常見方案:
? 平均響應(yīng)時(shí)間:比如1s內(nèi)持續(xù)進(jìn)入5個(gè)請(qǐng)求,對(duì)應(yīng)時(shí)刻的平均響應(yīng)時(shí)間均超過閾值衙伶,那么接下來在一個(gè)固定的時(shí)間窗口內(nèi),對(duì)這個(gè)方法的訪問都會(huì)自動(dòng)熔斷害碾。
? 異常比例:當(dāng)某個(gè)方法每秒調(diào)用所獲得的異呈妇ⅲ總數(shù)的比例超過設(shè)定的閾值時(shí),該資源會(huì)自動(dòng)進(jìn)入降級(jí)狀態(tài)慌随,也就是在接下來的一個(gè)固定時(shí)間窗口中芬沉,對(duì)這個(gè)方法的調(diào)用都會(huì)自動(dòng)返回。
? 異常數(shù)量:和異常比例類似阁猜,當(dāng)某個(gè)方法在指定時(shí)間窗口內(nèi)獲得的異常數(shù)量超過閾值時(shí)會(huì)觸發(fā)熔斷丸逸。

Sentinel

Sentinel是面向分布式服務(wù)架構(gòu)的輕量級(jí)流量控制組件,主要以流量為切入點(diǎn)剃袍,從限流黄刚、流量整形、服務(wù)降級(jí)民效、系統(tǒng)負(fù)載保護(hù)等多個(gè)維度來幫助我們保障微服務(wù)的穩(wěn)定性憔维。

文檔

https://github.com/alibaba/Sentinel/wiki

特性

豐富的應(yīng)用場景:幾乎涵蓋所有的應(yīng)用場景,例如秒殺(即突發(fā)流量控制在系統(tǒng)容量可以承受的范圍)畏邢、消息削峰填谷业扒、集群流量控制等。
? 實(shí)時(shí)監(jiān)控:Sentinel提供了實(shí)時(shí)監(jiān)控功能棵红。開發(fā)者可以在控制臺(tái)中看到接入應(yīng)用的單臺(tái)機(jī)器秒級(jí)數(shù)據(jù)凶赁,甚至500臺(tái)以下規(guī)模的集群匯總運(yùn)行情況。
? 開源生態(tài)支持:Sentinel提供開箱即用的與其他開源框架/庫的整合逆甜,例如與Spring Cloud虱肄、Dubbo、gRPC的整合交煞。開發(fā)者只需要引入相應(yīng)的依賴并進(jìn)行簡單的配置即可快速接入Sentinel咏窿。
? SPI擴(kuò)展點(diǎn)支持:Sentinel提供了SPI擴(kuò)展點(diǎn)支持,開發(fā)者可以通過擴(kuò)展點(diǎn)來定制化限流規(guī)則素征,動(dòng)態(tài)數(shù)據(jù)源適配等需求集嵌。

image.png

組成

Sentinel分為兩個(gè)部分:
? 核心庫(Java客戶端):不依賴任何框架/庫萝挤,能夠運(yùn)行于所有Java運(yùn)行時(shí)環(huán)境,同時(shí)對(duì)Dubbo根欧、Spring Cloud等框架也有較好的支持怜珍。
? 控制臺(tái)(Dashboard):基于Spring Boot開發(fā),打包后可以直接運(yùn)行凤粗,不需要額外的Tomcat等應(yīng)用容器酥泛。

啟動(dòng)控制臺(tái)

官方 GitHub Release 頁面 頁面下載最新版本的控制臺(tái) JAR 包。

啟動(dòng)

java -Dserver.port=10006 -Dcsp.sentinel.dashboard.server=localhost:10006 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard-1.8.1.jar

#ubuntu
nohup java -Dserver.port=10006 -Dcsp.sentinel.dashboard.server=localhost:10006 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard-1.6.2.jar >/dev/null 2> /dev/null &

notice:

n1.jdk環(huán)境必須是JDK1.8及以上嫌拣。
n2.從Sentinel 1.6.0 起柔袁,Sentinel 控制臺(tái)引入基本的 登錄 功能,默認(rèn)用戶名和密碼都是 sentinel异逐。

訪問

image.png

image.png

客戶端接入

pom

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

修改配置文件

在 Nacos 控制臺(tái)修改配置文件捶索,增加對(duì) Sentinel 的支持

spring:
  application:
    name: gulimail-order
  cloud:
    nacos:
      discovery:
        server-addr: xxx.xxx.xx.xx:8848
    sentinel:
      transport:
        dashboard:  xxx.xxx.xx.xx:10006
server:
  port: 9090

修改 api接口

package com.pl.gulimailcart.Interfaces.facade;

import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.pl.configuration.BusinessException.ErrorCodeEnume;
import com.pl.dddgulimail.common.dto.ResponseResult;
import com.pl.gulimailcart.Infrastructure.fallback.OrderFallback;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * <p>
 *
 * @Description: TODO
 * </p>
 * @ClassName CartApi
 * @Author pl
 * @Date 2021/1/20
 * @Version V1.0.0
 */
@Slf4j
@RestController()
@RequestMapping("order")
public class OrderApi {

    @GetMapping("/testFeign")
    public String testFeign() {
        return "cartList";
    }

    @PostMapping("/testSentinel")
    @SentinelResource(value = "testSentinelFallback")
    public ResponseResult testSentinel(String args){
        log.info("輸入?yún)?shù)》》》"+args);
        return new ResponseResult<>(ErrorCodeEnume.SUCCESS.getCode(), ErrorCodeEnume.SUCCESS.getMsg());
    }
}

測試熔斷

image.png

當(dāng)QPS>1時(shí)


image.png

image.png
notice:

n1. 必須至少請(qǐng)求過一次才能在 Sentinel 控制臺(tái)看到對(duì)應(yīng)的服務(wù)
n2.這個(gè)sentinel部署的服務(wù)器必須要和服務(wù)應(yīng)用服務(wù)器之間網(wǎng)絡(luò)是能夠互相連接的,否則sentinel會(huì)連接不上應(yīng)用的服務(wù)器灰瞻,無法監(jiān)控應(yīng)用腥例。
n3.每次重啟項(xiàng)目后,流控規(guī)則清空箩祥。
在實(shí)際應(yīng)用中院崇,大都采用JSON格式的數(shù)據(jù),所以如果希望修改觸發(fā)限流之后的返回結(jié)果形式袍祖,則可以通過自定義限流異常來處理底瓣,比如限流異常和熔斷異常。

限流異常

限流異常專門負(fù)責(zé)處理sentinel限流拋出的異常(BlockException)
定義限流異常處理類

package com.pl.gulimailcart.Infrastructure.sentinel.block;

import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.pl.configuration.BusinessException.ErrorCodeEnume;
import com.pl.dddgulimail.common.dto.ResponseResult;
import lombok.extern.slf4j.Slf4j;

/**
 * <p>
 *
 * @Description: TODO
 * </p>
 * @ClassName OrderBlockHandler
 * @Author pl
 * @Date 2021/3/12
 * @Version V1.0.0
 */
@Slf4j
public class OrderBlockHandler {
    public static ResponseResult<String> testSentinelFallback(String args,BlockException  blockException) {
        return new ResponseResult(ErrorCodeEnume.HTTP_SENTINEL.getCode(),ErrorCodeEnume.HTTP_SENTINEL.getMsg());
    }

}

OrderApi

package com.pl.gulimailcart.Interfaces.facade;

import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.pl.configuration.BusinessException.ErrorCodeEnume;
import com.pl.dddgulimail.common.dto.ResponseResult;
import com.pl.gulimailcart.Infrastructure.sentinel.block.OrderBlockHandler;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * <p>
 *
 * @Description: TODO
 * </p>
 * @ClassName CartApi
 * @Author pl
 * @Date 2021/1/20
 * @Version V1.0.0
 */
@Slf4j
@RestController()
@RequestMapping("order")
public class OrderApi {

    @GetMapping("/testFeign")
    public String testFeign() {
        return "cartList";
    }

    @PostMapping("/testSentinel")
    @SentinelResource(value = "testSentinel",blockHandler = "testSentinelFallback",blockHandlerClass = OrderBlockHandler.class)
    public ResponseResult testSentinel(String args){
        log.info("輸入?yún)?shù)》》》"+args);
        return new ResponseResult<>(ErrorCodeEnume.SUCCESS.getCode(), ErrorCodeEnume.SUCCESS.getMsg());
    }

}
image.png

notice:
n1.blockHandlerClass
blockHandler默認(rèn)需要和原方法寫在一個(gè)類中蕉陋,但是若希望使用其他類的函數(shù)捐凭,可配置 blockHandlerClass ,并指定blockHandlerClass里面的方法凳鬓。

n2.blockHandlerClass中的方法必須是static修飾


image.png

JAVA異常

fallback用于處理java異常
fallback類

package com.pl.gulimailcart.Infrastructure.sentinel.fallback;

import com.pl.configuration.BusinessException.ErrorCodeEnume;
import com.pl.dddgulimail.common.dto.ResponseResult;
import lombok.extern.slf4j.Slf4j;

/**
 * <p>
 *
 * @Description: TODO
 * </p>
 * @ClassName OrderFallback
 * @Author pl
 * @Date 2021/3/12
 * @Version V1.0.0
 */
@Slf4j
public class OrderFallback {

    public static ResponseResult testSentinelFallback(String args,Throwable ex){
        log.warn("Invoke testSentinelFallback: " + ex.getClass().getTypeName());
        ex.printStackTrace();
        log.info("進(jìn)入testSentinelFallback茁肠,輸入?yún)?shù)》》》"+args);
        return new ResponseResult<String>(ErrorCodeEnume.HTTP_FALLBACK.getCode(), ErrorCodeEnume.HTTP_FALLBACK.getMsg(),ex.getMessage());
    }
}

OrderApi

package com.pl.gulimailcart.Interfaces.facade;

import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.pl.configuration.BusinessException.ErrorCodeEnume;
import com.pl.dddgulimail.common.dto.ResponseResult;
import com.pl.gulimailcart.Infrastructure.sentinel.fallback.OrderFallback;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * <p>
 *
 * @Description: TODO
 * </p>
 * @ClassName CartApi
 * @Author pl
 * @Date 2021/1/20
 * @Version V1.0.0
 */
@Slf4j
@RestController()
@RequestMapping("order")
public class OrderApi {

    @GetMapping("/testFeign")
    public String testFeign() {
        return "cartList";
    }
    
    @PostMapping("/testSentinel")
    @SentinelResource(value = "testSentinel",fallback = "testSentinelFallback",fallbackClass = OrderFallback.class)
    public ResponseResult testSentinel(String args){
        log.info("輸入?yún)?shù)》》》"+args);
        int i = 10 / 0;
        return new ResponseResult<>(ErrorCodeEnume.SUCCESS.getCode(), ErrorCodeEnume.SUCCESS.getMsg());
    }

}
image.png

image.png

notice:
n1.fallbackClass中的方法必須是static修飾
n2.如果項(xiàng)目中有配置@ControllerAdvice注解的統(tǒng)一異常處理,則不太需要運(yùn)用fallback屬性

fallback和blockHandler一起使用

package com.pl.gulimailcart.Interfaces.facade;

import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.pl.configuration.BusinessException.ErrorCodeEnume;
import com.pl.dddgulimail.common.dto.ResponseResult;
import com.pl.gulimailcart.Infrastructure.sentinel.block.OrderBlockHandler;
import com.pl.gulimailcart.Infrastructure.sentinel.fallback.OrderFallback;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * <p>
 *
 * @Description: TODO
 * </p>
 * @ClassName CartApi
 * @Author pl
 * @Date 2021/1/20
 * @Version V1.0.0
 */
@Slf4j
@RestController()
@RequestMapping("order")
public class OrderApi {

    @GetMapping("/testFeign")
    public String testFeign() {
        return "cartList";
    }

    @PostMapping("/testSentinel")
    @SentinelResource(value = "testSentinel",fallback = "testSentinelFallback",fallbackClass = OrderFallback.class,blockHandler = "testSentinelFallback",blockHandlerClass = OrderBlockHandler.class)
    public ResponseResult testSentinel(String args){
        log.info("輸入?yún)?shù)》》》"+args);
        int i = 10 / 0;
        return new ResponseResult<>(ErrorCodeEnume.SUCCESS.getCode(), ErrorCodeEnume.SUCCESS.getMsg());
    }

}

FQS<1


image.png

FQS>1


image.png
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末缩举,一起剝皮案震驚了整個(gè)濱河市垦梆,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌仅孩,老刑警劉巖托猩,帶你破解...
    沈念sama閱讀 211,290評(píng)論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異辽慕,居然都是意外死亡京腥,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,107評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門溅蛉,熙熙樓的掌柜王于貴愁眉苦臉地迎上來公浪,“玉大人他宛,你說我怎么就攤上這事∏菲” “怎么了厅各?”我有些...
    開封第一講書人閱讀 156,872評(píng)論 0 347
  • 文/不壞的土叔 我叫張陵,是天一觀的道長晃琳。 經(jīng)常有香客問我讯检,道長,這世上最難降的妖魔是什么卫旱? 我笑而不...
    開封第一講書人閱讀 56,415評(píng)論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮围段,結(jié)果婚禮上顾翼,老公的妹妹穿的比我還像新娘。我一直安慰自己奈泪,他們只是感情好适贸,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,453評(píng)論 6 385
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著涝桅,像睡著了一般拜姿。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上冯遂,一...
    開封第一講書人閱讀 49,784評(píng)論 1 290
  • 那天蕊肥,我揣著相機(jī)與錄音,去河邊找鬼蛤肌。 笑死壁却,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的裸准。 我是一名探鬼主播展东,決...
    沈念sama閱讀 38,927評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼炒俱!你這毒婦竟也來了盐肃?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,691評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤权悟,失蹤者是張志新(化名)和其女友劉穎砸王,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體僵芹,經(jīng)...
    沈念sama閱讀 44,137評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡处硬,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,472評(píng)論 2 326
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了拇派。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片荷辕。...
    茶點(diǎn)故事閱讀 38,622評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡凿跳,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出疮方,到底是詐尸還是另有隱情控嗜,我是刑警寧澤,帶...
    沈念sama閱讀 34,289評(píng)論 4 329
  • 正文 年R本政府宣布骡显,位于F島的核電站疆栏,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏惫谤。R本人自食惡果不足惜壁顶,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,887評(píng)論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望溜歪。 院中可真熱鬧若专,春花似錦、人聲如沸蝴猪。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,741評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽自阱。三九已至嚎莉,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間沛豌,已是汗流浹背趋箩。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評(píng)論 1 265
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留琼懊,地道東北人阁簸。 一個(gè)月前我還...
    沈念sama閱讀 46,316評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像哼丈,于是被迫代替她去往敵國和親启妹。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,490評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容