Spring Cloud Alibaba:Sentinel實現(xiàn)熔斷與限流

Spring Cloud Alibaba:Sentinel實現(xiàn)熔斷與限流

Spring Cloud Alibaba 致力于提供微服務開發(fā)的一站式解決方案塑娇,Sentinel 作為其核心組件之一澈侠,具有熔斷與限流等一系列服務保護功能,本文將對其用法進行詳細介紹埋酬。

Sentinel簡介

隨著微服務的流行哨啃,服務和服務之間的穩(wěn)定性變得越來越重要。 Sentinel 以流量為切入點写妥,從流量控制拳球、熔斷降級、系統(tǒng)負載保護等多個維度保護服務的穩(wěn)定性珍特。

Sentinel具有如下特性:

豐富的應用場景:承接了阿里巴巴近 10 年的雙十一大促流量的核心場景祝峻,例如秒殺,可以實時熔斷下游不可用應用扎筒;

完備的實時監(jiān)控:同時提供實時的監(jiān)控功能莱找。可以在控制臺中看到接入應用的單臺機器秒級數(shù)據(jù)嗜桌,甚至 500 臺以下規(guī)模的集群的匯總運行情況奥溺;

廣泛的開源生態(tài):提供開箱即用的與其它開源框架/庫的整合模塊,例如與 Spring Cloud骨宠、Dubbo浮定、gRPC 的整合;

完善的 SPI 擴展點:提供簡單易用层亿、完善的 SPI 擴展點壶唤。您可以通過實現(xiàn)擴展點,快速的定制邏輯棕所。

安裝Sentinel控制臺

Sentinel控制臺是一個輕量級的控制臺應用闸盔,它可用于實時查看單機資源監(jiān)控及集群資源匯總,并提供了一系列的規(guī)則管理功能琳省,如流控規(guī)則迎吵、降級規(guī)則、熱點規(guī)則等针贬。

我們先從官網下載Sentinel击费,這里下載的是sentinel-dashboard-1.6.3.jar文件,下載地址:https://github.com/alibaba/Sentinel/releases

下載完成后在命令行輸入如下命令運行Sentinel控制臺:

java -jar sentinel-dashboard-1.6.3.jarCopy to clipboardErrorCopied

Sentinel控制臺默認運行在8080端口上桦他,登錄賬號密碼均為sentinel蔫巩,通過如下地址可以進行訪問:http://localhost:8080

Sentinel控制臺可以查看單臺機器的實時監(jiān)控數(shù)據(jù)。

創(chuàng)建sentinel-service模塊

這里我們創(chuàng)建一個sentinel-service模塊,用于演示Sentinel的熔斷與限流功能圆仔。

在pom.xml中添加相關依賴垃瞧,這里我們使用Nacos作為注冊中心,所以需要同時添加Nacos的依賴:

<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-sentinel</artifactId></dependency>Copy to clipboardErrorCopied

在application.yml中添加相關配置坪郭,主要是配置了Nacos和Sentinel控制臺的地址:

server:

? port: 8401

spring:

? application:

? ? name: sentinel-service

? cloud:

? ? nacos:

? ? ? discovery:

? ? ? ? server-addr: localhost:8848 #配置Nacos地址

? ? sentinel:

? ? ? transport:

? ? ? ? dashboard: localhost:8080 #配置sentinel dashboard地址

? ? ? ? port: 8719

service-url:

? user-service: http://nacos-user-service

management:

? endpoints:

? ? web:

? ? ? exposure:

? ? ? ? include: '*'Copy to clipboardErrorCopied

限流功能

Sentinel Starter 默認為所有的 HTTP 服務提供了限流埋點个从,我們也可以通過使用@SentinelResource來自定義一些限流行為。

創(chuàng)建RateLimitController類

用于測試熔斷和限流功能歪沃。

/**

* 限流功能

* Created by macro on 2019/11/7.

*/@RestController@RequestMapping("/rateLimit")publicclassRateLimitController{/**

? ? * 按資源名稱限流嗦锐,需要指定限流處理邏輯

? ? */@GetMapping("/byResource")@SentinelResource(value="byResource",blockHandler="handleException")publicCommonResultbyResource(){returnnewCommonResult("按資源名稱限流",200);}/**

? ? * 按URL限流,有默認的限流處理邏輯

? ? */@GetMapping("/byUrl")@SentinelResource(value="byUrl",blockHandler="handleException")publicCommonResultbyUrl(){returnnewCommonResult("按url限流",200);}publicCommonResulthandleException(BlockExceptionexception){returnnewCommonResult(exception.getClass().getCanonicalName(),200);}}Copy to clipboardErrorCopied

根據(jù)資源名稱限流

我們可以根據(jù)@SentinelResource注解中定義的value(資源名稱)來進行限流操作沪曙,但是需要指定限流處理邏輯奕污。

流控規(guī)則可以在Sentinel控制臺進行配置,由于我們使用了Nacos注冊中心液走,我們先啟動Nacos和sentinel-service菊值;

由于Sentinel采用的懶加載規(guī)則,需要我們先訪問下接口育灸,Sentinel控制臺中才會有對應服務信息腻窒,我們先訪問下該接口:http://localhost:8401/rateLimit/byResource

在Sentinel控制臺配置流控規(guī)則,根據(jù)@SentinelResource注解的value值:

快速訪問上面的接口磅崭,可以發(fā)現(xiàn)返回了自己定義的限流處理信息:

根據(jù)URL限流

我們還可以通過訪問的URL來限流儿子,會返回默認的限流處理信息。

在Sentinel控制臺配置流控規(guī)則砸喻,使用訪問的URL:

多次訪問該接口柔逼,會返回默認的限流處理結果:http://localhost:8401/rateLimit/byUrl

自定義限流處理邏輯

我們可以自定義通用的限流處理邏輯,然后在@SentinelResource中指定割岛。

創(chuàng)建CustomBlockHandler類用于自定義限流處理邏輯:

/**

* Created by macro on 2019/11/7.

*/publicclassCustomBlockHandler{publicCommonResulthandleException(BlockExceptionexception){returnnewCommonResult("自定義限流信息",200);}}Copy to clipboardErrorCopied

在RateLimitController中使用自定義限流處理邏輯:

/**

* 限流功能

* Created by macro on 2019/11/7.

*/@RestController@RequestMapping("/rateLimit")publicclassRateLimitController{/**

? ? * 自定義通用的限流處理邏輯

? ? */@GetMapping("/customBlockHandler")@SentinelResource(value="customBlockHandler",blockHandler="handleException",blockHandlerClass=CustomBlockHandler.class)publicCommonResultblockHandler(){returnnewCommonResult("限流成功",200);}}Copy to clipboardErrorCopied

熔斷功能

Sentinel 支持對服務間調用進行保護愉适,對故障應用進行熔斷操作,這里我們使用RestTemplate來調用nacos-user-service服務所提供的接口來演示下該功能癣漆。

首先我們需要使用@SentinelRestTemplate來包裝下RestTemplate實例:

/**

* Created by macro on 2019/8/29.

*/@ConfigurationpublicclassRibbonConfig{@Bean@SentinelRestTemplatepublicRestTemplaterestTemplate(){returnnewRestTemplate();}}Copy to clipboardErrorCopied

添加CircleBreakerController類维咸,定義對nacos-user-service提供接口的調用:

/**

* 熔斷功能

* Created by macro on 2019/11/7.

*/@RestController@RequestMapping("/breaker")publicclassCircleBreakerController{privateLoggerLOGGER=LoggerFactory.getLogger(CircleBreakerController.class);@AutowiredprivateRestTemplaterestTemplate;@Value("${service-url.user-service}")privateStringuserServiceUrl;@RequestMapping("/fallback/{id}")@SentinelResource(value="fallback",fallback="handleFallback")publicCommonResultfallback(@PathVariableLongid){returnrestTemplate.getForObject(userServiceUrl+"/user/{1}",CommonResult.class,id);}@RequestMapping("/fallbackException/{id}")@SentinelResource(value="fallbackException",fallback="handleFallback2",exceptionsToIgnore={NullPointerException.class})publicCommonResultfallbackException(@PathVariableLongid){if(id==1){thrownewIndexOutOfBoundsException();}elseif(id==2){thrownewNullPointerException();}returnrestTemplate.getForObject(userServiceUrl+"/user/{1}",CommonResult.class,id);}publicCommonResulthandleFallback(Longid){UserdefaultUser=newUser(-1L,"defaultUser","123456");returnnewCommonResult<>(defaultUser,"服務降級返回",200);}publicCommonResulthandleFallback2(@PathVariableLongid,Throwablee){LOGGER.error("handleFallback2 id:{},throwable class:{}",id,e.getClass());UserdefaultUser=newUser(-2L,"defaultUser2","123456");returnnewCommonResult<>(defaultUser,"服務降級返回",200);}}Copy to clipboardErrorCopied

啟動nacos-user-service和sentinel-service服務:

由于我們并沒有在nacos-user-service中定義id為4的用戶,所有訪問如下接口會返回服務降級結果:http://localhost:8401/breaker/fallback/4

{

? ? "data": {

? ? ? ? "id": -1,

? ? ? ? "username": "defaultUser",

? ? ? ? "password": "123456"

? ? },

? ? "message": "服務降級返回",

? ? "code": 200

}Copy to clipboardErrorCopied

由于我們使用了exceptionsToIgnore參數(shù)忽略了NullPointerException惠爽,所以我們訪問接口報空指針時不會發(fā)生服務降級:http://localhost:8401/breaker/fallbackException/2

與Feign結合使用

Sentinel也適配了Feign組件癌蓖,我們使用Feign來進行服務間調用時,也可以使用它來進行熔斷婚肆。

首先我們需要在pom.xml中添加Feign相關依賴:

<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId></dependency>Copy to clipboardErrorCopied

在application.yml中打開Sentinel對Feign的支持:

feign:

? sentinel:

? ? enabled: true #打開sentinel對feign的支持Copy to clipboardErrorCopied

在應用啟動類上添加@EnableFeignClients啟動Feign的功能租副;

創(chuàng)建一個UserService接口,用于定義對nacos-user-service服務的調用:

/**

* Created by macro on 2019/9/5.

*/@FeignClient(value="nacos-user-service",fallback=UserFallbackService.class)publicinterfaceUserService{@PostMapping("/user/create")CommonResultcreate(@RequestBodyUseruser);@GetMapping("/user/{id}")CommonResult<User>getUser(@PathVariableLongid);@GetMapping("/user/getByUsername")CommonResult<User>getByUsername(@RequestParamStringusername);@PostMapping("/user/update")CommonResultupdate(@RequestBodyUseruser);@PostMapping("/user/delete/{id}")CommonResultdelete(@PathVariableLongid);}Copy to clipboardErrorCopied

創(chuàng)建UserFallbackService類實現(xiàn)UserService接口较性,用于處理服務降級邏輯:

/**

* Created by macro on 2019/9/5.

*/@ComponentpublicclassUserFallbackServiceimplementsUserService{@OverridepublicCommonResultcreate(Useruser){UserdefaultUser=newUser(-1L,"defaultUser","123456");returnnewCommonResult<>(defaultUser,"服務降級返回",200);}@OverridepublicCommonResult<User>getUser(Longid){UserdefaultUser=newUser(-1L,"defaultUser","123456");returnnewCommonResult<>(defaultUser,"服務降級返回",200);}@OverridepublicCommonResult<User>getByUsername(Stringusername){UserdefaultUser=newUser(-1L,"defaultUser","123456");returnnewCommonResult<>(defaultUser,"服務降級返回",200);}@OverridepublicCommonResultupdate(Useruser){returnnewCommonResult("調用失敗用僧,服務被降級",500);}@OverridepublicCommonResultdelete(Longid){returnnewCommonResult("調用失敗结胀,服務被降級",500);}}Copy to clipboardErrorCopied

在UserFeignController中使用UserService通過Feign調用nacos-user-service服務中的接口:

/**

* Created by macro on 2019/8/29.

*/@RestController@RequestMapping("/user")publicclassUserFeignController{@AutowiredprivateUserServiceuserService;@GetMapping("/{id}")publicCommonResultgetUser(@PathVariableLongid){returnuserService.getUser(id);}@GetMapping("/getByUsername")publicCommonResultgetByUsername(@RequestParamStringusername){returnuserService.getByUsername(username);}@PostMapping("/create")publicCommonResultcreate(@RequestBodyUseruser){returnuserService.create(user);}@PostMapping("/update")publicCommonResultupdate(@RequestBodyUseruser){returnuserService.update(user);}@PostMapping("/delete/{id}")publicCommonResultdelete(@PathVariableLongid){returnuserService.delete(id);}}Copy to clipboardErrorCopied

調用如下接口會發(fā)生服務降級,返回服務降級處理信息:http://localhost:8401/user/4

{

? ? "data": {

? ? ? ? "id": -1,

? ? ? ? "username": "defaultUser",

? ? ? ? "password": "123456"

? ? },

? ? "message": "服務降級返回",

? ? "code": 200

}Copy to clipboardErrorCopied

使用Nacos存儲規(guī)則

默認情況下责循,當我們在Sentinel控制臺中配置規(guī)則時糟港,控制臺推送規(guī)則方式是通過API將規(guī)則推送至客戶端并直接更新到內存中。一旦我們重啟應用沼死,規(guī)則將消失。下面我們介紹下如何將配置規(guī)則進行持久化崔赌,以存儲到Nacos為例意蛀。

原理示意圖

首先我們直接在配置中心創(chuàng)建規(guī)則,配置中心將規(guī)則推送到客戶端健芭;

Sentinel控制臺也從配置中心去獲取配置信息县钥。

功能演示

先在pom.xml中添加相關依賴:

<dependency><groupId>com.alibaba.csp</groupId><artifactId>sentinel-datasource-nacos</artifactId></dependency>Copy to clipboardErrorCopied

修改application.yml配置文件,添加Nacos數(shù)據(jù)源配置:

spring:

? cloud:

? ? sentinel:

? ? ? datasource:

? ? ? ? ds1:

? ? ? ? ? nacos:

? ? ? ? ? ? server-addr: localhost:8848

? ? ? ? ? ? dataId: ${spring.application.name}-sentinel

? ? ? ? ? ? groupId: DEFAULT_GROUP

? ? ? ? ? ? data-type: json

? ? ? ? ? ? rule-type: flowCopy to clipboardErrorCopied

在Nacos中添加配置:

添加配置信息如下:

[

? ? {

? ? ? ? "resource": "/rateLimit/byUrl",

? ? ? ? "limitApp": "default",

? ? ? ? "grade": 1,

? ? ? ? "count": 1,

? ? ? ? "strategy": 0,

? ? ? ? "controlBehavior": 0,

? ? ? ? "clusterMode": false

? ? }

]Copy to clipboardErrorCopied

相關參數(shù)解釋:

resource:資源名稱慈迈;

limitApp:來源應用若贮;

grade:閾值類型,0表示線程數(shù)痒留,1表示QPS谴麦;

count:單機閾值;

strategy:流控模式伸头,0表示直接匾效,1表示關聯(lián),2表示鏈路恤磷;

controlBehavior:流控效果面哼,0表示快速失敗,1表示Warm Up扫步,2表示排隊等待魔策;

clusterMode:是否集群。

發(fā)現(xiàn)Sentinel控制臺已經有了如下限流規(guī)則:

快速訪問測試接口河胎,可以發(fā)現(xiàn)返回了限流處理信息:

參考資料

Spring Cloud Alibaba 官方文檔:https://github.com/alibaba/spring-cloud-alibaba/wiki

使用到的模塊

springcloud-learning

├── nacos-user-service -- 注冊到nacos的提供User對象CRUD接口的服務

└── sentinel-service -- sentinel功能測試服務

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末闯袒,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子游岳,更是在濱河造成了極大的恐慌搁吓,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,657評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件吭历,死亡現(xiàn)場離奇詭異堕仔,居然都是意外死亡,警方通過查閱死者的電腦和手機晌区,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,889評論 3 394
  • 文/潘曉璐 我一進店門摩骨,熙熙樓的掌柜王于貴愁眉苦臉地迎上來通贞,“玉大人,你說我怎么就攤上這事恼五〔郑” “怎么了?”我有些...
    開封第一講書人閱讀 164,057評論 0 354
  • 文/不壞的土叔 我叫張陵灾馒,是天一觀的道長茎用。 經常有香客問我,道長睬罗,這世上最難降的妖魔是什么轨功? 我笑而不...
    開封第一講書人閱讀 58,509評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮容达,結果婚禮上古涧,老公的妹妹穿的比我還像新娘。我一直安慰自己花盐,他們只是感情好羡滑,可當我...
    茶點故事閱讀 67,562評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著算芯,像睡著了一般柒昏。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上熙揍,一...
    開封第一講書人閱讀 51,443評論 1 302
  • 那天昙楚,我揣著相機與錄音,去河邊找鬼诈嘿。 笑死堪旧,一個胖子當著我的面吹牛,可吹牛的內容都是我干的奖亚。 我是一名探鬼主播淳梦,決...
    沈念sama閱讀 40,251評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼昔字!你這毒婦竟也來了爆袍?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,129評論 0 276
  • 序言:老撾萬榮一對情侶失蹤作郭,失蹤者是張志新(化名)和其女友劉穎陨囊,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體夹攒,經...
    沈念sama閱讀 45,561評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡蜘醋,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,779評論 3 335
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了咏尝。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片压语。...
    茶點故事閱讀 39,902評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡啸罢,死狀恐怖,靈堂內的尸體忽然破棺而出胎食,到底是詐尸還是另有隱情扰才,我是刑警寧澤,帶...
    沈念sama閱讀 35,621評論 5 345
  • 正文 年R本政府宣布厕怜,位于F島的核電站衩匣,受9級特大地震影響,放射性物質發(fā)生泄漏粥航。R本人自食惡果不足惜琅捏,卻給世界環(huán)境...
    茶點故事閱讀 41,220評論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望躁锡。 院中可真熱鬧午绳,春花似錦置侍、人聲如沸映之。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,838評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽杠输。三九已至,卻和暖如春秕衙,著一層夾襖步出監(jiān)牢的瞬間蠢甲,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,971評論 1 269
  • 我被黑心中介騙來泰國打工据忘, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留鹦牛,地道東北人。 一個月前我還...
    沈念sama閱讀 48,025評論 2 370
  • 正文 我出身青樓勇吊,卻偏偏與公主長得像曼追,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子汉规,可洞房花燭夜當晚...
    茶點故事閱讀 44,843評論 2 354