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