Spring Cloud Alibaba | Sentinel:分散式系統的流量防衛兵動態限流規則
- 2019 年 10 月 3 日
- 筆記
Spring Cloud Alibaba | Sentinel:分散式系統的流量防衛兵動態限流規則
前面幾篇文章較為詳細的介紹了Sentinel的使用姿勢,還沒看過的小夥伴可以訪問以下鏈接查看:
但是依然無法滿足我們日常的生產需要,其中,非常重要的一點就是限流規則的配置是存在當前應用的記憶體中的,每次我們重啟應用以後,我們在Sentinel控制台中配置的規則就丟失了,下面,我們就介紹一下Sentinel規則持久化的方式。
Sentinel為我們提供了兩種方式對規則進行修改:
- 通過 API 直接修改 (loadRules)
- 通過 DataSource 適配不同數據源修改
loadRules() 方法只接受記憶體態的規則對象,但更多時候規則存儲在文件、資料庫或者配置中心當中。DataSource 介面給我們提供了對接任意配置源的能力。相比直接通過 API 修改規則,實現 DataSource 介面是更加可靠的做法。
DataSource 擴展常見的實現方式有:
- 拉模式:客戶端主動向某個規則管理中心定期輪詢拉取規則,這個規則中心可以是 RDBMS、文件,甚至是 VCS 等。這樣做的方式是簡單,缺點是無法及時獲取變更;
- 推模式:規則中心統一推送,客戶端通過註冊監聽器的方式時刻監聽變化,比如使用 Nacos、Zookeeper 等配置中心。這種方式有更好的實時性和一致性保證。
Sentinel 目前支援以下數據源擴展:
- Pull-based: 文件、Consul (since 1.7.0)
- Push-based: ZooKeeper, Redis, Nacos, Apollo
這裡,我們重點介紹一下Sentinel基於Nacos實現動態規則。
1. Sentinel基於Nacos動態規則實戰
1.1 創建子工程sentinel_nacos
工程依賴pom.xml如下:
程式碼清單:Alibaba/sentinel-springcloud-high/sentinel_nacos/pom.xml
***
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>com.alibaba.csp</groupId> <artifactId>sentinel-datasource-nacos</artifactId> </dependency>
1.2 配置文件application.yml如下:
程式碼清單:Alibaba/sentinel-springcloud-high/sentinel_nacos/src/main/resources/application.yml
***
server: port: 10000 spring: application: name: spring-cloud-sentinel-nacos cloud: nacos: discovery: server-addr: 192.168.44.129:8848 sentinel: transport: dashboard: localhost:8080 port: 8720 datasource: ds: nacos: server-addr: 192.168.44.129:8848 dataId: spring-cloud-sentinel-nacos groupId: DEFAULT_GROUP rule-type: flow namespace: 8282c713-da90-486a-8438-2a5a212ef44f
spring.cloud.sentinel.transport.dashboard
:Sentinel控制台的訪問地址。spring.cloud.sentinel.datasource.ds.nacos.server-addr
:nacos的訪問地址。spring.cloud.sentinel.datasource.ds.nacos.dataId
:nacos中存儲規則的groupId。spring.cloud.sentinel.datasource.ds.nacos.groupId
:nacos中存儲規則的dataId。spring.cloud.sentinel.datasource.ds.nacos.rule-type
:用來定義存儲的規則類型,不可為空。spring.cloud.sentinel.datasource.ds.nacos.namespace
:nacos中存儲規則的namespace。
由於版本迭代關係,本示例中的配置資訊不一定適用於所有版本,可以通過分析DataSourcePropertiesConfiguration
、NacosDataSourceProperties
和AbstractDataSourceProperties
這三個配置來得出具體配置內容,會更為準確。
例如,本示例中的配置來源於NacosDataSourceProperties
和AbstractDataSourceProperties
。
NacosDataSourceProperties
源碼如下:
public class NacosDataSourceProperties extends AbstractDataSourceProperties { private String serverAddr; @NotEmpty private String groupId = "DEFAULT_GROUP"; @NotEmpty private String dataId; private String endpoint; private String namespace; private String accessKey; private String secretKey; // 程式碼省略... }
AbstractDataSourceProperties
源碼如下:
public class AbstractDataSourceProperties { @NotEmpty private String dataType = "json"; @NotNull private RuleType ruleType; private String converterClass; @JsonIgnore private final String factoryBeanName; @JsonIgnore private Environment env; }
筆者這裡僅配置一個不可為空並且沒有默認值的ruleType
,有關ruleType
的取值可以查看com.alibaba.cloud.sentinel.datasource.RuleType
,這是一個枚舉類型。
1.3 創建一個介面測試類HelloController.java如下:
程式碼清單:Alibaba/sentinel-springcloud-high/sentinel_nacos/src/main/java/com/springcloud/sentinel_nacos/controller/HelloController.java
***
@RestController public class HelloController { @GetMapping("/hello") public String hello(HttpServletRequest request) { return "Hello, port is: " + request.getLocalPort(); } }
1.4 配置Nacos配置中心
配置內容如圖:
注意其中配置的Data ID和Group要和程式中配置的保持一致。格式選擇JSON,填入的內容如下:
[ { "resource": "/hello", "limitApp": "default", "grade": 1, "count": 1, "strategy": 0, "controlBehavior": 0, "clusterMode": false } ]
可以看到上面配置規則是一個數組類型,數組中的每個對象是針對每一個保護資源的配置對象,每個對象中的屬性解釋如下:
- resource:資源名,即限流規則的作用對象。
- limitApp:流控針對的調用來源,若為 default 則不區分調用來源。
- grade:限流閾值類型,QPS 或執行緒數模式,0代表根據並發數量來限流,1代表根據QPS來進行流量控制。
- count:限流閾值
- strategy:判斷的根據是資源自身,還是根據其它關聯資源 (refResource),還是根據鏈路入口
- controlBehavior:流控效果(直接拒絕 / 排隊等待 / 慢啟動模式)
- clusterMode:是否為集群模式
1.5 測試
正常啟動子工程,打開瀏覽器訪問幾次http://localhost:10000/hello ,速度快一些可以發現已經限流了,限流後頁面顯示如下:
Blocked by Sentinel (flow limiting)
正面限流配置成功,這時我們打開Sentinel控制台,看一下流量規則限制,已經有一條數據了,是我們在Nacos中配置的數據,如圖:
注意:
在Sentinel動態規則整合了Nacos以後,對於修改介面流量控制就有兩個地方了,一個是Sentinel的控制台,還有一個是Nacos的控制台。
但是要謹記,在當前版本中,在Sentinel控制台中修改了規則,將不會同步至Nacos的配置中心,而在Nacos中修改了配置規則,則會通過在客戶端的Listener來是同步Sentinel控制台。所以,在整合了Nacos做動態規則存儲後需要注意兩點:
- Sentinel控制台中修改規則:僅存在於服務的記憶體中,不會修改Nacos中的配置值,重啟後恢復原來的值。
- Nacos控制台中修改規則:服務的記憶體中規則會更新,Nacos中持久化規則也會更新,重啟後依然保持。
建議各位堵住最好在Nacos控制台做規則的修改操作,盡量避免直接在Sentinel控制台中直接做規則修改。