sentinel是今年阿里開源的高可用防禦的流量管理框架。html
git地址:https://github.com/alibaba/Sentinel前端
wiki:https://github.com/alibaba/Sentinel/wikijava
FAQ:https://github.com/alibaba/Sentinel/wiki/FAQgit
--------------------------------------------------------------------------------------------------------------------------------------------------------github
[學習]sentinel中的DatatSource(一) ReadableDataSource數據庫
在上一篇中學習了sentinel中的ReadableDataSource,本篇來學習和梳理下WritableDataSource。json
--------------------------------------------------------------------------------------------------------------------------------------------------------瀏覽器
WritableDataSource顧名思義,是可寫的數據源,在sentinel-datasource-extension模塊下,com.alibaba.csp.sentinel.datasource包:併發
接口有兩個方法:框架
write是將數據寫到數據源中,進行保存;
close是關閉datasource相關的資源。
該包下提供了一個實現類,FileWritableDataSource,使用文件做爲數據源。
先看屬性,定義了
configEncoder用於將T類型轉換爲String類型;
file用於肯定數據源文件;
charset字符集用於區分編碼格式,默認是UTF-8;
lock用戶寫文件時加鎖,避免併發寫問題;
接着是構造函數,能夠看到提供了3種重載來方便構造;
在最後實際調用的構造函數中,首先驗證了參數合法性,包括:文件非空、不是目錄、轉換器和字符集非空;而後將參數保存在類的屬性中;
最後是實現WritableDataSource接口的兩個方法:
write方法首先經過lock加鎖,調用轉換器configEncoder的convert方法將T類型轉換爲String,再調用java io將String寫入文件,最後釋放鎖;
close方法中,因沒有釋放的資源,不做任何處理。
在IDEA裏,按住Ctrl鍵,點擊FileWritableDataSource<T>類名,發現FileDataSourceInit類用到了它
該類位於sentinel-demo模塊下的sentinel-demo-dynamic-file-rule,是一個FileDatasource的demo演示:
咱們看到FileDataSourceInit實現了InitFunc接口,這是Sentinel 的 InitFunc SPI 擴展接口。
參考:https://github.com/alibaba/Sentinel/wiki/動態規則擴展
看代碼中如何構造FileWritableDataSource的:
flowRulePath是流控規則文件的路徑;
encodeJson是前文提到的轉換器,這裏用了jdk1.8雙冒號的語法,使用用fastjson提供的靜態方法JSON.toJSONString將List<Rule>轉換爲String;
注意到,構造好WritableDataSource後,用WritableDataSourceRegistry.registerFlowDataSource(wds)進行了註冊;
WritableDataSourceRegistry類位於sentinel-transport-common模塊裏,裏面保存了flow、degrade、system、authority四種規則的WritableDataSource,並提供了註冊(register)和獲取(get)的靜態方法;
一樣可使用剛纔Ctrl+左鍵的方式繼續跟下去,找到它的調用。限於篇幅就暫不展開了。有興趣的讀者能夠試試。
WritableDataSource用於寫規則數據至數據源,跟sentinel-dashborad結合使用。
以流控規則爲例,數據流轉大體以下:
1. 在sentinel-dashboard界面中新增、修改、刪除流控規則
2.dashborad中FlowController接收前端界面請求,先調用InMemFlowRuleStore的repository將內存中的數據更新,而後用SentinelApiClient經過http請求的方式與sentinel客戶端(接入sentinel的應用)進行交互
http://ip:port/setRulesPath?type=flowRuleType&data=xxx
3.sentinel客戶端的ModifyRulesCommandHandler處理請求,經過FlowRuleManager.loadRules(flowRules)從新加載規則,再調用已註冊的WritableDataSource的write方法,將規則數據寫至數據源
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
咱們來看看FileDataSource的demo。
FileDataSourceDemo類listenRules方法,構造了3種規則的FileRefreshableDataSource。
FlowQpsRunner類中的資源名稱爲"abc",
在FlowRule.json文件中有一條該資源的流控規則:
能夠看到是controlBehavior=0默認快速失敗方式,grade=1的QPS方法,count=20.0。 該規則表示超過20QPS/秒進行快速失敗限流。
運行FileDataSourceDemo類的main方法:
能夠看到,經過的qps大體在20左右。
前文提到FileWritableDataSource在FileDataSourceInit類中構造。demo中使用了FileRefreshableDataSource讀取規則。
咱們來把FileWritableDataSource用起來試試。
參考官方文檔,在demo工程的resources目錄下,增長META-INF/services目錄結構,增長com.alibaba.csp.sentinel.init.InitFunc文件 // 能夠從sentinel-transport-simple-http模塊中的resources目錄拷貝
文件內容爲com.alibaba.csp.sentinel.demo.file.rule.FileDataSourceInit
因FileDataSourceInit中已經有ReadableDataSource和WritableDataSource構造了,所以咱們將FileDataSourceDemo中加載規則的代碼註釋掉;
增長啓動參數-Dproject.name=FileDataSourceDemo -Dcsp.sentinel.dashboard.server=localhost:8080;
把dashboard先啓起來;
demo中的FlowQpsRunner類,運行是100秒,爲了有更充裕的時間觀察、debug而程序不退出,咱們把它改大一點:
FileDataSourceInit加載的文件路徑是用戶目錄下的/sentinel/rules/flowRule.json
所以咱們把目錄結構按此建好,拷貝resources下的FlowRule.json文件過去
而後運行FileDataSourceDemo,啓動後觀察console輸出:
因爲FlowRule.json文件中abc資源的count=20,能夠看到pass的qps在20左右;
瀏覽器打開控制檯http://localhost:8080,在機器列表菜單下,能夠看到應用已經在列表中顯示
點擊流控規則,
能夠看到資源abc的規則閾值設置爲20,點擊編輯把閾值改爲5,點保存;
再觀察console的輸出:
pass的qps已經從20,降到了5左右;
打開用戶目錄下的/sentinel/rules/flowRule.json文件,能夠看到json中的abc資源的count已變成了5;
因而可知,FileWritableDataSource是生效了的;
而且這種方式結合控制檯能夠很方便的在界面配置規則,並持久化到文件。
打開用戶目錄/logs/csp中的最近修改的record.log.pidxxxx文件:
2018-09-13 13:13:25 [FlowRuleManager] Flow rules received: {abc1=[FlowRule{resource=abc1, limitApp=default, grade=1, count=20.0, strategy=0, refResource=null, controlBehavior=0, warmUpPeriodSec=10, maxQueueingTimeMs=500, controller=com.alibaba.csp.sentinel.slots.block.flow.controller.DefaultController@301ad2}], abc=[FlowRule{resource=abc, limitApp=default, grade=1, count=5.0, strategy=0, refResource=null, controlBehavior=0, warmUpPeriodSec=10, maxQueueingTimeMs=500, controller=com.alibaba.csp.sentinel.slots.block.flow.controller.DefaultController@150daa0}]}
2018-09-13 13:13:25 [FileWritableDataSource] Writing to file C:\Users\five\sentinel\rules\flowRule.json: [{"controlBehavior":0,"count":20.0,"grade":1,"limitApp":"default","maxQueueingTimeMs":500,"resource":"abc1","strategy":0,"warmUpPeriodSec":10},{"controlBehavior":0,"count":5.0,"grade":1,"limitApp":"default","maxQueueingTimeMs":500,"resource":"abc","strategy":0,"warmUpPeriodSec":10}]
看到修改的規則已被FlowRuleManager從新加載,而且經過FileWritableDataSource寫至到了flowRule.json文件:)
--------------------------------------------------------------------------------------------------------------------------------------------------------
總結:
1. WritableDataSource提供了咱們將sentinel內存中規則寫回數據源的接口,控制檯編輯規則時,除了經過http方式更新sentinel客戶端的規則,還會調用WritableDataSourceRegistry註冊的WritableDataSource的write方法;
2. 如Jdbc數據庫、File文件等可寫入的數據源,實現定製的WritableDataSource接口,能夠方便咱們配合控制檯界面來配置規則;
3. 不一樣類型的數據源,根據Pull、Push模式,對控制檯、ReadableDataSource、WritableDataSource可根據須要進行不一樣的定製擴展。
--------------------------------------------------------------------------------------------------------------------------------------------------------
思考:
1.WritableDataSource的write默認是全量更新數據,單個應用規則多時可能有性能問題,考慮如何區分出有變更的增量規則,將增量數據寫入數據源;
2.sentinel的控制檯界面,規則是按應用、ip、端口來單獨配置的,設計持久化結構時須要考慮。
--------------------------------------------------------------------------------------------------------------------------------------------------------
參考: