Sentinel在订单大量服务调用的应用场景
Sentinel譯為“哨兵”,顧名思義,面對您后臺的大量服務(wù)/微服務(wù),前置一個哨兵,但面對大量請求時,讓后臺服務(wù)有序被調(diào)用,但某些服務(wù)的不可用時,采用服務(wù)熔斷降級等措施,讓系統(tǒng)仍能平穩(wěn)運行,不至于造成系統(tǒng)雪崩,典型應(yīng)用場景:
image
隨著微服務(wù)的流行,服務(wù)和服務(wù)之間的穩(wěn)定性變得越來越重要。Sentinel 以流量為切入點,從流量控制、熔斷降級、系統(tǒng)負載保護等多個維度保護服務(wù)的穩(wěn)定性。
Sentinel 具有以下特征:
-
豐富的應(yīng)用場景:Sentinel 承接了阿里巴巴近 10 年的雙十一大促流量的核心場景,例如秒殺(即突發(fā)流量控制在系統(tǒng)容量可以承受的范圍)、消息削峰填谷、實時熔斷下游不可用應(yīng)用等。
-
完備的實時監(jiān)控:Sentinel 同時提供實時的監(jiān)控功能。您可以在控制臺中看到接入應(yīng)用的單臺機器秒級數(shù)據(jù),甚至 500 臺以下規(guī)模的集群的匯總運行情況。
-
廣泛的開源生態(tài):Sentinel 提供開箱即用的與其它開源框架/庫的整合模塊,例如與 Spring Cloud、Dubbo、gRPC 的整合。您只需要引入相應(yīng)的依賴并進行簡單的配置即可快速地接入 Sentinel。
-
完善的 SPI 擴展點:Sentinel 提供簡單易用、完善的 SPI 擴展點。您可以通過實現(xiàn)擴展點,快速的定制邏輯。例如定制規(guī)則管理、適配數(shù)據(jù)源等。
Sentinel分為兩部分:
核心庫(Java 客戶端)不依賴任何框架/庫,能夠運行于所有 Java 運行時環(huán)境,同時對 Dubbo / Spring Cloud 等框架也有較好的支持。
控制臺(Dashboard)基于 Spring Boot 開發(fā),打包后可以直接運行,不需要額外的 Tomcat 等應(yīng)用容器,該模塊目前基于SpringBoot運行;
部署
在使用Sentinel之前,我們首先需部署Sentinel Dashborad,下載最新版的Sentinel Dashborad,通過以下命令運行:
?
java -Dserver.port=8088 -jar sentinel-dashboard-1.3.0.jar通過server.port執(zhí)行程序運行端口號,通過http://localhost:8088打開控制臺,如下:
image
至此部署完成,非常簡單!
項目中使用Sentinel
Sentinel針對各個主流框架都提供了適配(包括Servlet,Dubbo,SpringBoot/SpringCloud,gRPC,RocketMQ等),本文以SpringBoot2舉例(通過筆者測試發(fā)現(xiàn),SpringBoot 1.x支持不好,自定義流控規(guī)則不可用),首先我們需要在SpringBoot2的配置文件中指定Sentinel連接的控制臺地址和項目名,即application.yml文件,如下:
?
project:name: 在控制臺顯示的項目名 spring:cloud:sentinel:transport:dashboard: 192.168.1.154:8088在項目中加入依賴:
?
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-alibaba-sentinel</artifactId><version>0.2.0.RELEASE</version> </dependency>啟動SpringBoot2后,可以在簇點鏈路頁面看到項目的各個服務(wù)(首次訪問服務(wù)時會被出現(xiàn)在列表中,這些服務(wù)在Sentinel中被稱為資源),接著,你就可以針對這些資源進行流控,降級,熱點,授權(quán)等操作。
流量控制與規(guī)則擴展
在控制臺可通過流控規(guī)則菜單定義某資源的流控規(guī)則,不過這個定義只在內(nèi)存中,但控制臺重啟后,隨之消失,所以我們一般在項目中通過配置文件來定義流控規(guī)則,編寫一個流控數(shù)據(jù)源,如下:
?
package com.sumscope.study.springboot2.service;import java.net.URLDecoder; import java.util.List;import com.alibaba.csp.sentinel.datasource.Converter; import com.alibaba.csp.sentinel.datasource.ReadableDataSource; import com.alibaba.csp.sentinel.init.InitFunc; import com.alibaba.csp.sentinel.datasource.FileRefreshableDataSource; import com.alibaba.csp.sentinel.property.PropertyListener; import com.alibaba.csp.sentinel.property.SentinelProperty; import com.alibaba.csp.sentinel.slots.block.Rule; import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRule; import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRuleManager; import com.alibaba.csp.sentinel.slots.block.flow.FlowRule; import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager; import com.alibaba.csp.sentinel.slots.system.SystemRule; import com.alibaba.csp.sentinel.slots.system.SystemRuleManager; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.TypeReference; public class FileDataSourceInit implements InitFunc{private Converter<String, List<FlowRule>> flowRuleListParser = source -> JSON.parseObject(source,new TypeReference<List<FlowRule>>() {});private Converter<String, List<DegradeRule>> degradeRuleListParser = source -> JSON.parseObject(source,new TypeReference<List<DegradeRule>>() {});private Converter<String, List<SystemRule>> systemRuleListParser = source -> JSON.parseObject(source,new TypeReference<List<SystemRule>>() {});@Overridepublic void init() throws Exception {ClassLoader classLoader = getClass().getClassLoader();String flowRulePath = URLDecoder.decode(classLoader.getResource("FlowRule.json").getFile(), "UTF-8");String degradeRulePath = URLDecoder.decode(classLoader.getResource("DegradeRule.json").getFile(), "UTF-8");String systemRulePath = URLDecoder.decode(classLoader.getResource("SystemRule.json").getFile(), "UTF-8");// Data source for FlowRuleFileRefreshableDataSource<List<FlowRule>> flowRuleDataSource = new FileRefreshableDataSource<>(flowRulePath, flowRuleListParser);FlowRuleManager.register2Property(flowRuleDataSource.getProperty());// Data source for DegradeRuleFileRefreshableDataSource<List<DegradeRule>> degradeRuleDataSource= new FileRefreshableDataSource<>(degradeRulePath, degradeRuleListParser);DegradeRuleManager.register2Property(degradeRuleDataSource.getProperty());// Data source for SystemRuleFileRefreshableDataSource<List<SystemRule>> systemRuleDataSource= new FileRefreshableDataSource<>(systemRulePath, systemRuleListParser);SystemRuleManager.register2Property(systemRuleDataSource.getProperty());} }然后在項目的resources下新增目錄META-INF\services\com.alibaba.csp.sentinel.init.InitFunc,并填寫以上類的完成類名如com.sumscope.study.springboot2.service.FileDataSourceInit即可,這樣,在您的classpath目錄下通過DegradeRule.json,FlowRule.json,SystemRule.json分別來定義降級規(guī)則,流控規(guī)則和系統(tǒng)規(guī)則,比如我們定義一個流控規(guī)則,讓test資源QPS為1,即1秒鐘最多調(diào)用1次,如下:
?
[{"resource": "test","controlBehavior": 0,"count": 1,"grade": 1,"limitApp": "default","strategy": 0} ]在Java代碼中,通過@SentinelResource("test")來定義服務(wù)對應(yīng)的資源名,如果不指數(shù),URI即為資源名。
熔斷降級
降級規(guī)則定義如下:
image
可基于RT(平均響應(yīng)時間)或異常比例兩種方式來定義,其中RT單位為毫秒。
指定RT時,當資源的平均響應(yīng)時間超過閾值(DegradeRule 中的 count,以 ms 為單位)之后,資源進入準降級狀態(tài)。接下來如果持續(xù)進入 5 個請求,它們的 RT 都持續(xù)超過這個閾值,那么在接下的時間窗口(DegradeRule 中的 timeWindow,以 s 為單位)之內(nèi),對這個方法的調(diào)用都會自動地返回。
指定異常時,當資源的每秒異常總數(shù)占通過總數(shù)的比值超過閾值(DegradeRule 中的 count)之后,資源進入降級狀態(tài),即在接下的時間窗口(DegradeRule 中的 timeWindow,以 s 為單位)之內(nèi),對這個方法的調(diào)用都會自動地返回。
熱點參數(shù)限流
也可對經(jīng)常訪問的數(shù)據(jù)進行限流,如某個商品或某個用戶等,如下圖:
image
Sentinel 利用 LRU 策略,結(jié)合底層的滑動窗口機制來實現(xiàn)熱點參數(shù)統(tǒng)計。LRU 策略可以統(tǒng)計單位時間內(nèi),最近最常訪問的熱點參數(shù),而滑動窗口機制可以幫助統(tǒng)計每個參數(shù)的 QPS,熱點參數(shù)限流目前只支持QPS模式。
黑白名單
可通過定義策略(黑名單或白名單)限定資源的調(diào)用方是否讓其通過,以下是代碼定義白名單規(guī)則:
?
AuthorityRule rule = new AuthorityRule(); rule.setResource("test"); rule.setStrategy(RuleConstant.AUTHORITY_WHITE); rule.setLimitApp("appA,appB"); AuthorityRuleManager.loadRules(Collections.singletonList(rule));實時監(jiān)控
在控制臺我們可以實時看到每個資源的qps情況如下圖:
image
注:其中p_qps是每秒通過的請求數(shù),b_qps是每秒拒絕的請求數(shù)
?
總結(jié)
以上是生活随笔為你收集整理的Sentinel在订单大量服务调用的应用场景的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 为什么选用NACOS
- 下一篇: n2n内网穿透打洞部署全过程 + ngi