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控制台中直接做規則修改。