This is an automated email from the ASF dual-hosted git repository.
xiaoyu pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/shenyu.git
The following commit(s) were added to refs/heads/master by this push:
new 1746a8e21 [type:feat] add L1 cache and trie as L2 cache (#4417)
1746a8e21 is described below
commit 1746a8e21d9686a055dc408424829438d32d87af
Author: moremind <[email protected]>
AuthorDate: Thu Mar 2 11:36:39 2023 +0800
[type:feat] add L1 cache and trie as L2 cache (#4417)
* [type:feat] add L1 cache and trie as L2 cache
* [type:feat] add L1 cache and trie as L2 cache
* fix npe
* fix npe
---
.../src/main/resources/application.yml | 10 +-
.../shenyu/common/cache/WindowTinyLFUMap.java | 75 +++++++++++++++
.../apache/shenyu/common/config/ShenyuConfig.java | 105 +++++++++++++++++++--
.../shenyu/plugin/base/AbstractShenyuPlugin.java | 98 ++++++++++++++-----
.../base/cache/CommonPluginDataSubscriber.java | 5 +-
.../shenyu/plugin/base/cache/MatchDataCache.java | 48 ++++++++++
.../plugin/base/AbstractShenyuPluginTest.java | 20 ++--
.../web/controller/LocalPluginController.java | 2 +-
8 files changed, 319 insertions(+), 44 deletions(-)
diff --git a/shenyu-bootstrap/src/main/resources/application.yml
b/shenyu-bootstrap/src/main/resources/application.yml
index f90973d6f..f0cf675d0 100644
--- a/shenyu-bootstrap/src/main/resources/application.yml
+++ b/shenyu-bootstrap/src/main/resources/application.yml
@@ -66,14 +66,18 @@ management:
enabled: false
shenyu:
+ matchCache:
+ selector:
+ selectorEnabled: false
+ maxSelectorFreeMemory: 256 # 256MB
+ rule:
+ initialCapacity: 10000 # initial capacity in cache
+ maximumSize: 10000 # max size in cache
trie:
childrenSize: 10000
pathVariableSize: 1000
pathRuleCacheSize: 1000
matchMode: antPathMatch
- matchCache:
- selectorEnabled: false
- maxSelectorFreeMemory: 256 # 256MB
netty:
http:
# set to false, user can custom the netty tcp server config.
diff --git
a/shenyu-common/src/main/java/org/apache/shenyu/common/cache/WindowTinyLFUMap.java
b/shenyu-common/src/main/java/org/apache/shenyu/common/cache/WindowTinyLFUMap.java
new file mode 100644
index 000000000..27114aaf4
--- /dev/null
+++
b/shenyu-common/src/main/java/org/apache/shenyu/common/cache/WindowTinyLFUMap.java
@@ -0,0 +1,75 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shenyu.common.cache;
+
+import com.github.benmanes.caffeine.cache.Cache;
+import com.github.benmanes.caffeine.cache.Caffeine;
+
+import javax.annotation.concurrent.ThreadSafe;
+import java.io.Serializable;
+import java.util.AbstractMap;
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+
+@ThreadSafe
+public class WindowTinyLFUMap<K, V> extends AbstractMap<K, V> implements
Serializable {
+
+ private static final long serialVersionUID = 2176631265536166614L;
+
+ private final Cache<K, V> cache;
+
+ public WindowTinyLFUMap(final int initialCapacity, final long maximumSize)
{
+ this.cache = Caffeine.newBuilder()
+ .initialCapacity(initialCapacity)
+ .maximumSize(maximumSize)
+ .build();
+ }
+
+ public WindowTinyLFUMap(final int initialSize, final long
expireAfterWrite, final long maximumSize) {
+ this.cache = Caffeine.newBuilder()
+ .initialCapacity(initialSize)
+ .expireAfterWrite(expireAfterWrite, TimeUnit.MILLISECONDS)
+ .maximumSize(maximumSize)
+ .build();
+ }
+
+ @Override
+ public V put(final K key, final V value) {
+ V v = cache.getIfPresent(value);
+ cache.put(key, value);
+ return v;
+ }
+
+ @Override
+ public V get(final Object key) {
+ return cache.getIfPresent(key);
+ }
+
+ @Override
+ public V remove(final Object key) {
+ V value = cache.getIfPresent(key);
+ cache.invalidate(key);
+ cache.cleanUp();
+ return value;
+ }
+
+ @Override
+ public Set<Entry<K, V>> entrySet() {
+ return cache.asMap().entrySet();
+ }
+}
diff --git
a/shenyu-common/src/main/java/org/apache/shenyu/common/config/ShenyuConfig.java
b/shenyu-common/src/main/java/org/apache/shenyu/common/config/ShenyuConfig.java
index 3f1bd8b68..e47509e05 100644
---
a/shenyu-common/src/main/java/org/apache/shenyu/common/config/ShenyuConfig.java
+++
b/shenyu-common/src/main/java/org/apache/shenyu/common/config/ShenyuConfig.java
@@ -531,14 +531,60 @@ public class ShenyuConfig {
* the match cache.
*/
public static class MatchCache {
-
+
+ private SelectorCacheConfig selector = new SelectorCacheConfig();
+
+ private RuleCacheConfig rule = new RuleCacheConfig();
+
+ /**
+ * get selector cache config.
+ *
+ * @return {@linkplain SelectorCacheConfig}
+ */
+ public SelectorCacheConfig getSelector() {
+ return selector;
+ }
+
+ /**
+ * set selector cache config.
+ *
+ * @param selector SelectorCacheConfig
+ */
+ public void setSelector(final SelectorCacheConfig selector) {
+ this.selector = selector;
+ }
+
+ /**
+ * get rule cache Config.
+ *
+ * @return rule cache config
+ */
+ public RuleCacheConfig getRule() {
+ return rule;
+ }
+
+ /**
+ * set rule cache config.
+ *
+ * @param rule rule cache
+ */
+ public void setRule(final RuleCacheConfig rule) {
+ this.rule = rule;
+ }
+ }
+
+ /**
+ * selector cache.
+ */
+ public static class SelectorCacheConfig {
+
private boolean selectorEnabled;
-
+
/**
* Max free memory, unit mb.
*/
private Integer maxSelectorFreeMemory = 256;
-
+
/**
* Get selector cache enabled.
*
@@ -547,7 +593,7 @@ public class ShenyuConfig {
public boolean getSelectorEnabled() {
return selectorEnabled;
}
-
+
/**
* Set selector enabled.
*
@@ -556,8 +602,7 @@ public class ShenyuConfig {
public void setSelectorEnabled(final boolean selectorEnabled) {
this.selectorEnabled = selectorEnabled;
}
-
-
+
/**
* Gets maxFreeMemory.
*
@@ -566,7 +611,7 @@ public class ShenyuConfig {
public Integer getMaxSelectorFreeMemory() {
return maxSelectorFreeMemory;
}
-
+
/**
* Sets maxFreeMemory.
*
@@ -577,6 +622,52 @@ public class ShenyuConfig {
}
}
+ /**
+ * rule cache config.
+ */
+ public static class RuleCacheConfig {
+
+ private int initialCapacity = 10000;
+
+ private long maximumSize = 10000L;
+
+ /**
+ * get initial capacity.
+ *
+ * @return initial capacity
+ */
+ public int getInitialCapacity() {
+ return initialCapacity;
+ }
+
+ /**
+ * set initial capacity.
+ *
+ * @param initialCapacity initialCapacity
+ */
+ public void setInitialCapacity(final int initialCapacity) {
+ this.initialCapacity = initialCapacity;
+ }
+
+ /**
+ * get maximum size.
+ *
+ * @return rule cache maximumSize
+ */
+ public long getMaximumSize() {
+ return maximumSize;
+ }
+
+ /**
+ * set rule cache maximumSize.
+ *
+ * @param maximumSize rule cache maximumSize
+ */
+ public void setMaximumSize(final long maximumSize) {
+ this.maximumSize = maximumSize;
+ }
+ }
+
/**
* The type Exclude path.
*/
diff --git
a/shenyu-plugin/shenyu-plugin-base/src/main/java/org/apache/shenyu/plugin/base/AbstractShenyuPlugin.java
b/shenyu-plugin/shenyu-plugin-base/src/main/java/org/apache/shenyu/plugin/base/AbstractShenyuPlugin.java
index 8d84659ab..1e9e627a1 100644
---
a/shenyu-plugin/shenyu-plugin-base/src/main/java/org/apache/shenyu/plugin/base/AbstractShenyuPlugin.java
+++
b/shenyu-plugin/shenyu-plugin-base/src/main/java/org/apache/shenyu/plugin/base/AbstractShenyuPlugin.java
@@ -57,6 +57,8 @@ public abstract class AbstractShenyuPlugin implements
ShenyuPlugin {
private static final String URI_CONDITION_TYPE = "uri";
private ShenyuConfig.MatchCache matchCacheConfig;
+
+ private ShenyuTrie trie;
/**
* this is Template Method child has Implement your own logic.
@@ -79,7 +81,7 @@ public abstract class AbstractShenyuPlugin implements
ShenyuPlugin {
*/
@Override
public Mono<Void> execute(final ServerWebExchange exchange, final
ShenyuPluginChain chain) {
- initMatchCacheConfig();
+ initCacheConfig();
final String pluginName = named();
PluginData pluginData =
BaseDataCache.getInstance().obtainPluginData(pluginName);
// early exit
@@ -100,14 +102,14 @@ public abstract class AbstractShenyuPlugin implements
ShenyuPlugin {
Pair<Boolean, SelectorData> matchSelectorData =
matchSelector(exchange, selectors);
selectorData = matchSelectorData.getRight();
if (Objects.isNull(selectorData)) {
- if (matchCacheConfig.getSelectorEnabled() &&
matchSelectorData.getLeft()) {
+ if (matchCacheConfig.getSelector().getSelectorEnabled() &&
matchSelectorData.getLeft()) {
selectorData = new SelectorData();
selectorData.setPluginName(pluginName);
cacheSelectorData(path, selectorData);
}
return handleSelectorIfNull(pluginName, exchange, chain);
} else {
- if (matchCacheConfig.getSelectorEnabled() &&
matchSelectorData.getLeft()) {
+ if (matchCacheConfig.getSelector().getSelectorEnabled() &&
matchSelectorData.getLeft()) {
cacheSelectorData(path, selectorData);
}
}
@@ -121,24 +123,30 @@ public abstract class AbstractShenyuPlugin implements
ShenyuPlugin {
if (CollectionUtils.isEmpty(rules)) {
return handleRuleIfNull(pluginName, exchange, chain);
}
- RuleData ruleData;
+ RuleData ruleData = obtainRuleDataCache(path);
+ if (Objects.nonNull(ruleData) && Objects.isNull(ruleData.getId())) {
+ return handleRuleIfNull(pluginName, exchange, chain);
+ }
if (selectorData.getType() == SelectorTypeEnum.FULL_FLOW.getCode()) {
//get last
RuleData rule = rules.get(rules.size() - 1);
printLog(rule, pluginName);
return doExecute(exchange, chain, selectorData, rule);
} else {
- // match path with rule uri condition
- ShenyuTrieNode matchTrieNode =
SpringBeanUtils.getInstance().getBean(ShenyuTrie.class).match(path,
selectorData.getId());
- if (Objects.nonNull(matchTrieNode)) {
- List<RuleData> ruleDataList =
matchTrieNode.getPathRuleCache().getIfPresent(selectorData.getId());
- if (CollectionUtils.isNotEmpty(ruleDataList)) {
- ruleData = genericMatchRule(exchange, ruleDataList);
- } else {
- ruleData = genericMatchRule(exchange, rules);
+ // lru map as L1 cache,the cache is enabled by default.
+ // if the L1 cache fails to hit, using L2 cache based on trie
cache.
+ // if the L2 cache fails to hit, execute default strategy.
+ if (Objects.isNull(ruleData)) {
+ // L1 cache not exist data, try to get data through trie cache
+ ruleData = trieMatchRule(exchange, selectorData, path);
+ // trie cache fails to hit, execute default strategy
+ if (Objects.isNull(ruleData)) {
+ Pair<Boolean, RuleData> matchRuleData =
matchRule(exchange, rules);
+ ruleData = matchRuleData.getRight();
+ if (matchRuleData.getLeft()) {
+ cacheRuleData(path, ruleData);
+ }
}
- } else {
- ruleData = genericMatchRule(exchange, rules);
}
if (Objects.isNull(ruleData)) {
return handleRuleIfNull(pluginName, exchange, chain);
@@ -148,13 +156,19 @@ public abstract class AbstractShenyuPlugin implements
ShenyuPlugin {
return doExecute(exchange, chain, selectorData, ruleData);
}
- private void initMatchCacheConfig() {
+ private void initCacheConfig() {
if (Objects.isNull(matchCacheConfig)) {
matchCacheConfig =
SpringBeanUtils.getInstance().getBean(ShenyuConfig.class).getMatchCache();
}
+ if (Objects.isNull(trie)) {
+ trie = SpringBeanUtils.getInstance().getBean(ShenyuTrie.class);
+ }
}
private void cacheSelectorData(final String path, final SelectorData
selectorData) {
+ if (Objects.isNull(selectorData)) {
+ return;
+ }
if (StringUtils.isBlank(selectorData.getId())) {
MatchDataCache.getInstance().cacheSelectorData(path, selectorData,
getSelectorMaxFreeMemory());
return;
@@ -169,11 +183,11 @@ public abstract class AbstractShenyuPlugin implements
ShenyuPlugin {
}
private Integer getSelectorMaxFreeMemory() {
- return matchCacheConfig.getMaxSelectorFreeMemory() * 1024 * 1024;
+ return matchCacheConfig.getSelector().getMaxSelectorFreeMemory() *
1024 * 1024;
}
private SelectorData obtainSelectorDataCacheIfEnabled(final String path) {
- return matchCacheConfig.getSelectorEnabled() ?
MatchDataCache.getInstance().obtainSelectorData(named(), path) : null;
+ return matchCacheConfig.getSelector().getSelectorEnabled() ?
MatchDataCache.getInstance().obtainSelectorData(named(), path) : null;
}
protected RuleData defaultRuleData(final SelectorData selectorData) {
@@ -230,21 +244,13 @@ public abstract class AbstractShenyuPlugin implements
ShenyuPlugin {
return true;
}
- private RuleData genericMatchRule(final ServerWebExchange exchange, final
Collection<RuleData> rules) {
- Pair<Boolean, RuleData> genericMatchRule = this.matchRule(exchange,
rules);
- if (genericMatchRule.getLeft()) {
- return genericMatchRule.getRight();
- }
- return null;
- }
-
private Pair<Boolean, RuleData> matchRule(final ServerWebExchange
exchange, final Collection<RuleData> rules) {
List<RuleData> filterRuleData = rules.stream()
.filter(rule -> filterRule(rule, exchange))
.distinct()
.collect(Collectors.toList());
if (filterRuleData.size() > 1) {
- return Pair.of(Boolean.TRUE, manyMatchRule(filterRuleData));
+ return Pair.of(Boolean.FALSE, manyMatchRule(filterRuleData));
} else {
return Pair.of(Boolean.TRUE,
filterRuleData.stream().findFirst().orElse(null));
}
@@ -268,6 +274,46 @@ public abstract class AbstractShenyuPlugin implements
ShenyuPlugin {
private Boolean filterRule(final RuleData ruleData, final
ServerWebExchange exchange) {
return ruleData.getEnabled() &&
MatchStrategyFactory.match(ruleData.getMatchMode(),
ruleData.getConditionDataList(), exchange);
}
+
+ private RuleData obtainRuleDataCache(final String path) {
+ return MatchDataCache.getInstance().obtainRuleData(named(), path);
+ }
+
+ private void cacheRuleData(final String path, final RuleData ruleData) {
+ if (Objects.isNull(ruleData)) {
+ return;
+ }
+ int initialCapacity = matchCacheConfig.getRule().getInitialCapacity();
+ long maximumSize = matchCacheConfig.getRule().getMaximumSize();
+ if (StringUtils.isBlank(ruleData.getId())) {
+ MatchDataCache.getInstance().cacheRuleData(path, ruleData,
initialCapacity, maximumSize);
+ return;
+ }
+ List<ConditionData> conditionList = ruleData.getConditionDataList();
+ if (CollectionUtils.isNotEmpty(conditionList)) {
+ boolean isUriCondition = conditionList.stream().allMatch(v ->
URI_CONDITION_TYPE.equals(v.getParamType()));
+ if (isUriCondition) {
+ MatchDataCache.getInstance().cacheRuleData(path, ruleData,
initialCapacity, maximumSize);
+ }
+ }
+ }
+
+ private RuleData trieMatchRule(final ServerWebExchange exchange, final
SelectorData selectorData, final String path) {
+ RuleData ruleData = null;
+ ShenyuTrieNode shenyuTrieNode = trie.match(path, selectorData.getId());
+ if (Objects.nonNull(shenyuTrieNode)) {
+ List<RuleData> ruleDataList =
shenyuTrieNode.getPathRuleCache().getIfPresent(selectorData.getId());
+ if (CollectionUtils.isNotEmpty(ruleDataList)) {
+ Pair<Boolean, RuleData> ruleDataPair = matchRule(exchange,
ruleDataList);
+ ruleData = ruleDataPair.getRight();
+ if (ruleDataPair.getLeft()) {
+ // exist only one rule data, cache rule
+ cacheRuleData(path, ruleData);
+ }
+ }
+ }
+ return ruleData;
+ }
private void printLog(final Object data, final String pluginName) {
if (data instanceof SelectorData) {
diff --git
a/shenyu-plugin/shenyu-plugin-base/src/main/java/org/apache/shenyu/plugin/base/cache/CommonPluginDataSubscriber.java
b/shenyu-plugin/shenyu-plugin-base/src/main/java/org/apache/shenyu/plugin/base/cache/CommonPluginDataSubscriber.java
index b14f9d0b9..5174271bb 100644
---
a/shenyu-plugin/shenyu-plugin-base/src/main/java/org/apache/shenyu/plugin/base/cache/CommonPluginDataSubscriber.java
+++
b/shenyu-plugin/shenyu-plugin-base/src/main/java/org/apache/shenyu/plugin/base/cache/CommonPluginDataSubscriber.java
@@ -151,6 +151,7 @@ public class CommonPluginDataSubscriber implements
PluginDataSubscriber {
@Override
public void refreshRuleDataAll() {
BaseDataCache.getInstance().cleanRuleData();
+ MatchDataCache.getInstance().cleanRuleDataData();
SpringBeanUtils.getInstance().getBean(ShenyuTrie.class).clear();
}
@@ -205,10 +206,11 @@ public class CommonPluginDataSubscriber implements
PluginDataSubscriber {
BaseDataCache.getInstance().cacheRuleData(ruleData);
Optional.ofNullable(handlerMap.get(ruleData.getPluginName()))
.ifPresent(handler -> handler.handlerRule(ruleData));
+
MatchDataCache.getInstance().removeRuleData(ruleData.getPluginName());
if
(CollectionUtils.isEmpty(ruleData.getBeforeConditionDataList())) {
eventPublisher.publishEvent(new
RuleTrieEvent(RuleTrieEventEnum.INSERT, ruleData));
} else {
- // if has before condition, use upodate
+ // if rule data has before condition, update trie
eventPublisher.publishEvent(new
RuleTrieEvent(RuleTrieEventEnum.UPDATE, ruleData));
}
}
@@ -255,6 +257,7 @@ public class CommonPluginDataSubscriber implements
PluginDataSubscriber {
BaseDataCache.getInstance().removeRuleData(ruleData);
Optional.ofNullable(handlerMap.get(ruleData.getPluginName()))
.ifPresent(handler -> handler.removeRule(ruleData));
+
MatchDataCache.getInstance().removeRuleData(ruleData.getPluginName());
eventPublisher.publishEvent(new
RuleTrieEvent(RuleTrieEventEnum.REMOVE, ruleData));
}
}
diff --git
a/shenyu-plugin/shenyu-plugin-base/src/main/java/org/apache/shenyu/plugin/base/cache/MatchDataCache.java
b/shenyu-plugin/shenyu-plugin-base/src/main/java/org/apache/shenyu/plugin/base/cache/MatchDataCache.java
index eafb2face..879e2ef5f 100644
---
a/shenyu-plugin/shenyu-plugin-base/src/main/java/org/apache/shenyu/plugin/base/cache/MatchDataCache.java
+++
b/shenyu-plugin/shenyu-plugin-base/src/main/java/org/apache/shenyu/plugin/base/cache/MatchDataCache.java
@@ -19,6 +19,8 @@ package org.apache.shenyu.plugin.base.cache;
import com.google.common.collect.Maps;
import org.apache.shenyu.common.cache.MemorySafeWindowTinyLFUMap;
+import org.apache.shenyu.common.cache.WindowTinyLFUMap;
+import org.apache.shenyu.common.dto.RuleData;
import org.apache.shenyu.common.dto.SelectorData;
import org.apache.shenyu.common.utils.MapUtils;
@@ -38,6 +40,12 @@ public final class MatchDataCache {
* pluginName -> LRUMap.
*/
private static final ConcurrentMap<String, Map<String, SelectorData>>
SELECTOR_DATA_MAP = Maps.newConcurrentMap();
+
+ /**
+ * plugin name -> LRU Map.
+ * LRU Map: path -> rule data.
+ */
+ private static final ConcurrentMap<String, Map<String, RuleData>>
RULE_DATA_MAP = Maps.newConcurrentMap();
private MatchDataCache() {
}
@@ -89,4 +97,44 @@ public final class MatchDataCache {
final Map<String, SelectorData> lruMap =
SELECTOR_DATA_MAP.get(pluginName);
return Optional.ofNullable(lruMap).orElse(Maps.newHashMap()).get(path);
}
+
+ /**
+ * cache rule data.
+ *
+ * @param path path
+ * @param ruleData rule data
+ * @param initialCapacity initial capacity
+ * @param maximumSize maximum size
+ */
+ public void cacheRuleData(final String path, final RuleData ruleData,
final int initialCapacity, final long maximumSize) {
+ MapUtils.computeIfAbsent(RULE_DATA_MAP, ruleData.getPluginName(), map
-> new WindowTinyLFUMap<>(initialCapacity, maximumSize)).put(path, ruleData);
+ }
+
+ /**
+ * remove rule data.
+ *
+ * @param pluginName pluginName
+ */
+ public void removeRuleData(final String pluginName) {
+ RULE_DATA_MAP.remove(pluginName);
+ }
+
+ /**
+ * clear the cache.
+ */
+ public void cleanRuleDataData() {
+ RULE_DATA_MAP.clear();
+ }
+
+ /**
+ * get rule data.
+ *
+ * @param pluginName pluginName
+ * @param path path
+ * @return ruleData
+ */
+ public RuleData obtainRuleData(final String pluginName, final String path)
{
+ final Map<String, RuleData> lruMap = RULE_DATA_MAP.get(pluginName);
+ return Optional.ofNullable(lruMap).orElse(Maps.newHashMap()).get(path);
+ }
}
diff --git
a/shenyu-plugin/shenyu-plugin-base/src/test/java/org/apache/shenyu/plugin/base/AbstractShenyuPluginTest.java
b/shenyu-plugin/shenyu-plugin-base/src/test/java/org/apache/shenyu/plugin/base/AbstractShenyuPluginTest.java
index b00e5729d..0ea30a92b 100644
---
a/shenyu-plugin/shenyu-plugin-base/src/test/java/org/apache/shenyu/plugin/base/AbstractShenyuPluginTest.java
+++
b/shenyu-plugin/shenyu-plugin-base/src/test/java/org/apache/shenyu/plugin/base/AbstractShenyuPluginTest.java
@@ -67,18 +67,26 @@ public final class AbstractShenyuPluginTest {
@BeforeEach
public void setUp() {
mockShenyuConfig();
- this.ruleData = RuleData.builder().id("1")
- .selectorId("1").enabled(true)
- .loged(true).sort(1).build();
+ this.ruleData = RuleData.builder()
+ .id("1")
+ .pluginName("SHENYU")
+ .selectorId("1")
+ .enabled(true)
+ .loged(true)
+ .sort(1).build();
this.conditionData = new ConditionData();
this.conditionData.setOperator("match");
this.conditionData.setParamName("/");
this.conditionData.setParamType("uri");
this.conditionData.setParamValue("/http/**");
this.shenyuPluginChain = mock(ShenyuPluginChain.class);
- this.pluginData =
PluginData.builder().name("SHENYU").enabled(true).build();
- this.selectorData = SelectorData.builder().id("1").pluginName("SHENYU")
-
.enabled(true).type(SelectorTypeEnum.CUSTOM_FLOW.getCode()).build();
+ this.pluginData = PluginData.builder()
+ .name("SHENYU")
+ .enabled(true).build();
+ this.selectorData = SelectorData.builder()
+ .id("1").pluginName("SHENYU")
+ .enabled(true)
+ .type(SelectorTypeEnum.CUSTOM_FLOW.getCode()).build();
this.testShenyuPlugin = spy(new TestShenyuPlugin());
this.exchange =
MockServerWebExchange.from(MockServerHttpRequest.get("/http/SHENYU/SHENYU")
.build());
diff --git
a/shenyu-web/src/main/java/org/apache/shenyu/web/controller/LocalPluginController.java
b/shenyu-web/src/main/java/org/apache/shenyu/web/controller/LocalPluginController.java
index 5c823a172..4fc8f0668 100644
---
a/shenyu-web/src/main/java/org/apache/shenyu/web/controller/LocalPluginController.java
+++
b/shenyu-web/src/main/java/org/apache/shenyu/web/controller/LocalPluginController.java
@@ -98,9 +98,9 @@ public class LocalPluginController {
final List<String> selectorIds =
selectorData.stream().map(SelectorData::getId).collect(Collectors.toList());
BaseDataCache.getInstance().removeSelectDataByPluginName(name);
MatchDataCache.getInstance().removeSelectorData(name);
+ MatchDataCache.getInstance().removeRuleData(name);
for (String selectorId : selectorIds) {
BaseDataCache.getInstance().removeRuleDataBySelectorId(selectorId);
-
List<RuleData> ruleDataList =
BaseDataCache.getInstance().obtainRuleData(selectorId);
if (CollectionUtils.isNotEmpty(ruleDataList)) {
ruleDataList.forEach(rule -> {