<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ## sentinel規則持久化 生產環境上,一般都是通過動態規則持久化的方式來動態的管理限流規則,也就是說,很多時候流控規則都會存儲在文件,數據庫或者配置中心當中,Sentinel的DataSource接口給我們提供了對接任意配置源的能力。所謂的動態規則就是通過控制臺配置規則后持久化到各個數據源中。 ![](https://img.kancloud.cn/cf/e8/cfe8227514224d3140b4e4b19cfa24c3_1130x584.png) ## sentinel的兩個DataSource接口 * ReadableDataSource:讀數據源負責監聽持久化的數據源的變更,在接收到變更事件時將最新的數據更新 * WritableDataSource:寫數據源負責將變更后的規則寫入到持久化的數據源中 ## sentinel-extension模塊分析 在 1.7.1 版本,sentinel-extension 模塊下的子模塊除 sentinel-parameter-flow-control、sentinel-annotation-aspectj 之外,其余子模塊都是實現動態數據源的模塊。 * sentinel-datasource-extension:定義動態數據源接口、提供抽象類 * sentinel-datasource-redis:基于 Redis 實現的動態數據源 * sentinel-datasource-zookeeper: 基于 ZooKeeper 實現的動態數據源 * 其它省略 sentinel-datasource-extension 模塊是 Sentinel 實現動態數據源的核心。 ### SentinelProperty SentinelProperty 是 Sentinel 提供的一個接口,可注冊到 Sentinel 提供的各種規則的 Manager,例如 FlowRuleManager,并且可以給 SentinelProperty 添加監聽器,在配置改變時,你可以調用 SentinelProperty#updateValue 方法,由它負責調用監聽器去更新規則,而不需要調用 FlowRuleManager#loadRules 方法。同時,你也可以注冊額外的監聽器,在配置改變時做些別的事情。 SentinelProperty 并非 sentinel-datasource-extension 模塊中定義的接口,而是 sentinel-core 定義的接口,其源碼如下: ~~~ public interface SentinelProperty<T> { void addListener(PropertyListener<T> listener); void removeListener(PropertyListener<T> listener); boolean updateValue(T newValue); } ~~~ * addListener:添加監聽器 * removeListener:移除監聽器 * updateValue:通知所有監聽器配置更新,參數 newValue 為新的配置 默認使用的實現類是 DynamicSentinelProperty,其實現源碼如下: ~~~ public class DynamicSentinelProperty<T> implements SentinelProperty<T> { // 存儲注冊的監聽器 protected Set<PropertyListener<T>> listeners = Collections.synchronizedSet(new HashSet<PropertyListener<T>>()); @Override public void addListener(PropertyListener<T> listener) { listeners.add(listener); listener.configLoad(value); } @Override public void removeListener(PropertyListener<T> listener) { listeners.remove(listener); } @Override public boolean updateValue(T newValue) { for (PropertyListener<T> listener : listeners) { listener.configUpdate(newValue); } return true; } } ~~~ DynamicSentinelProperty 使用 Set 存儲已注冊的監聽器,updateValue 負責通知所有監聽器,調用監聽器的 configUpdate 方法。 ~~~ private?static?SentinelProperty<List<FlowRule>>?currentProperty?=?new?DynamicSentinelProperty<List<FlowRule>>();/**?*?Load?{@link?FlowRule}s,?former?rules?will?be?replaced.?*?*?@param?rules?new?rules?to?load.?*/public?static?void?loadRules(List<FlowRule>?rules)?{????currentProperty.updateValue(rules);} ~~~ 在前面分析 FlowRuleManager 時,我們只關注了其 loadRules 方法,除了使用 loadRules 方法加載規則配置之外,FlowRuleManager 還提供 registerProperty API,用于注冊 SentinelProperty。 使用 SentinelProperty 實現加載 FlowRule 的步驟如下: 1. 給 FlowRuleManager 注冊一個 SentinelProperty,替換 FlowRuleManager 默認創建的 SentinelProperty(因為默認的 SentinelProperty 外部拿不到); 2. 這一步由 FlowRuleManager 完成,FlowRuleManager 會給 SentinelProperty 注冊 FlowPropertyListener 監聽器,該監聽器負責更新 FlowRuleManager.flowRules 緩存的限流規則; 3. 在應用啟動或者規則配置改變時,只需要調用 SentinelProperty#updateValue 方法,由 updateValue 通知 FlowPropertyListener 監聽器去更新規則。 FlowRuleManager 支持使用 SentinelProperty 加載或更新限流規則的實現源碼如下: ~~~ public class FlowRuleManager { // 緩存限流規則 private static final Map<String, List<FlowRule>> flowRules = new ConcurrentHashMap<String, List<FlowRule>>(); // PropertyListener 監聽器 private static final FlowPropertyListener LISTENER = new FlowPropertyListener(); // SentinelProperty private static SentinelProperty<List<FlowRule>> currentProperty // 提供默認的 SentinelProperty = new DynamicSentinelProperty<List<FlowRule>>(); static { // 給默認的 SentinelProperty 注冊監聽器(FlowPropertyListener) currentProperty.addListener(LISTENER); } // 注冊 SentinelProperty public static void register2Property(SentinelProperty<List<FlowRule>> property) { synchronized (LISTENER) { currentProperty.removeListener(LISTENER); // 注冊監聽器 property.addListener(LISTENER); currentProperty = property; } } } ~~~ 實現更新限流規則緩存的 FlowPropertyListener 是 FlowRuleManager 的一個內部類,其源碼如下: ~~~ private static final class FlowPropertyListener implements PropertyListener<List<FlowRule>> { @Override public void configUpdate(List<FlowRule> value) { Map<String, List<FlowRule>> rules = FlowRuleUtil.buildFlowRuleMap(value); if (rules != null) { // 先清空緩存再寫入 flowRules.clear(); flowRules.putAll(rules); } } @Override public void configLoad(List<FlowRule> conf) { Map<String, List<FlowRule>> rules = FlowRuleUtil.buildFlowRuleMap(conf); if (rules != null) { flowRules.clear(); flowRules.putAll(rules); } } } ~~~ PropertyListener 接口定義的兩個方法: * configUpdate:在規則更新時被調用,被調用的時機就是在 SentinelProperty#updateValue 方法被調用時。 * configLoad:在規則首次加載時被調用,是否會被調用由 SentinelProperty 決定。DynamicSentinelProperty 就沒有調用這個方法。 所以,現在我們有兩種方法更新限流規則: * 調用 FlowRuleManager#loadRules 方法 * 注冊 SentinelProperty,調用 SentinelProperty#updateValue 方法 ### ReadableDataSource Sentinel 將讀和寫數據源抽離成兩個接口,一開始只有讀接口,寫接口是后面才加的功能,目前來看,寫接口只在熱點參數限流模塊中使用到。事實上,使用讀接口就已經滿足我們的需求。ReadableDataSource 接口的定義如下: ~~~ public interface ReadableDataSource<S, T> { T loadConfig() throws Exception; S readSource() throws Exception; SentinelProperty<T> getProperty(); void close() throws Exception; } ~~~ ReadableDataSource 是一個泛型接口,參數化類型 S 代表用于裝載從數據源讀取的配置的類型,參數化類型 T 代表對應 Sentinel 中的規則類型。例如,我們可以定義一個 FlowRuleProps 類,用于裝載從 yml 配置文件中讀取的限流規則配置,然后再將 FlowRuleProps 轉為 FlowRule,所以 S 可以替換為 FlowRuleProps,T 可以替換為`List<FlowRule>`。 ReadableDataSource 接口定義的方法解釋說明如下: * loadConfig:加載配置。 * readSource:從數據源讀取配置,數據源可以是 yaml 配置文件,可以是 MySQL、Redis 等,由實現類決定從哪種數據源讀取配置。 * getProperty:獲取 SentinelProperty。 * close:用于關閉數據源,例如使用文件存儲配置時,可在此方法實現關閉文件輸入流等。 如果動態數據源提供 SentinelProperty,則可以調用 getProperty 方法獲取動態數據源的 SentinelProperty,將 SentinelProperty 注冊給規則管理器(XxxManager),動態數據源在讀取到配置時就可以調用自身 SentinelProperty 的 updateValue 方法通知規則管理器(XxxManager)更新規則。 AbstractDataSource 是一個抽象類,該類實現 ReadableDataSource 接口,用于簡化具體動態數據源的實現,子類只需要繼承 AbstractDataSource 并實現 readSource 方法即可。AbstractDataSource 源碼如下: ~~~ public abstract class AbstractDataSource<S, T> implements ReadableDataSource<S, T> { protected final Converter<S, T> parser; protected final SentinelProperty<T> property; public AbstractDataSource(Converter<S, T> parser) { if (parser == null) { throw new IllegalArgumentException("parser can't be null"); } this.parser = parser; this.property = new DynamicSentinelProperty<T>(); } @Override public T loadConfig() throws Exception { return loadConfig(readSource()); } public T loadConfig(S conf) throws Exception { T value = parser.convert(conf); return value; } @Override public SentinelProperty<T> getProperty() { return property; } } ~~~ 從源碼可以看出: * AbstractDataSource 要求所有子類都必須提供一個數據轉換器(Converter),Converter 用于將 S 類型的對象轉為 T 類型對象,例如將 FlowRuleProps 對象轉為 FlowRule 集合。 * AbstractDataSource 在構造方法中創建 DynamicSentinelProperty,因此子類無需創建 SentinelProperty。 * AbstractDataSource 實現 loadConfig 方法,首先調用子類實現的 readSource 方法從數據源讀取配置,返回的對象類型為 S,再調用 Converter#convert 方法,將對象類型由 S 轉為 T。 Converter 接口的定義如下: ~~~ public interface Converter<S, T> { T convert(S source); } ~~~ * convert:將類型為 S 的參數 source 轉為類型為 T 的對象。 ## sentinel可以支持4種持久化策略 * nacos分布式配置中心 * 阿波羅配置中心 * zookeeper * 本地文件 ![](https://img.kancloud.cn/5a/a1/5aa17a1415deab4ffea710f632e09662_912x138.png) ## 規則流程 ![](https://img.kancloud.cn/b0/7b/b07ba907e33149af08aed8ee1495cf63_1058x503.png) ## 改造內容 ### 推模式 ![](https://img.kancloud.cn/25/2e/252e4902ee18969389a8abb89ed86f8a_991x590.png) * 增加nacos地址 ![](https://img.kancloud.cn/55/9a/559a8ff834f6cb2e74d48acf061621fa_1471x650.png) * 增加配置 ![](https://img.kancloud.cn/41/65/416537d31f9c4163c31b9acab45561a0_1531x579.png) * 增加nacos ![](https://img.kancloud.cn/a8/28/a828349d68f4cb5cb0326306690260e8_506x661.png) * 修改 com.alibaba.csp.sentinel.dashboard.controller.v2.FlowControllerV2 ,找到 ![](https://img.kancloud.cn/89/38/89385021f6432d748586bf4973d6157f_1757x679.png) * 注釋選中代碼 ![](https://img.kancloud.cn/16/1d/161d7a99a15b8627ba9ff4dc4c23aa7e_507x571.png) * 修改流控規則代碼 ![](https://img.kancloud.cn/41/9a/419a495682a3aa1c3ea8b36dcc66a6d8_1661x497.png)
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看