微服務熔斷神器 Sentinel 重啟后限流規則失效了!一招教你用 Nacos 實現永久存儲
一、背景介紹
在上一篇文章中,我們詳細介紹了如何使用 Sentinel 來實現服務的限流和降級操作,同時也遺留的一個問題:如何將 Sentinel 規則數據進行持久化存儲?
今天通過這篇文章,并結合之前的知識,我們一起來了解一下 Sentinel 數據持久化存儲思路。
二、方案實踐
在上篇文章中,我們簡單介紹了 Sentinel 控制臺的使用,當我們在控制臺對某個客戶端的資源設置相關規則時,Sentinel 會自動將這些規則推送給客戶端并保存到內存中。
也就是說,當我們重啟客戶端的時候,這些規則也會丟失。有沒有一種辦法將 Sentinel 規則數據持久化存儲。
答案也是肯定的,Sentinel 支持多種數據源存儲,例如 ZooKeeper,Nacos,Apollo。這里我們介紹一下使用 Nacos 的配置中心來存儲 Sentinel 相關的規則數據。
服務之間的交互邏輯,可以用如下圖來概括。
圖片
具體實現步驟如下!
2.1、創建限流規則配置文件
首先,在 nacos 創建一個限流規則配置文件,具體示例如下。
圖片
其中DataId值為alibaba-sentinel-client-rules,所屬Group值為SENTINEL_GROUP;配置格式選擇JSON,并在配置內容中填入下面的內容:
[
{
"resource": "hello",
"limitApp": "default",
"grade": 1,
"count": 5,
"strategy": 0,
"controlBehavior": 0,
"clusterMode": false
}
]
可以看到上面配置規則是一個數組類型,數組中的每個對象是針對每一個要保護資源的配置信息,每個對象中的屬性作用如下:
- resource:資源名,即限流規則的作用對象
- limitApp:流控針對的調用來源,若為default則不區分調用來源
- grade:限流閾值類型;0 代表根據線程數來限流,1 代表根據 QPS 來限流
- count:限流閾值
- strategy:調用關系限流策略
- controlBehavior:流量控制效果(直接拒絕、Warm Up、勻速排隊)
- clusterMode:是否為集群模式
實際上還有非常多可配置選項和規則,這里為了方便演示,只做簡單的配置介紹。詳細的配置參數可以參考 sentinel 官網文檔。
2.2、sentinel 客戶端添加數據源
客戶端要想使用 Nacos 中配置的限流規則數據,此時需要對應用進行一些改造,具體實現步驟如下。
首先,在應用引入nacos相關依賴,示例如下:
<dependencies>
<!-- SpringBoot web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 服務限流和熔斷處理:sentinel -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<!--以nacos作為sentinel數據源的依賴-->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
</dependency>
</dependencies>
這里的sentinel-datasource-nacos不需要填寫版本號,因為在spring-cloud-starter-alibaba-sentinel已經配置了。
然后,在application.properties文件中配置nacos數據源,示例如下:
spring.application.name=alibaba-sentinel-client
server.port=8002
# sentinel dashboard
spring.cloud.sentinel.transport.dashboard=localhost:8080
# 配置sentinel數據源
spring.cloud.sentinel.datasource.ds2.nacos.server-addr=127.0.0.1:8848
spring.cloud.sentinel.datasource.ds2.nacos.data-id=alibaba-sentinel-client-rules
spring.cloud.sentinel.datasource.ds2.nacos.group-id=SENTINEL_GROUP
spring.cloud.sentinel.datasource.ds2.nacos.data-type=json
spring.cloud.sentinel.datasource.ds2.nacos.rule-type=flow
2.3、服務測試
最后啟動服務,再次訪問 Sentinel 控制臺,點擊流控規則-》回到單機頁面,可以看到剛剛創建的限流規則信息。
圖片
實際上,Sentinel Dashboard 會收集客戶端中定義的數據源,然后向目標數據源拉取相關的限流規則信息,因此可以看到在 Nacos 中配置的數據。
將 Nacos 中的限流規則閥值改成1,看看是否能實時同步到 Sentinel 控制臺。
圖片
再次刷新流控規則頁面,可以看到如下信息,限流規則閥值改成1。
圖片
最后再次訪問客戶端的http://127.0.0.1:8002/hello接口,限流效果非常明顯。
圖片
三、反向修改同步到 Nacos
看完以上的案例之后,可能有的同學又會發出疑問,自己在 Sentinel Dashboard 中修改了限流規則,但是沒有同步到 Nacos 配置中心,當客戶端服務重啟之后,還是原來的配置規則,請問怎么實現 Sentinel Dashboard 與 Nacos 的雙向數據同步?
很遺憾的告訴大家,目前 Sentinel Dashboard 并沒有直接將數據同步到 Nacos 的配置,要想實現這個功能得自己修改源代碼,然后重新編譯打包部署。
實現過程有些復雜,在此我以流控規則的數據同步為例,向大家介紹其改造的過程,其他的規則改造邏輯也類似。
3.1、下載源碼
首先,訪問 Sentinel 官網倉庫地址,將源代碼下載來了,然后導入到 IDEA 中。
然后,切換到與應用匹配的版本號,例如本案例中使用的 Sentinel 的版本號是1.7.2,使用 IDEA 自帶的 git 工具切換到目標分支。
圖片
接著,打開sentinel-dashboard模塊中的pom.xml,將sentinel-datasource-nacos的scope標簽注釋掉。
圖片
3.2、修改流控規則源碼
3.2.1、創建數據查詢和同步服務
首先,打開test文件夾下的com.alibaba.csp.sentinel.dashboard.rule.nacos包,找到如下四個文件。
圖片
將nacos包下的四個文件,拷貝到main文件夾下的com.alibaba.csp.sentinel.dashboard.rule包中。
圖片
然后,打開NacosConfigUtil類,其中有兩個重要的參數需要特別注意,在 Nacos 中創建配置時會用到。
圖片
- GROUP_ID:代表配置文件所屬分組,對應 Nacos 中配置規則所屬的Group
- FLOW_DATA_ID_POSTFIX:代表流控規則配置后綴名稱,例如客戶端的應用名稱為alibaba-sentinel-client,那么 Sentinel Dashboard 生成的配置規則文件名為alibaba-sentinel-client-flow-rules,對應 Nacos 中配置規則所屬的DataId
最后,打開NacosConfig,填寫 Nacos 配置中心相關的地址信息,以便與 Nacos 進行數據同步。
圖片
3.2.2、修改流控規則接口
打開controller文件夾,找到FlowControllerV2,它是一個流控規則備用接口類,將上文中FlowRuleNacosProvider和FlowRuleNacosPublisher類注入到FlowControllerV2中,并替換到原來的接口。
圖片
// 修改前的代碼
@Autowired
@Qualifier("flowRuleDefaultProvider")
private DynamicRuleProvider<List<FlowRuleEntity>> ruleProvider;
@Autowired
@Qualifier("flowRuleDefaultPublisher")
private DynamicRulePublisher<List<FlowRuleEntity>> rulePublisher;
// 修改后的代碼
@Autowired
private FlowRuleNacosProvider ruleProvider;
@Autowired
private FlowRuleNacosPublisher rulePublisher;
3.2.3、修改流控規則頁面
在webapp文件夾下,找到sidebar.html文件,它是一個左側菜單頁面,找到流控規則按鈕代碼,將dashboard.flowV1修改成dashboard.flow。
圖片
<!--修改前的代碼-->
<li ui-sref-active="active">
<a ui-sref="dashboard.flowV1({app: entry.app})">
<i class="glyphicon glyphicon-filter"></i> 流控規則
</a>
</li>
<!--修改后的代碼-->
<li ui-sref-active="active">
<a ui-sref="dashboard.flow({app: entry.app})">
<i class="glyphicon glyphicon-filter"></i> 流控規則
</a>
</li>
按住ctrl并點擊dashboard.flow,可以跳轉到對應的 JS 詳情頁面。
圖片
圖片
可以清晰的看到dashboard.flow對應的Controller接口類為FlowControllerV2,當我們在控制臺修改流控規則時,就會利用上文的 Nacos 服務類自動同步到 Nacos 配置中心。
3.2.4、重新打包部署服務
最后將sentinel-dashboard工程執行打包編譯操作。
mvn clean package
獲取最新的sentinel-dashboard.jar,然后按照上文介紹的方式重新部署服務。
如果是本地調試,也可以直接通過 IDEA 啟動 Sentinel Dashboard 服務。
3.3、在 Nacos 創建配置文件
首先 Sentinel Dashboard 是無法自動在 Nacos 中幫我們創建配置規則文件的,因此需要我們手工創建配置規則。
根據上文的配置信息,我們可以在 Nacos 中創建一個DataId為alibaba-sentinel-client-flow-rules,Group為SENTINEL_GROUP的限流配置規則,具體內容如下:
圖片
3.4、客戶端添加數據源
重新打開alibaba-sentinel-client工程,根據最新的限流配置規則文件,重新配置 sentinel 數據源,示例如下:
spring.application.name=alibaba-sentinel-client
server.port=8002
# sentinel dashboard
spring.cloud.sentinel.transport.dashboard=localhost:8080
# 配置sentinel數據源
spring.cloud.sentinel.datasource.ds2.nacos.server-addr=127.0.0.1:8848
spring.cloud.sentinel.datasource.ds2.nacos.data-id=alibaba-sentinel-client-flow-rules
spring.cloud.sentinel.datasource.ds2.nacos.group-id=SENTINEL_GROUP
spring.cloud.sentinel.datasource.ds2.nacos.data-type=json
spring.cloud.sentinel.datasource.ds2.nacos.rule-type=flow
然后將alibaba-sentinel-client服務進行重啟。
3.5、服務測試
再次訪問 Sentinel 控制臺,點擊流控規則,可以看到從 Nacos 配置中心獲取的最新限流規則數據。
圖片
點擊編輯,將當前限流規則的閥值修改成5并保存。
圖片
回到 Nacos 配置中心控制臺,點擊alibaba-sentinel-client-flow-rules配置,可以看到詳情中的限流規則閥值被改成最新值。
圖片
到這里,Sentinel Dashboard 和 Nacos 之間的數據雙向同步就完成了,當在 Sentinel Dashboard 中新增流控規則的時候也會同步到 Nacos 中,大家也可以自信嘗試。
其它的規則改造過程也基本類似,先改服務接口,再改前端頁面邏輯,確保 Nacos 中的配置名稱與 Sentinel Dashboard 生成的配置規則名稱一致,基本上就沒什么問題了。
四、小結
最后總結一下,在實際的開發過程中,我們可以利用 Nacos 的配置中心功能,集中存儲 Sentinel 各種規則數據,依次來實現數據的持久化存儲。目前 Sentinel 控制臺并沒有直接支持將修改后的數據同步到 Nacos 的配置,因此需要修改源代碼進行重新編譯打包部署。
本文內容比較多,如果有描述不對的地方,歡迎大家在評論區留言指出!
五、參考
1、https://sca.aliyun.com/docs/2.2.x/user-guide/sentinel/overview
2、https://developer.aliyun.com/article/783342
3、https://sentinelguard.io/zh-cn/docs/introduction.html