摘要:這樣做的方式是簡單,缺點是無法及時獲取變更推模式規則中心統一推送,客戶端通過注冊監聽器的方式時刻監聽變化,比如使用等配置中心。
在前面的學習過程中,Sentinel 的規則,也就是我們之前定義的限流規則,是通過代碼的方式定義好的。這是初始化時需要做的事情,Sentinel 提供了基于API的方式修改規則:
FlowRuleManager.loadRules(Listrules); // 修改流控規則 DegradeRuleManager.loadRules(List rules); // 修改降級規則 SystemRuleManager.loadRules(List rules); // 修改系統規則 AuthorityRuleManager.loadRules(List rules); // 修改授權規則
當我們接入了控制臺后,可以通過控制臺進行規則的動態修改,問題是當應用程序重啟后規則信息就會恢復到初始化的階段,也就是說后面修改的值會丟失,因為規則信息都是存儲在應用的內存中。
為了解決這個問題Sentinel 提供了DataSource 擴展的功能,官方推薦通過控制臺設置規則后將規則推送到統一的規則中心,客戶端實現 ReadableDataSource 接口端監聽規則中心實時獲取變更,流程如下:
擴展的常見方式有推和拉兩種模式:
拉模式:客戶端主動向某個規則管理中心定期輪詢拉取規則,這個規則中心可以是 RDBMS、文件,甚至是 VCS 等。這樣做的方式是簡單,缺點是無法及時獲取變更;
推模式:規則中心統一推送,客戶端通過注冊監聽器的方式時刻監聽變化,比如使用?Nacos、Apollo、Zookeeper 等配置中心。這種方式有更好的實時性和一致性保證。
今天我們主要是講如何使用 Apollo 來配置規則進行持久化,Apollo是攜程開源的配置中心,非常好用
Github地址:https://github.com/ctripcorp/...
在我的書中也有對Apollo使用的詳細介紹,等出版了再通知大家。
首先集成需要的依賴:
com.alibaba.csp sentinel-datasource-apollo 1.4.1
然后創建 ApolloDataSource 并將其注冊至對應的 RuleManager 上即可。比如:
private static void loadRules() { // Apollo 中的應用名稱,自己定義的 String appId = "SampleApp"; // Apollo 的地址 String apolloMetaServerAddress = "http://localhost:8080"; System.setProperty("app.id", appId); System.setProperty("apollo.meta", apolloMetaServerAddress); // 指定環境 System.setProperty("env", "DEV"); // Apollo 的命名空間 String namespaceName = "application"; // 限流規則的Key, 在Apollo中用此Key String flowRuleKey = "flowRules"; // 限流規則的默認值 String defaultFlowRules = "[]"; // 注冊數據源 ReadableDataSource> flowRuleDataSource = new ApolloDataSource<>(namespaceName, flowRuleKey, defaultFlowRules, source -> JSON.parseObject(source, new TypeReference >() { })); FlowRuleManager.register2Property(flowRuleDataSource.getProperty()); }
到此為止配置就結束了,詳細的解釋我都寫了注釋哈。官方文檔也是這么寫的,問題是如果你剛接觸會一頭霧水的,為什么?
你不知道在Apollo中怎么配置啊,我們講的就是說可以用Apollo來作為存儲,持久化規則,那么規則怎么配置就需要我們自己去想。
我也是通過看源碼才知道怎么去配置的,帶著大家一起來看源碼吧!
主要就是new ApolloDataSource這里,參數都是通過這里傳進去的
public ApolloDataSource(String namespaceName, String flowRulesKey, String defaultFlowRuleValue, Converterparser) { super(parser); Preconditions.checkArgument(!Strings.isNullOrEmpty(namespaceName), "Namespace name could not be null or empty"); Preconditions.checkArgument(!Strings.isNullOrEmpty(flowRulesKey), "FlowRuleKey could not be null or empty!"); this.flowRulesKey = flowRulesKey; this.defaultFlowRuleValue = defaultFlowRuleValue; this.config = ConfigService.getConfig(namespaceName); initialize(); RecordLog.info(String.format("Initialized rule for namespace: %s, flow rules key: %s", namespaceName, flowRulesKey)); }
這邊就是對傳入的參數賦值,然后看下面這行:
this.config = ConfigService.getConfig(namespaceName);
這就是通過命名空間去Apollo中獲取配置,獲取完后就執行初始化
private void initialize() { initializeConfigChangeListener(); loadAndUpdateRules(); }
initializeConfigChangeListener是初始化配置的監聽器,當配置發生修改時會進入該監聽器,也就是說在這個監聽器里需要監聽配置的修改,然后更新規則
private void initializeConfigChangeListener() { config.addChangeListener(new ConfigChangeListener() { @Override public void onChange(ConfigChangeEvent changeEvent) { ConfigChange change = changeEvent.getChange(flowRulesKey); //change is never null because the listener will only notify for this key if (change != null) { RecordLog.info("[ApolloDataSource] Received config changes: " + change.toString()); } loadAndUpdateRules(); } }, Sets.newHashSet(flowRulesKey)); }
loadAndUpdateRules就是更新規則的邏輯了
private void loadAndUpdateRules() { try { T newValue = loadConfig(); if (newValue == null) { RecordLog.warn("[ApolloDataSource] WARN: rule config is null, you may have to check your data source"); } getProperty().updateValue(newValue); } catch (Throwable ex) { RecordLog.warn("[ApolloDataSource] Error when loading rule config", ex); } }
那么配置是怎么來的呢,請看loadConfig
@Override public T loadConfig() throws Exception { return loadConfig(readSource()); } public T loadConfig(S conf) throws Exception { T value = parser.convert(conf); return value; }
readSource就是獲取我們配置的flowRulesKey的值,那么配置其實就是一個字符串,然后下面通過Json轉換
public String readSource() throws Exception { return config.getProperty(flowRulesKey, defaultFlowRuleValue); }
我們再返過來看看注冊的代碼:
// 注冊數據源 ReadableDataSource> flowRuleDataSource = new ApolloDataSource<>(namespaceName, flowRuleKey, defaultFlowRules, source -> JSON.parseObject(source, new TypeReference >() { }));
重點是ource -> JSON.parseObject(source, new TypeReference>()這行,這不就是轉換成List
我們配置一個試試看:
flowRules = [{"grade":1,"count":11,"resource":"HelloWorld"}]
點擊保存并且發布,可以在initializeConfigChangeListener里面設置一個斷點,你會發現,當發布配置之后,這邊馬上就會進來,然后執行其他的邏輯,到此為止整個流程結束。
歡迎加入我的知識星球,一起交流技術,免費學習猿天地的課程(http://cxytiandi.com/course) PS:目前星球中正在星主的帶領下組隊學習Sentinel,等你哦!文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/74014.html
摘要:在之前的兩篇教程中我們分別介紹了如何將的限流規則存儲到和中。本文以存儲為例,下一篇介紹的改在示例。但是由于考慮到與的結合使用,略作修改。 在之前的兩篇教程中我們分別介紹了如何將Sentinel的限流規則存儲到Nacos和Apollo中。同時,在文末的思考中,我都指出了這兩套整合方案都存在一個不足之處:不論采用什么配置中心,限流規則都只能通過Nacos界面或Apollo界面來完成修改才能...
摘要:前面我們都是直接通過集成的依賴,通過編碼的方式配置規則等。對于集成到中阿里已經有了一套開源框架,就是用于將一系列的框架成功的整合到中。但這也是在學習過程中遇到的一個問題,還是得通過調試源碼的方式去發現問題的原因。 前面我們都是直接通過集成sentinel的依賴,通過編碼的方式配置規則等。對于集成到Spring Cloud中阿里已經有了一套開源框架spring-cloud-alibaba...
摘要:改造背景前面我們講解了如何對接來持久化限流的規則,對接后可以直接通過的后臺進行規則的修改,推送到各個客戶端實時生效。因此推送規則正確做法應該是配置中心控制臺控制臺配置中心數據源,而不是經數據源推送至配置中心。 改造背景 前面我們講解了如何對接Apollo來持久化限流的規則,對接后可以直接通過Apollo的后臺進行規則的修改,推送到各個客戶端實時生效。 但還有一個問題就是Sentinel...
摘要:上一篇我們介紹了如何通過的配置功能來存儲限流規則。第六步啟動應用。深入思考在使用存儲規則配置的時候與存儲一樣,對于控制臺這些數據是只讀的,也就是說控制臺中修改規則僅存在于服務的內存中,不會修改中的配置值,重啟后恢復原來的值。 上一篇我們介紹了如何通過Nacos的配置功能來存儲限流規則。Apollo是國內用戶非常多的配置中心,所以,今天我們繼續說說Spring Cloud Alibaba...
摘要:所以,在整合了做規則存儲之后,需要知道在下面兩個地方修改存在不同的效果控制臺中修改規則僅存在于服務的內存中,不會修改中的配置值,重啟后恢復原來的值。控制臺中修改規則服務的內存中規則會更新,中持久化規則也會更新,重啟后依然保持。 通過上一篇《使用Sentinel實現接口限流》的介紹,相信大家對Sentinel已經有了初步的認識。在Spring Cloud Alibaba的整合封裝之下,接...
閱讀 1337·2023-04-26 00:10
閱讀 2433·2021-09-22 15:38
閱讀 3791·2021-09-22 15:13
閱讀 3514·2019-08-30 13:11
閱讀 654·2019-08-30 11:01
閱讀 3038·2019-08-29 14:20
閱讀 3216·2019-08-29 13:27
閱讀 1731·2019-08-29 11:33