This is an automated email from the ASF dual-hosted git repository. hefengen 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 e38f4eac29 [type:feat]The sync-data-http method adapts to the namespace transformation (#5598) e38f4eac29 is described below commit e38f4eac29fc796e41bc057ed95d3abc4d4ac54a Author: xcsnx <1192709...@qq.com> AuthorDate: Wed Oct 16 22:04:31 2024 +0800 [type:feat]The sync-data-http method adapts to the namespace transformation (#5598) * sync frontend * commit * commit * fix e2e * fix test * fix * fix cr * fix cr * fix cr * final * fix * fix * fix * fix * fix uni test * fix * fix * fix * fix * fix * fix * fix * fix --------- Co-authored-by: ‘xcsnx’ <‘1192709...@qq.com’> Co-authored-by: aias00 <rok...@163.com> --- .../config/HttpLongPollingSyncConfiguration.java | 1 - .../shenyu/admin/controller/ConfigController.java | 41 +++++-- .../admin/discovery/LocalDiscoveryProcessor.java | 2 + .../listener/AbstractDataChangedListener.java | 136 ++++++++++++--------- .../shenyu/admin/listener/ConfigDataCache.java | 14 ++- .../shenyu/admin/listener/DataChangedEvent.java | 6 +- .../http/HttpLongPollingDataChangedListener.java | 107 +++++++++++----- .../shenyu/admin/mapper/NamespaceMapper.java | 9 +- .../apache/shenyu/admin/model/entity/RuleDO.java | 1 + .../shenyu/admin/service/NamespaceService.java | 7 ++ .../admin/service/impl/DiscoveryServiceImpl.java | 1 + .../admin/service/impl/NamespaceServiceImpl.java | 9 +- .../admin/service/impl/SelectorServiceImpl.java | 3 +- .../admin/service/impl/UpstreamCheckService.java | 1 + .../shenyu/admin/transfer/DiscoveryTransfer.java | 1 + .../shenyu/admin/transfer/MetaDataTransfer.java | 1 + .../main/resources/mappers/namespace-sqlmap.xml | 8 +- .../admin/controller/ConfigControllerTest.java | 19 ++- .../listener/AbstractDataChangedListenerTest.java | 77 +++++++----- .../shenyu/admin/listener/ConfigDataCacheTest.java | 3 +- .../apache/shenyu/common/config/ShenyuConfig.java | 8 +- .../shenyu/common/dto/ProxySelectorData.java | 20 +++ .../sync/data/http/HttpSyncDataConfiguration.java | 8 +- .../http/HttpClientPluginConfigurationTest.java | 3 +- .../shenyu/sync/data/http/HttpSyncDataService.java | 29 +++-- .../sync/data/http/HttpSyncDataServiceTest.java | 6 +- 26 files changed, 358 insertions(+), 163 deletions(-) diff --git a/shenyu-admin/src/main/java/org/apache/shenyu/admin/config/HttpLongPollingSyncConfiguration.java b/shenyu-admin/src/main/java/org/apache/shenyu/admin/config/HttpLongPollingSyncConfiguration.java index 190c938bc8..0b06a529e0 100644 --- a/shenyu-admin/src/main/java/org/apache/shenyu/admin/config/HttpLongPollingSyncConfiguration.java +++ b/shenyu-admin/src/main/java/org/apache/shenyu/admin/config/HttpLongPollingSyncConfiguration.java @@ -42,5 +42,4 @@ public class HttpLongPollingSyncConfiguration { public HttpLongPollingDataChangedListener httpLongPollingDataChangedListener(final HttpSyncProperties httpSyncProperties) { return new HttpLongPollingDataChangedListener(httpSyncProperties); } - } diff --git a/shenyu-admin/src/main/java/org/apache/shenyu/admin/controller/ConfigController.java b/shenyu-admin/src/main/java/org/apache/shenyu/admin/controller/ConfigController.java index 5d8c67e156..6a77afae7e 100644 --- a/shenyu-admin/src/main/java/org/apache/shenyu/admin/controller/ConfigController.java +++ b/shenyu-admin/src/main/java/org/apache/shenyu/admin/controller/ConfigController.java @@ -18,8 +18,16 @@ package org.apache.shenyu.admin.controller; import com.google.common.collect.Maps; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.validation.constraints.NotNull; +import org.apache.commons.lang3.ObjectUtils; +import org.apache.commons.lang3.StringUtils; +import org.apache.shenyu.admin.exception.ShenyuAdminException; import org.apache.shenyu.admin.listener.http.HttpLongPollingDataChangedListener; import org.apache.shenyu.admin.model.result.ShenyuAdminResult; +import org.apache.shenyu.admin.model.vo.NamespaceVO; +import org.apache.shenyu.admin.service.NamespaceService; import org.apache.shenyu.admin.utils.ShenyuResultMessage; import org.apache.shenyu.common.dto.ConfigData; import org.apache.shenyu.common.enums.ConfigGroupEnum; @@ -27,10 +35,6 @@ import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; - -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; -import jakarta.validation.constraints.NotNull; import org.springframework.web.bind.annotation.RestController; import java.util.Map; @@ -42,29 +46,40 @@ import java.util.Map; @RequestMapping("/configs") @RestController public class ConfigController { - + private final HttpLongPollingDataChangedListener longPollingListener; - - public ConfigController(final HttpLongPollingDataChangedListener longPollingListener) { + + private final NamespaceService namespaceService; + + public ConfigController(final HttpLongPollingDataChangedListener longPollingListener, final NamespaceService namespaceService) { this.longPollingListener = longPollingListener; + this.namespaceService = namespaceService; } - + /** * Fetch configs shenyu result. * - * @param groupKeys the group keys + * @param groupKeys the group keys + * @param namespaceId namespaceId * @return the shenyu result */ @GetMapping("/fetch") - public ShenyuAdminResult fetchConfigs(@NotNull final String[] groupKeys) { + public ShenyuAdminResult fetchConfigs(@NotNull final String[] groupKeys, final String namespaceId) { + if (StringUtils.isEmpty(namespaceId)) { + throw new ShenyuAdminException("namespaceId is null"); + } + NamespaceVO existNamespace = namespaceService.findById(namespaceId); + if (StringUtils.isNotEmpty(namespaceId) && ObjectUtils.isEmpty(existNamespace)) { + throw new ShenyuAdminException("namespace is not exist"); + } Map<String, ConfigData<?>> result = Maps.newHashMap(); for (String groupKey : groupKeys) { - ConfigData<?> data = longPollingListener.fetchConfig(ConfigGroupEnum.valueOf(groupKey)); + ConfigData<?> data = longPollingListener.fetchConfig(ConfigGroupEnum.valueOf(groupKey), namespaceId); result.put(groupKey, data); } return ShenyuAdminResult.success(ShenyuResultMessage.SUCCESS, result); } - + /** * Listener. * @@ -75,5 +90,5 @@ public class ConfigController { public void listener(final HttpServletRequest request, final HttpServletResponse response) { longPollingListener.doLongPolling(request, response); } - + } diff --git a/shenyu-admin/src/main/java/org/apache/shenyu/admin/discovery/LocalDiscoveryProcessor.java b/shenyu-admin/src/main/java/org/apache/shenyu/admin/discovery/LocalDiscoveryProcessor.java index 223e0873bc..08be2f5a6d 100644 --- a/shenyu-admin/src/main/java/org/apache/shenyu/admin/discovery/LocalDiscoveryProcessor.java +++ b/shenyu-admin/src/main/java/org/apache/shenyu/admin/discovery/LocalDiscoveryProcessor.java @@ -88,6 +88,7 @@ public class LocalDiscoveryProcessor implements DiscoveryProcessor, ApplicationE discoverySyncData.setSelectorName(proxySelectorDTO.getName()); List<DiscoveryUpstreamData> upstreamDataList = upstreamDTOS.stream().map(DiscoveryTransfer.INSTANCE::mapToData).collect(Collectors.toList()); discoverySyncData.setUpstreamDataList(upstreamDataList); + discoverySyncData.setNamespaceId(proxySelectorDTO.getNamespaceId()); DataChangedEvent dataChangedEvent = new DataChangedEvent(ConfigGroupEnum.DISCOVER_UPSTREAM, DataEventTypeEnum.UPDATE, Collections.singletonList(discoverySyncData)); eventPublisher.publishEvent(dataChangedEvent); DiscoveryStreamUpdatedEvent discoveryStreamUpdatedEvent = new DiscoveryStreamUpdatedEvent(discoverySyncData, LOCAL_DISCOVERY_UPSTREAM_UPDATE); @@ -108,6 +109,7 @@ public class LocalDiscoveryProcessor implements DiscoveryProcessor, ApplicationE discoverySyncData.setSelectorName(proxySelectorDTO.getName()); List<DiscoveryUpstreamData> upstreamDataList = discoveryUpstreamDOS.stream().map(DiscoveryTransfer.INSTANCE::mapToData).collect(Collectors.toList()); discoverySyncData.setUpstreamDataList(upstreamDataList); + discoverySyncData.setNamespaceId(proxySelectorDTO.getNamespaceId()); DataChangedEvent dataChangedEvent = new DataChangedEvent(ConfigGroupEnum.DISCOVER_UPSTREAM, DataEventTypeEnum.UPDATE, Collections.singletonList(discoverySyncData)); eventPublisher.publishEvent(dataChangedEvent); } diff --git a/shenyu-admin/src/main/java/org/apache/shenyu/admin/listener/AbstractDataChangedListener.java b/shenyu-admin/src/main/java/org/apache/shenyu/admin/listener/AbstractDataChangedListener.java index 2084a9086d..6547b2fa6d 100644 --- a/shenyu-admin/src/main/java/org/apache/shenyu/admin/listener/AbstractDataChangedListener.java +++ b/shenyu-admin/src/main/java/org/apache/shenyu/admin/listener/AbstractDataChangedListener.java @@ -17,23 +17,28 @@ package org.apache.shenyu.admin.listener; +import jakarta.annotation.Resource; import org.apache.commons.codec.digest.DigestUtils; import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.StringUtils; +import org.apache.shenyu.admin.listener.http.HttpLongPollingDataChangedListener; +import org.apache.shenyu.admin.model.vo.NamespaceVO; import org.apache.shenyu.admin.service.AppAuthService; import org.apache.shenyu.admin.service.DiscoveryUpstreamService; import org.apache.shenyu.admin.service.MetaDataService; import org.apache.shenyu.admin.service.NamespacePluginService; +import org.apache.shenyu.admin.service.NamespaceService; import org.apache.shenyu.admin.service.ProxySelectorService; import org.apache.shenyu.admin.service.RuleService; import org.apache.shenyu.admin.service.SelectorService; import org.apache.shenyu.common.dto.AppAuthData; import org.apache.shenyu.common.dto.ConfigData; +import org.apache.shenyu.common.dto.DiscoverySyncData; import org.apache.shenyu.common.dto.MetaData; import org.apache.shenyu.common.dto.PluginData; +import org.apache.shenyu.common.dto.ProxySelectorData; import org.apache.shenyu.common.dto.RuleData; import org.apache.shenyu.common.dto.SelectorData; -import org.apache.shenyu.common.dto.DiscoverySyncData; -import org.apache.shenyu.common.dto.ProxySelectorData; import org.apache.shenyu.common.enums.ConfigGroupEnum; import org.apache.shenyu.common.enums.DataEventTypeEnum; import org.apache.shenyu.common.utils.GsonUtils; @@ -42,11 +47,12 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.InitializingBean; -import jakarta.annotation.Resource; import java.util.List; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; +import static org.apache.shenyu.common.constant.Constants.SYS_DEFAULT_NAMESPACE_ID; + /** * Abstract class for ConfigEventListener. @@ -98,14 +104,18 @@ public abstract class AbstractDataChangedListener implements DataChangedListener @Resource private DiscoveryUpstreamService discoveryUpstreamService; + @Resource + private NamespaceService namespaceService; + /** * fetch configuration from cache. * - * @param groupKey the group key + * @param groupKey the group key + * @param namespaceId the namespaceId * @return the configuration data */ - public ConfigData<?> fetchConfig(final ConfigGroupEnum groupKey) { - ConfigDataCache config = CACHE.get(groupKey.name()); + public ConfigData<?> fetchConfig(final ConfigGroupEnum groupKey, final String namespaceId) { + ConfigDataCache config = CACHE.get(HttpLongPollingDataChangedListener.buildCacheKey(namespaceId, groupKey.name())); switch (groupKey) { case APP_AUTH: return buildConfigData(config, AppAuthData.class); @@ -131,8 +141,9 @@ public abstract class AbstractDataChangedListener implements DataChangedListener if (CollectionUtils.isEmpty(changed)) { return; } - this.updateAppAuthCache(); - this.afterAppAuthChanged(changed, eventType); + String namespaceId = changed.stream().map(value -> StringUtils.defaultString(value.getNamespaceId(), SYS_DEFAULT_NAMESPACE_ID)).findFirst().get(); + this.updateAppAuthCache(namespaceId); + this.afterAppAuthChanged(changed, eventType, namespaceId); } /** @@ -141,7 +152,7 @@ public abstract class AbstractDataChangedListener implements DataChangedListener * @param changed the changed * @param eventType the event type */ - protected void afterAppAuthChanged(final List<AppAuthData> changed, final DataEventTypeEnum eventType) { + protected void afterAppAuthChanged(final List<AppAuthData> changed, final DataEventTypeEnum eventType, final String namespaceId) { } @Override @@ -149,8 +160,9 @@ public abstract class AbstractDataChangedListener implements DataChangedListener if (CollectionUtils.isEmpty(changed)) { return; } - this.updateMetaDataCache(); - this.afterMetaDataChanged(changed, eventType); + String namespaceId = changed.stream().map(value -> StringUtils.defaultString(value.getNamespaceId(), SYS_DEFAULT_NAMESPACE_ID)).findFirst().get(); + this.updateMetaDataCache(namespaceId); + this.afterMetaDataChanged(changed, eventType, namespaceId); } /** @@ -159,7 +171,7 @@ public abstract class AbstractDataChangedListener implements DataChangedListener * @param changed the changed * @param eventType the event type */ - protected void afterMetaDataChanged(final List<MetaData> changed, final DataEventTypeEnum eventType) { + protected void afterMetaDataChanged(final List<MetaData> changed, final DataEventTypeEnum eventType, final String namespaceId) { } @Override @@ -167,45 +179,48 @@ public abstract class AbstractDataChangedListener implements DataChangedListener if (CollectionUtils.isEmpty(changed)) { return; } - this.updatePluginCache(); - this.afterPluginChanged(changed, eventType); + String namespaceId = changed.stream().map(value -> StringUtils.defaultString(value.getNamespaceId(), SYS_DEFAULT_NAMESPACE_ID)).findFirst().get(); + this.updatePluginCache(namespaceId); + this.afterPluginChanged(changed, eventType, namespaceId); } - + /** * After plugin changed. * * @param changed the changed * @param eventType the event type */ - protected void afterPluginChanged(final List<PluginData> changed, final DataEventTypeEnum eventType) { + protected void afterPluginChanged(final List<PluginData> changed, final DataEventTypeEnum eventType, final String namespaceId) { } - + @Override public void onRuleChanged(final List<RuleData> changed, final DataEventTypeEnum eventType) { if (CollectionUtils.isEmpty(changed)) { return; } LOG.info("onRuleChanged, changed:{}, eventType:{}", JsonUtils.toJson(changed), JsonUtils.toJson(eventType)); - this.updateRuleCache(); - this.afterRuleChanged(changed, eventType); + String namespaceId = changed.stream().map(value -> StringUtils.defaultString(value.getNamespaceId(), SYS_DEFAULT_NAMESPACE_ID)).findFirst().get(); + this.updateRuleCache(namespaceId); + this.afterRuleChanged(changed, eventType, namespaceId); } - + /** * After rule changed. * * @param changed the changed * @param eventType the event type */ - protected void afterRuleChanged(final List<RuleData> changed, final DataEventTypeEnum eventType) { + protected void afterRuleChanged(final List<RuleData> changed, final DataEventTypeEnum eventType, final String namespaceId) { } - + @Override public void onSelectorChanged(final List<SelectorData> changed, final DataEventTypeEnum eventType) { if (CollectionUtils.isEmpty(changed)) { return; } - this.updateSelectorCache(); - this.afterSelectorChanged(changed, eventType); + String namespaceId = changed.stream().map(value -> StringUtils.defaultString(value.getNamespaceId(), SYS_DEFAULT_NAMESPACE_ID)).findFirst().get(); + this.updateSelectorCache(namespaceId); + this.afterSelectorChanged(changed, eventType, namespaceId); } /** @@ -218,8 +233,9 @@ public abstract class AbstractDataChangedListener implements DataChangedListener if (CollectionUtils.isEmpty(changed)) { return; } - this.updateProxySelectorDataCache(); - this.afterProxySelectorChanged(changed, eventType); + String namespaceId = changed.stream().map(value -> StringUtils.defaultString(value.getNamespaceId(), SYS_DEFAULT_NAMESPACE_ID)).findFirst().get(); + this.updateProxySelectorDataCache(namespaceId); + this.afterProxySelectorChanged(changed, eventType, namespaceId); } /** @@ -228,7 +244,7 @@ public abstract class AbstractDataChangedListener implements DataChangedListener * @param changed the changed * @param eventType the event type */ - protected void afterProxySelectorChanged(final List<ProxySelectorData> changed, final DataEventTypeEnum eventType) { + protected void afterProxySelectorChanged(final List<ProxySelectorData> changed, final DataEventTypeEnum eventType, final String namespaceId) { } /** @@ -241,8 +257,9 @@ public abstract class AbstractDataChangedListener implements DataChangedListener if (CollectionUtils.isEmpty(changed)) { return; } - this.updateDiscoveryUpstreamDataCache(); - this.afterDiscoveryUpstreamDataChanged(changed, eventType); + String namespaceId = changed.stream().map(value -> StringUtils.defaultString(value.getNamespaceId(), SYS_DEFAULT_NAMESPACE_ID)).findFirst().get(); + this.updateDiscoveryUpstreamDataCache(namespaceId); + this.afterDiscoveryUpstreamDataChanged(changed, eventType, namespaceId); } /** @@ -251,7 +268,7 @@ public abstract class AbstractDataChangedListener implements DataChangedListener * @param changed the changed * @param eventType the event type */ - protected void afterDiscoveryUpstreamDataChanged(final List<DiscoverySyncData> changed, final DataEventTypeEnum eventType) { + protected void afterDiscoveryUpstreamDataChanged(final List<DiscoverySyncData> changed, final DataEventTypeEnum eventType, final String namespaceId) { } /** @@ -260,7 +277,7 @@ public abstract class AbstractDataChangedListener implements DataChangedListener * @param changed the changed * @param eventType the event type */ - protected void afterSelectorChanged(final List<SelectorData> changed, final DataEventTypeEnum eventType) { + protected void afterSelectorChanged(final List<SelectorData> changed, final DataEventTypeEnum eventType, final String namespaceId) { } @Override @@ -278,68 +295,73 @@ public abstract class AbstractDataChangedListener implements DataChangedListener * @param <T> the type of class * @param data the new config data */ - protected <T> void updateCache(final ConfigGroupEnum group, final List<T> data) { + protected <T> void updateCache(final ConfigGroupEnum group, final List<T> data, final String namespaceId) { String json = GsonUtils.getInstance().toJson(data); - ConfigDataCache newVal = new ConfigDataCache(group.name(), json, DigestUtils.md5Hex(json), System.currentTimeMillis()); + String configDataCacheKey = HttpLongPollingDataChangedListener.buildCacheKey(namespaceId, group.name()); + ConfigDataCache newVal = new ConfigDataCache(configDataCacheKey, json, DigestUtils.md5Hex(json), System.currentTimeMillis(), namespaceId); ConfigDataCache oldVal = CACHE.put(newVal.getGroup(), newVal); LOG.info("update config cache[{}], old: {}, updated: {}", group, oldVal, newVal); LOG.info("update config json: {}", json); } - + /** * refresh local cache. */ protected void refreshLocalCache() { - this.updateAppAuthCache(); - this.updatePluginCache(); - this.updateRuleCache(); - this.updateSelectorCache(); - this.updateMetaDataCache(); - this.updateProxySelectorDataCache(); - this.updateDiscoveryUpstreamDataCache(); + List<NamespaceVO> namespaceList = namespaceService.listAll(); + for (NamespaceVO namespace : namespaceList) { + String namespaceId = namespace.getNamespaceId(); + this.updatePluginCache(namespaceId); + this.updateAppAuthCache(namespaceId); + this.updateRuleCache(namespaceId); + this.updateSelectorCache(namespaceId); + this.updateMetaDataCache(namespaceId); + this.updateProxySelectorDataCache(namespaceId); + this.updateDiscoveryUpstreamDataCache(namespaceId); + } } /** * Update selector cache. */ - protected void updateSelectorCache() { - this.updateCache(ConfigGroupEnum.SELECTOR, selectorService.listAll()); + protected void updateSelectorCache(final String namespaceId) { + this.updateCache(ConfigGroupEnum.SELECTOR, selectorService.listAll(), namespaceId); } /** * Update rule cache. */ - protected void updateRuleCache() { - this.updateCache(ConfigGroupEnum.RULE, ruleService.listAll()); + protected void updateRuleCache(final String namespaceId) { + this.updateCache(ConfigGroupEnum.RULE, ruleService.listAll(), namespaceId); } /** * Update plugin cache. */ - protected void updatePluginCache() { - this.updateCache(ConfigGroupEnum.PLUGIN, namespacePluginService.listAll()); + protected void updatePluginCache(final String namespaceId) { + this.updateCache(ConfigGroupEnum.PLUGIN, namespacePluginService.listAll(namespaceId), namespaceId); } - + /** * Update app auth cache. */ - protected void updateAppAuthCache() { - this.updateCache(ConfigGroupEnum.APP_AUTH, appAuthService.listAll()); + protected void updateAppAuthCache(final String namespaceId) { + this.updateCache(ConfigGroupEnum.APP_AUTH, appAuthService.listAll(), namespaceId); } - + /** * Update meta data cache. */ - protected void updateMetaDataCache() { - this.updateCache(ConfigGroupEnum.META_DATA, metaDataService.listAll()); + protected void updateMetaDataCache(final String namespaceId) { + this.updateCache(ConfigGroupEnum.META_DATA, metaDataService.listAll(), namespaceId); } - protected void updateProxySelectorDataCache() { - this.updateCache(ConfigGroupEnum.PROXY_SELECTOR, proxySelectorService.listAll()); + protected void updateProxySelectorDataCache(final String namespaceId) { + this.updateCache(ConfigGroupEnum.PROXY_SELECTOR, proxySelectorService.listAll(), namespaceId); } - protected void updateDiscoveryUpstreamDataCache() { - this.updateCache(ConfigGroupEnum.DISCOVER_UPSTREAM, discoveryUpstreamService.listAll()); + protected void updateDiscoveryUpstreamDataCache(final String namespaceId) { + this.updateCache(ConfigGroupEnum.DISCOVER_UPSTREAM, discoveryUpstreamService.listAll(), namespaceId); } private <T> ConfigData<T> buildConfigData(final ConfigDataCache config, final Class<T> dataType) { diff --git a/shenyu-admin/src/main/java/org/apache/shenyu/admin/listener/ConfigDataCache.java b/shenyu-admin/src/main/java/org/apache/shenyu/admin/listener/ConfigDataCache.java index c399851b99..973839f1fd 100644 --- a/shenyu-admin/src/main/java/org/apache/shenyu/admin/listener/ConfigDataCache.java +++ b/shenyu-admin/src/main/java/org/apache/shenyu/admin/listener/ConfigDataCache.java @@ -31,6 +31,8 @@ public class ConfigDataCache { private final String json; private volatile long lastModifyTime; + + private final String namespaceId; /** * Instantiates a new Config data cache. @@ -40,11 +42,12 @@ public class ConfigDataCache { * @param md5 the md5 * @param lastModifyTime the last modify time */ - public ConfigDataCache(final String group, final String json, final String md5, final long lastModifyTime) { + public ConfigDataCache(final String group, final String json, final String md5, final long lastModifyTime, final String namespaceId) { this.group = group; this.json = json; this.md5 = md5; this.lastModifyTime = lastModifyTime; + this.namespaceId = namespaceId; } /** @@ -94,6 +97,15 @@ public class ConfigDataCache { return json; } + /** + * Gets namespaceId. + * + * @return the namespaceId + */ + public String getNamespaceId() { + return namespaceId; + } + @Override public String toString() { return "{" diff --git a/shenyu-admin/src/main/java/org/apache/shenyu/admin/listener/DataChangedEvent.java b/shenyu-admin/src/main/java/org/apache/shenyu/admin/listener/DataChangedEvent.java index 728668992c..e89105528e 100644 --- a/shenyu-admin/src/main/java/org/apache/shenyu/admin/listener/DataChangedEvent.java +++ b/shenyu-admin/src/main/java/org/apache/shenyu/admin/listener/DataChangedEvent.java @@ -42,9 +42,9 @@ public class DataChangedEvent extends ApplicationEvent { /** * Instantiates a new Data changed event. * - * @param groupKey the group key - * @param type the type - * @param source the source + * @param groupKey the group key + * @param type the type + * @param source the source */ public DataChangedEvent(final ConfigGroupEnum groupKey, final DataEventTypeEnum type, final List<?> source) { super(source.stream().filter(Objects::nonNull).collect(Collectors.toList())); diff --git a/shenyu-admin/src/main/java/org/apache/shenyu/admin/listener/http/HttpLongPollingDataChangedListener.java b/shenyu-admin/src/main/java/org/apache/shenyu/admin/listener/http/HttpLongPollingDataChangedListener.java index e9baa1c1f2..3a409f6763 100644 --- a/shenyu-admin/src/main/java/org/apache/shenyu/admin/listener/http/HttpLongPollingDataChangedListener.java +++ b/shenyu-admin/src/main/java/org/apache/shenyu/admin/listener/http/HttpLongPollingDataChangedListener.java @@ -46,20 +46,25 @@ import org.springframework.http.MediaType; import jakarta.servlet.AsyncContext; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; + import java.io.IOException; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Iterator; import java.util.List; +import java.util.Map; import java.util.Objects; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.BlockingQueue; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.Future; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.TimeUnit; +import static org.apache.shenyu.common.constant.Constants.SYS_DEFAULT_NAMESPACE_ID; + /** * HTTP long polling, which blocks the client's request thread * and informs the client of group information about data changes @@ -82,7 +87,7 @@ public class HttpLongPollingDataChangedListener extends AbstractDataChangedListe /** * Blocked client. */ - private final BlockingQueue<LongPollingClient> clients; + private final Map<String, BlockingQueue<LongPollingClient>> clientsMap; private final ScheduledExecutorService scheduler; @@ -94,7 +99,7 @@ public class HttpLongPollingDataChangedListener extends AbstractDataChangedListe * @param httpSyncProperties the HttpSyncProperties */ public HttpLongPollingDataChangedListener(final HttpSyncProperties httpSyncProperties) { - this.clients = new ArrayBlockingQueue<>(1024); + this.clientsMap = new ConcurrentHashMap<>(); this.scheduler = new ScheduledThreadPoolExecutor(1, ShenyuThreadFactory.create("long-polling", true)); this.httpSyncProperties = httpSyncProperties; @@ -126,7 +131,8 @@ public class HttpLongPollingDataChangedListener extends AbstractDataChangedListe public void doLongPolling(final HttpServletRequest request, final HttpServletResponse response) { // compare group md5 List<ConfigGroupEnum> changedGroup = compareChangedGroup(request); - String clientIp = getRemoteIp(request); + final String clientIp = getRemoteIp(request); + final String namespaceId = getNamespaceId(request); // response immediately. if (CollectionUtils.isNotEmpty(changedGroup)) { this.generateResponse(response, changedGroup); @@ -139,46 +145,47 @@ public class HttpLongPollingDataChangedListener extends AbstractDataChangedListe // AsyncContext.settimeout() does not timeout properly, so you have to control it yourself asyncContext.setTimeout(0L); // block client's thread. - scheduler.execute(new LongPollingClient(asyncContext, clientIp, HttpConstants.SERVER_MAX_HOLD_TIMEOUT)); + scheduler.execute(new LongPollingClient(asyncContext, clientIp, HttpConstants.SERVER_MAX_HOLD_TIMEOUT, namespaceId)); } @Override - protected void afterAppAuthChanged(final List<AppAuthData> changed, final DataEventTypeEnum eventType) { - scheduler.execute(new DataChangeTask(ConfigGroupEnum.APP_AUTH)); + protected void afterAppAuthChanged(final List<AppAuthData> changed, final DataEventTypeEnum eventType, final String namespaceId) { + scheduler.execute(new DataChangeTask(ConfigGroupEnum.APP_AUTH, namespaceId)); } @Override - protected void afterMetaDataChanged(final List<MetaData> changed, final DataEventTypeEnum eventType) { - scheduler.execute(new DataChangeTask(ConfigGroupEnum.META_DATA)); + protected void afterMetaDataChanged(final List<MetaData> changed, final DataEventTypeEnum eventType, final String namespaceId) { + scheduler.execute(new DataChangeTask(ConfigGroupEnum.META_DATA, namespaceId)); } @Override - protected void afterPluginChanged(final List<PluginData> changed, final DataEventTypeEnum eventType) { - scheduler.execute(new DataChangeTask(ConfigGroupEnum.PLUGIN)); + protected void afterPluginChanged(final List<PluginData> changed, final DataEventTypeEnum eventType, final String namespaceId) { + scheduler.execute(new DataChangeTask(ConfigGroupEnum.PLUGIN, namespaceId)); } @Override - protected void afterRuleChanged(final List<RuleData> changed, final DataEventTypeEnum eventType) { - scheduler.execute(new DataChangeTask(ConfigGroupEnum.RULE)); + protected void afterRuleChanged(final List<RuleData> changed, final DataEventTypeEnum eventType, final String namespaceId) { + scheduler.execute(new DataChangeTask(ConfigGroupEnum.RULE, namespaceId)); } @Override - protected void afterSelectorChanged(final List<SelectorData> changed, final DataEventTypeEnum eventType) { - scheduler.execute(new DataChangeTask(ConfigGroupEnum.SELECTOR)); + protected void afterSelectorChanged(final List<SelectorData> changed, final DataEventTypeEnum eventType, final String namespaceId) { + scheduler.execute(new DataChangeTask(ConfigGroupEnum.SELECTOR, namespaceId)); } @Override - protected void afterProxySelectorChanged(final List<ProxySelectorData> changed, final DataEventTypeEnum eventType) { - scheduler.execute(new DataChangeTask(ConfigGroupEnum.PROXY_SELECTOR)); + protected void afterProxySelectorChanged(final List<ProxySelectorData> changed, final DataEventTypeEnum eventType, final String namespaceId) { + scheduler.execute(new DataChangeTask(ConfigGroupEnum.PROXY_SELECTOR, namespaceId)); } @Override - protected void afterDiscoveryUpstreamDataChanged(final List<DiscoverySyncData> changed, final DataEventTypeEnum eventType) { - scheduler.execute(new DataChangeTask(ConfigGroupEnum.DISCOVER_UPSTREAM)); + protected void afterDiscoveryUpstreamDataChanged(final List<DiscoverySyncData> changed, final DataEventTypeEnum eventType, final String namespaceId) { + scheduler.execute(new DataChangeTask(ConfigGroupEnum.DISCOVER_UPSTREAM, namespaceId)); } private List<ConfigGroupEnum> compareChangedGroup(final HttpServletRequest request) { List<ConfigGroupEnum> changedGroup = new ArrayList<>(ConfigGroupEnum.values().length); + String namespaceId = getNamespaceId(request); for (ConfigGroupEnum group : ConfigGroupEnum.values()) { // md5,lastModifyTime String[] params = StringUtils.split(request.getParameter(group.name()), ','); @@ -187,7 +194,8 @@ public class HttpLongPollingDataChangedListener extends AbstractDataChangedListe } String clientMd5 = params[0]; long clientModifyTime = NumberUtils.toLong(params[1]); - ConfigDataCache serverCache = CACHE.get(group.name()); + + ConfigDataCache serverCache = CACHE.get(buildCacheKey(namespaceId, group.name())); // do check. if (this.checkCacheDelayAndUpdate(serverCache, clientMd5, clientModifyTime)) { changedGroup.add(group); @@ -196,6 +204,10 @@ public class HttpLongPollingDataChangedListener extends AbstractDataChangedListe return changedGroup; } + public static String buildCacheKey(final String namespaceId, final String group) { + return namespaceId + "_" + group; + } + /** * check whether the client needs to update the cache. * @@ -218,17 +230,20 @@ public class HttpLongPollingDataChangedListener extends AbstractDataChangedListe // the lastModifyTime before client, then the local cache needs to be updated. // Considering the concurrency problem, admin must lock, // otherwise it may cause the request from shenyu-web to update the cache concurrently, causing excessive db pressure - ConfigDataCache latest = CACHE.get(serverCache.getGroup()); + + String configDataCacheKey = buildCacheKey(serverCache.getNamespaceId(), serverCache.getGroup()); + + ConfigDataCache latest = CACHE.get(configDataCacheKey); if (latest != serverCache) { return !StringUtils.equals(clientMd5, latest.getMd5()); } synchronized (this) { - latest = CACHE.get(serverCache.getGroup()); + latest = CACHE.get(configDataCacheKey); if (latest != serverCache) { return !StringUtils.equals(clientMd5, latest.getMd5()); } super.refreshLocalCache(); - latest = CACHE.get(serverCache.getGroup()); + latest = CACHE.get(configDataCacheKey); return !StringUtils.equals(clientMd5, latest.getMd5()); } } @@ -267,6 +282,20 @@ public class HttpLongPollingDataChangedListener extends AbstractDataChangedListe return StringUtils.isBlank(header) ? request.getRemoteAddr() : header; } + /** + * get namespaceId. + * + * @param request the request + * @return the namespaceId + */ + private static String getNamespaceId(final HttpServletRequest request) { + String namespaceId = SYS_DEFAULT_NAMESPACE_ID; + if (StringUtils.isNotEmpty(request.getParameter("namespaceId"))) { + namespaceId = request.getParameter("namespaceId"); + } + return namespaceId; + } + /** * When a group's data changes, the thread is created to notify the client asynchronously. */ @@ -282,24 +311,34 @@ public class HttpLongPollingDataChangedListener extends AbstractDataChangedListe */ private final long changeTime = System.currentTimeMillis(); + /** + * The namespaceId. + */ + private final String namespaceId; + /** * Instantiates a new Data change task. * * @param groupKey the group key */ - DataChangeTask(final ConfigGroupEnum groupKey) { + DataChangeTask(final ConfigGroupEnum groupKey, final String namespaceId) { this.groupKey = groupKey; + this.namespaceId = namespaceId; } @Override public void run() { - if (clients.size() > httpSyncProperties.getNotifyBatchSize()) { - List<LongPollingClient> targetClients = new ArrayList<>(clients.size()); - clients.drainTo(targetClients); + BlockingQueue<LongPollingClient> namespaceClients = clientsMap.get(namespaceId); + if (CollectionUtils.isEmpty(namespaceClients)) { + return; + } + if (namespaceClients.size() > httpSyncProperties.getNotifyBatchSize()) { + List<LongPollingClient> targetClients = new ArrayList<>(namespaceClients.size()); + namespaceClients.drainTo(targetClients); List<List<LongPollingClient>> partitionClients = Lists.partition(targetClients, httpSyncProperties.getNotifyBatchSize()); partitionClients.forEach(item -> scheduler.execute(() -> doRun(item))); } else { - doRun(clients); + doRun(namespaceClients); } } @@ -337,6 +376,11 @@ public class HttpLongPollingDataChangedListener extends AbstractDataChangedListe */ private final long timeoutTime; + /** + * The namespaceId. + */ + private final String namespaceId; + /** * The Async timeout future. */ @@ -349,22 +393,25 @@ public class HttpLongPollingDataChangedListener extends AbstractDataChangedListe * @param ip the ip * @param timeoutTime the timeout time */ - LongPollingClient(final AsyncContext ac, final String ip, final long timeoutTime) { + LongPollingClient(final AsyncContext ac, final String ip, final long timeoutTime, final String namespaceId) { this.asyncContext = ac; this.ip = ip; this.timeoutTime = timeoutTime; + this.namespaceId = namespaceId; } @Override public void run() { try { + BlockingQueue<LongPollingClient> namespaceClients = clientsMap.getOrDefault(namespaceId, new ArrayBlockingQueue<>(1024)); this.asyncTimeoutFuture = scheduler.schedule(() -> { - clients.remove(LongPollingClient.this); + namespaceClients.remove(LongPollingClient.this); List<ConfigGroupEnum> changedGroups = compareChangedGroup((HttpServletRequest) asyncContext.getRequest()); sendResponse(changedGroups); log.debug("LongPollingClient {} ", GsonUtils.getInstance().toJson(changedGroups)); }, timeoutTime, TimeUnit.MILLISECONDS); - clients.add(this); + namespaceClients.add(this); + clientsMap.put(namespaceId, namespaceClients); } catch (Exception ex) { log.error("add long polling client error", ex); } diff --git a/shenyu-admin/src/main/java/org/apache/shenyu/admin/mapper/NamespaceMapper.java b/shenyu-admin/src/main/java/org/apache/shenyu/admin/mapper/NamespaceMapper.java index 06b16e6c9d..f9612d855f 100644 --- a/shenyu-admin/src/main/java/org/apache/shenyu/admin/mapper/NamespaceMapper.java +++ b/shenyu-admin/src/main/java/org/apache/shenyu/admin/mapper/NamespaceMapper.java @@ -64,7 +64,14 @@ public interface NamespaceMapper extends ExistProvider { * @param name name. * @return namespaceDOList */ - List<NamespaceDO> selectAll(String name); + List<NamespaceDO> selectAllByName(String name); + + /** + * selectAll. + * + * @return namespaceDOList + */ + List<NamespaceDO> selectAll(); /** * insert namespace. diff --git a/shenyu-admin/src/main/java/org/apache/shenyu/admin/model/entity/RuleDO.java b/shenyu-admin/src/main/java/org/apache/shenyu/admin/model/entity/RuleDO.java index 4d0a102927..bddf298ece 100644 --- a/shenyu-admin/src/main/java/org/apache/shenyu/admin/model/entity/RuleDO.java +++ b/shenyu-admin/src/main/java/org/apache/shenyu/admin/model/entity/RuleDO.java @@ -329,6 +329,7 @@ public final class RuleDO extends BaseDO { .matchRestful(ruleDO.getMatchRestful()) .conditionDataList(conditionDataList) .beforeConditionDataList(beforeConditionDataList) + .namespaceId(ruleDO.getNamespaceId()) .build(); } diff --git a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/NamespaceService.java b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/NamespaceService.java index 9cc581d5b2..a5236284c4 100644 --- a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/NamespaceService.java +++ b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/NamespaceService.java @@ -65,4 +65,11 @@ public interface NamespaceService { * @return {@linkplain List} */ List<NamespaceVO> list(String name); + + /** + * find list of namespace. + * + * @return {@linkplain List} + */ + List<NamespaceVO> listAll(); } diff --git a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/DiscoveryServiceImpl.java b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/DiscoveryServiceImpl.java index ab4bcf7331..83a20e2b63 100644 --- a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/DiscoveryServiceImpl.java +++ b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/DiscoveryServiceImpl.java @@ -262,6 +262,7 @@ public class DiscoveryServiceImpl implements DiscoveryService { proxySelectorDTO.setPluginName(d.getPluginName()); proxySelectorDTO.setName(selectorDO.getName()); proxySelectorDTO.setId(selectorDO.getId()); + proxySelectorDTO.setNamespaceId(selectorDO.getNamespaceId()); DiscoveryHandlerDO discoveryHandlerDO = discoveryHandlerMapper.selectBySelectorId(selectorDO.getId()); discoveryProcessor.createProxySelector(DiscoveryTransfer.INSTANCE.mapToDTO(discoveryHandlerDO), proxySelectorDTO); discoveryProcessor.fetchAll(DiscoveryTransfer.INSTANCE.mapToDTO(discoveryHandlerDO), proxySelectorDTO); diff --git a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/NamespaceServiceImpl.java b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/NamespaceServiceImpl.java index 7adc399f4b..c647bf1eca 100644 --- a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/NamespaceServiceImpl.java +++ b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/NamespaceServiceImpl.java @@ -99,10 +99,17 @@ public class NamespaceServiceImpl implements NamespaceService { @Override public List<NamespaceVO> list(final String name) { - List<NamespaceDO> namespaceDOS = namespaceMapper.selectAll(name); + List<NamespaceDO> namespaceDOS = namespaceMapper.selectAllByName(name); return namespaceDOS.stream().map(NamespaceTransfer.INSTANCE::mapToVo).collect(Collectors.toList()); } + @Override + public List<NamespaceVO> listAll() { + List<NamespaceDO> namespaceDOS = namespaceMapper.selectAll(); + return namespaceDOS.stream().map(NamespaceTransfer.INSTANCE::mapToVo).collect(Collectors.toList()); + + } + private NamespaceVO create(final NamespaceDTO namespaceDTO) { Timestamp currentTime = new Timestamp(System.currentTimeMillis()); String id = UUIDUtils.getInstance().generateShortUuid(); diff --git a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/SelectorServiceImpl.java b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/SelectorServiceImpl.java index 9e7be95214..79f8974d50 100644 --- a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/SelectorServiceImpl.java +++ b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/SelectorServiceImpl.java @@ -295,10 +295,11 @@ public class SelectorServiceImpl implements SelectorService { discoveryUpstreamMapper.deleteByDiscoveryHandlerId(discoveryHandlerDO.getId()); DiscoveryDO discoveryDO = discoveryMapper.selectById(discoveryHandlerDO.getDiscoveryId()); if (Objects.nonNull(discoveryDO)) { - DiscoveryProcessor discoveryProcessor = discoveryProcessorHolder.chooseProcessor(discoveryDO.getType()); + final DiscoveryProcessor discoveryProcessor = discoveryProcessorHolder.chooseProcessor(discoveryDO.getType()); ProxySelectorDTO proxySelectorDTO = new ProxySelectorDTO(); proxySelectorDTO.setName(selector.getName()); proxySelectorDTO.setPluginName(pluginMap.getOrDefault(selector.getId(), "")); + proxySelectorDTO.setNamespaceId(selector.getNamespaceId()); discoveryProcessor.removeProxySelector(DiscoveryTransfer.INSTANCE.mapToDTO(discoveryHandlerDO), proxySelectorDTO); if (DiscoveryLevel.SELECTOR.getCode().equals(discoveryDO.getLevel())) { discoveryProcessor.removeDiscovery(discoveryDO); diff --git a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/UpstreamCheckService.java b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/UpstreamCheckService.java index 0cd3e6573f..ac39f46d1c 100644 --- a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/UpstreamCheckService.java +++ b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/UpstreamCheckService.java @@ -432,6 +432,7 @@ public class UpstreamCheckService { discoverySyncData.setPluginName(pluginName); discoverySyncData.setSelectorId(selectorId); discoverySyncData.setSelectorName(selectorDO.getName()); + discoverySyncData.setNamespaceId(selectorDO.getNamespaceId()); LOG.debug("UpstreamCacheManager update selectorId={}|json={}", selectorId, GsonUtils.getGson().toJson(discoverySyncData)); eventPublisher.publishEvent(new DataChangedEvent(ConfigGroupEnum.DISCOVER_UPSTREAM, DataEventTypeEnum.UPDATE, Collections.singletonList(discoverySyncData))); } diff --git a/shenyu-admin/src/main/java/org/apache/shenyu/admin/transfer/DiscoveryTransfer.java b/shenyu-admin/src/main/java/org/apache/shenyu/admin/transfer/DiscoveryTransfer.java index cec29e0c88..9209248e2d 100644 --- a/shenyu-admin/src/main/java/org/apache/shenyu/admin/transfer/DiscoveryTransfer.java +++ b/shenyu-admin/src/main/java/org/apache/shenyu/admin/transfer/DiscoveryTransfer.java @@ -229,6 +229,7 @@ public enum DiscoveryTransfer { proxySelectorData.setPluginName(data.getPluginName()); proxySelectorData.setType(data.getType()); proxySelectorData.setForwardPort(data.getForwardPort()); + proxySelectorData.setNamespaceId(data.getNamespaceId()); String props = data.getProps(); Properties properties = GsonUtils.getInstance().fromJson(props, Properties.class); proxySelectorData.setProps(properties); diff --git a/shenyu-admin/src/main/java/org/apache/shenyu/admin/transfer/MetaDataTransfer.java b/shenyu-admin/src/main/java/org/apache/shenyu/admin/transfer/MetaDataTransfer.java index 6f8dbaaaad..427ade08b6 100644 --- a/shenyu-admin/src/main/java/org/apache/shenyu/admin/transfer/MetaDataTransfer.java +++ b/shenyu-admin/src/main/java/org/apache/shenyu/admin/transfer/MetaDataTransfer.java @@ -149,6 +149,7 @@ public enum MetaDataTransfer { .parameterTypes(v.getParameterTypes()) .rpcExt(v.getRpcExt()) .enabled(v.getEnabled()) + .namespaceId(v.getNamespaceId()) .build()) .orElse(null); } diff --git a/shenyu-admin/src/main/resources/mappers/namespace-sqlmap.xml b/shenyu-admin/src/main/resources/mappers/namespace-sqlmap.xml index b7802ce67a..6271aab533 100644 --- a/shenyu-admin/src/main/resources/mappers/namespace-sqlmap.xml +++ b/shenyu-admin/src/main/resources/mappers/namespace-sqlmap.xml @@ -56,7 +56,7 @@ WHERE namespace_id = #{namespaceId, jdbcType=VARCHAR} </select> - <select id="selectAll" resultType="org.apache.shenyu.admin.model.entity.NamespaceDO"> + <select id="selectAllByName" resultType="org.apache.shenyu.admin.model.entity.NamespaceDO"> SELECT <include refid="Base_Column_List"/> FROM namespace @@ -67,6 +67,12 @@ </where> </select> + <select id="selectAll" resultType="org.apache.shenyu.admin.model.entity.NamespaceDO"> + SELECT + <include refid="Base_Column_List"/> + FROM namespace + </select> + <insert id="insert" keyColumn="id" keyProperty="id" useGeneratedKeys="true" parameterType="org.apache.shenyu.admin.model.entity.NamespaceDO"> INSERT INTO namespace diff --git a/shenyu-admin/src/test/java/org/apache/shenyu/admin/controller/ConfigControllerTest.java b/shenyu-admin/src/test/java/org/apache/shenyu/admin/controller/ConfigControllerTest.java index 5ff5c2c473..70a098994c 100644 --- a/shenyu-admin/src/test/java/org/apache/shenyu/admin/controller/ConfigControllerTest.java +++ b/shenyu-admin/src/test/java/org/apache/shenyu/admin/controller/ConfigControllerTest.java @@ -18,6 +18,8 @@ package org.apache.shenyu.admin.controller; import org.apache.shenyu.admin.listener.http.HttpLongPollingDataChangedListener; +import org.apache.shenyu.admin.model.vo.NamespaceVO; +import org.apache.shenyu.admin.service.NamespaceService; import org.apache.shenyu.admin.utils.ShenyuResultMessage; import org.apache.shenyu.common.dto.ConfigData; import org.apache.shenyu.common.enums.ConfigGroupEnum; @@ -36,8 +38,10 @@ import org.springframework.test.web.servlet.setup.MockMvcBuilders; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; + import java.util.Collections; +import static org.apache.shenyu.common.constant.Constants.SYS_DEFAULT_NAMESPACE_ID; import static org.assertj.core.api.Assertions.assertThat; import static org.hamcrest.core.Is.is; import static org.mockito.ArgumentMatchers.any; @@ -62,6 +66,9 @@ public final class ConfigControllerTest { @Mock private HttpLongPollingDataChangedListener mockLongPollingListener; + @Mock + private NamespaceService namespaceService; + @BeforeEach public void setUp() { this.mockMvc = MockMvcBuilders.standaloneSetup(configController).build(); @@ -71,12 +78,14 @@ public final class ConfigControllerTest { public void testFetchConfigs() throws Exception { // Configure HttpLongPollingDataChangedListener.fetchConfig(...). final ConfigData<?> configData = new ConfigData<>("md5-value1", 0L, Collections.emptyList()); - doReturn(configData).when(mockLongPollingListener).fetchConfig(ConfigGroupEnum.APP_AUTH); - + final NamespaceVO namespaceVO = new NamespaceVO(); + doReturn(configData).when(mockLongPollingListener).fetchConfig(ConfigGroupEnum.APP_AUTH, SYS_DEFAULT_NAMESPACE_ID); + doReturn(namespaceVO).when(namespaceService).findById(SYS_DEFAULT_NAMESPACE_ID); // Run the test final MockHttpServletResponse response = mockMvc.perform(get("/configs/fetch") - .param("groupKeys", new String[]{ConfigGroupEnum.APP_AUTH.toString()}) - .accept(MediaType.APPLICATION_JSON)) + .param("groupKeys", new String[]{ConfigGroupEnum.APP_AUTH.toString()}) + .param("namespaceId", SYS_DEFAULT_NAMESPACE_ID) + .accept(MediaType.APPLICATION_JSON)) .andExpect(status().isOk()) .andExpect(jsonPath("$.message", is(ShenyuResultMessage.SUCCESS))) .andExpect(jsonPath("$.data['APP_AUTH'].md5", is("md5-value1"))) @@ -90,7 +99,7 @@ public final class ConfigControllerTest { public void testListener() throws Exception { // Run the test final MockHttpServletResponse response = mockMvc.perform(post("/configs/listener") - .accept(MediaType.APPLICATION_JSON)) + .accept(MediaType.APPLICATION_JSON)) .andReturn().getResponse(); // Verify the results diff --git a/shenyu-admin/src/test/java/org/apache/shenyu/admin/listener/AbstractDataChangedListenerTest.java b/shenyu-admin/src/test/java/org/apache/shenyu/admin/listener/AbstractDataChangedListenerTest.java index 9c3f492331..abcf5d1424 100644 --- a/shenyu-admin/src/test/java/org/apache/shenyu/admin/listener/AbstractDataChangedListenerTest.java +++ b/shenyu-admin/src/test/java/org/apache/shenyu/admin/listener/AbstractDataChangedListenerTest.java @@ -18,10 +18,13 @@ package org.apache.shenyu.admin.listener; import com.google.common.collect.Lists; +import org.apache.shenyu.admin.listener.http.HttpLongPollingDataChangedListener; +import org.apache.shenyu.admin.model.vo.NamespaceVO; import org.apache.shenyu.admin.service.AppAuthService; import org.apache.shenyu.admin.service.DiscoveryUpstreamService; import org.apache.shenyu.admin.service.MetaDataService; import org.apache.shenyu.admin.service.NamespacePluginService; +import org.apache.shenyu.admin.service.NamespaceService; import org.apache.shenyu.admin.service.ProxySelectorService; import org.apache.shenyu.admin.service.RuleService; import org.apache.shenyu.admin.service.SelectorService; @@ -40,9 +43,11 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import java.lang.reflect.Field; +import java.util.ArrayList; import java.util.List; import java.util.concurrent.ConcurrentMap; +import static org.apache.shenyu.common.constant.Constants.SYS_DEFAULT_NAMESPACE_ID; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -70,6 +75,8 @@ public final class AbstractDataChangedListenerTest { private DiscoveryUpstreamService discoveryUpstreamService; + private NamespaceService namespaceService; + @BeforeEach public void setUp() throws Exception { listener = new MockAbstractDataChangedListener(); @@ -80,6 +87,7 @@ public final class AbstractDataChangedListenerTest { metaDataService = mock(MetaDataService.class); proxySelectorService = mock(ProxySelectorService.class); discoveryUpstreamService = mock(DiscoveryUpstreamService.class); + namespaceService = mock(NamespaceService.class); Class clazz = MockAbstractDataChangedListener.class.getSuperclass(); Field appAuthServiceField = clazz.getDeclaredField("appAuthService"); @@ -103,11 +111,14 @@ public final class AbstractDataChangedListenerTest { Field discoveryUpstreamServiceField = clazz.getDeclaredField("discoveryUpstreamService"); discoveryUpstreamServiceField.setAccessible(true); discoveryUpstreamServiceField.set(listener, discoveryUpstreamService); + Field namespaceServiceField = clazz.getDeclaredField("namespaceService"); + namespaceServiceField.setAccessible(true); + namespaceServiceField.set(listener, namespaceService); List<AppAuthData> appAuthDatas = Lists.newArrayList(mock(AppAuthData.class)); when(appAuthService.listAll()).thenReturn(appAuthDatas); List<PluginData> pluginDatas = Lists.newArrayList(mock(PluginData.class)); - when(namespacePluginService.listAll()).thenReturn(pluginDatas); + when(namespacePluginService.listAll(SYS_DEFAULT_NAMESPACE_ID)).thenReturn(pluginDatas); List<RuleData> ruleDatas = Lists.newArrayList(mock(RuleData.class)); when(ruleService.listAll()).thenReturn(ruleDatas); List<SelectorData> selectorDatas = Lists.newArrayList(mock(SelectorData.class)); @@ -118,7 +129,12 @@ public final class AbstractDataChangedListenerTest { when(proxySelectorService.listAll()).thenReturn(proxySelectorDatas); List<DiscoverySyncData> discoverySyncDatas = Lists.newArrayList(mock(DiscoverySyncData.class)); when(discoveryUpstreamService.listAll()).thenReturn(discoverySyncDatas); - + List<NamespaceVO> list = new ArrayList<>(); + NamespaceVO namespaceVO = new NamespaceVO(); + namespaceVO.setNamespaceId(SYS_DEFAULT_NAMESPACE_ID); + list.add(namespaceVO); + when(namespaceService.listAll()).thenReturn(list); + // clear first listener.getCache().clear(); } @@ -131,28 +147,28 @@ public final class AbstractDataChangedListenerTest { @Test public void testFetchConfig() { List<AppAuthData> appAuthDatas = Lists.newArrayList(mock(AppAuthData.class)); - listener.updateCache(ConfigGroupEnum.APP_AUTH, appAuthDatas); - ConfigData<?> result1 = listener.fetchConfig(ConfigGroupEnum.APP_AUTH); + listener.updateCache(ConfigGroupEnum.APP_AUTH, appAuthDatas, SYS_DEFAULT_NAMESPACE_ID); + ConfigData<?> result1 = listener.fetchConfig(ConfigGroupEnum.APP_AUTH, SYS_DEFAULT_NAMESPACE_ID); assertNotNull(result1); List<PluginData> pluginDatas = Lists.newArrayList(mock(PluginData.class)); - listener.updateCache(ConfigGroupEnum.PLUGIN, pluginDatas); - ConfigData<?> result2 = listener.fetchConfig(ConfigGroupEnum.PLUGIN); + listener.updateCache(ConfigGroupEnum.PLUGIN, pluginDatas, SYS_DEFAULT_NAMESPACE_ID); + ConfigData<?> result2 = listener.fetchConfig(ConfigGroupEnum.PLUGIN, SYS_DEFAULT_NAMESPACE_ID); assertNotNull(result2); List<RuleData> ruleDatas = Lists.newArrayList(mock(RuleData.class)); - listener.updateCache(ConfigGroupEnum.RULE, ruleDatas); - ConfigData<?> result3 = listener.fetchConfig(ConfigGroupEnum.RULE); + listener.updateCache(ConfigGroupEnum.RULE, ruleDatas, SYS_DEFAULT_NAMESPACE_ID); + ConfigData<?> result3 = listener.fetchConfig(ConfigGroupEnum.RULE, SYS_DEFAULT_NAMESPACE_ID); assertNotNull(result3); List<SelectorData> selectorDatas = Lists.newArrayList(mock(SelectorData.class)); - listener.updateCache(ConfigGroupEnum.SELECTOR, selectorDatas); - ConfigData<?> result4 = listener.fetchConfig(ConfigGroupEnum.SELECTOR); + listener.updateCache(ConfigGroupEnum.SELECTOR, selectorDatas, SYS_DEFAULT_NAMESPACE_ID); + ConfigData<?> result4 = listener.fetchConfig(ConfigGroupEnum.SELECTOR, SYS_DEFAULT_NAMESPACE_ID); assertNotNull(result4); List<MetaData> metaDatas = Lists.newArrayList(mock(MetaData.class)); - listener.updateCache(ConfigGroupEnum.META_DATA, metaDatas); - ConfigData<?> result5 = listener.fetchConfig(ConfigGroupEnum.META_DATA); + listener.updateCache(ConfigGroupEnum.META_DATA, metaDatas, SYS_DEFAULT_NAMESPACE_ID); + ConfigData<?> result5 = listener.fetchConfig(ConfigGroupEnum.META_DATA, SYS_DEFAULT_NAMESPACE_ID); assertNotNull(result5); } @@ -161,10 +177,10 @@ public final class AbstractDataChangedListenerTest { List<AppAuthData> empty = Lists.newArrayList(); DataEventTypeEnum eventType = mock(DataEventTypeEnum.class); listener.onAppAuthChanged(empty, eventType); - assertFalse(listener.getCache().containsKey(ConfigGroupEnum.APP_AUTH.name())); + assertFalse(listener.getCache().containsKey(HttpLongPollingDataChangedListener.buildCacheKey(SYS_DEFAULT_NAMESPACE_ID, ConfigGroupEnum.APP_AUTH.name()))); List<AppAuthData> appAuthDatas = Lists.newArrayList(mock(AppAuthData.class)); listener.onAppAuthChanged(appAuthDatas, eventType); - assertTrue(listener.getCache().containsKey(ConfigGroupEnum.APP_AUTH.name())); + assertTrue(listener.getCache().containsKey(HttpLongPollingDataChangedListener.buildCacheKey(SYS_DEFAULT_NAMESPACE_ID, ConfigGroupEnum.APP_AUTH.name()))); } @Test @@ -172,10 +188,10 @@ public final class AbstractDataChangedListenerTest { List<MetaData> empty = Lists.newArrayList(); DataEventTypeEnum eventType = mock(DataEventTypeEnum.class); listener.onMetaDataChanged(empty, eventType); - assertFalse(listener.getCache().containsKey(ConfigGroupEnum.META_DATA.name())); + assertFalse(listener.getCache().containsKey(HttpLongPollingDataChangedListener.buildCacheKey(SYS_DEFAULT_NAMESPACE_ID, ConfigGroupEnum.META_DATA.name()))); List<MetaData> metaDatas = Lists.newArrayList(mock(MetaData.class)); listener.onMetaDataChanged(metaDatas, eventType); - assertTrue(listener.getCache().containsKey(ConfigGroupEnum.META_DATA.name())); + assertTrue(listener.getCache().containsKey(HttpLongPollingDataChangedListener.buildCacheKey(SYS_DEFAULT_NAMESPACE_ID, ConfigGroupEnum.META_DATA.name()))); } @Test @@ -183,10 +199,13 @@ public final class AbstractDataChangedListenerTest { List<PluginData> empty = Lists.newArrayList(); DataEventTypeEnum eventType = mock(DataEventTypeEnum.class); listener.onPluginChanged(empty, eventType); - assertFalse(listener.getCache().containsKey(ConfigGroupEnum.PLUGIN.name())); + assertFalse(listener.getCache().containsKey(HttpLongPollingDataChangedListener.buildCacheKey(SYS_DEFAULT_NAMESPACE_ID, ConfigGroupEnum.PLUGIN.name()))); List<PluginData> pluginDatas = Lists.newArrayList(mock(PluginData.class)); + PluginData pluginData = new PluginData(); + pluginData.setNamespaceId(SYS_DEFAULT_NAMESPACE_ID); + pluginDatas.set(0, pluginData); listener.onPluginChanged(pluginDatas, eventType); - assertTrue(listener.getCache().containsKey(ConfigGroupEnum.PLUGIN.name())); + assertTrue(listener.getCache().containsKey(HttpLongPollingDataChangedListener.buildCacheKey(SYS_DEFAULT_NAMESPACE_ID, ConfigGroupEnum.PLUGIN.name()))); } @Test @@ -194,10 +213,10 @@ public final class AbstractDataChangedListenerTest { List<RuleData> empty = Lists.newArrayList(); DataEventTypeEnum eventType = mock(DataEventTypeEnum.class); listener.onRuleChanged(empty, eventType); - assertFalse(listener.getCache().containsKey(ConfigGroupEnum.RULE.name())); + assertFalse(listener.getCache().containsKey(HttpLongPollingDataChangedListener.buildCacheKey(SYS_DEFAULT_NAMESPACE_ID, ConfigGroupEnum.RULE.name()))); List<RuleData> ruleDatas = Lists.newArrayList(mock(RuleData.class)); listener.onRuleChanged(ruleDatas, eventType); - assertTrue(listener.getCache().containsKey(ConfigGroupEnum.RULE.name())); + assertTrue(listener.getCache().containsKey(HttpLongPollingDataChangedListener.buildCacheKey(SYS_DEFAULT_NAMESPACE_ID, ConfigGroupEnum.RULE.name()))); } @Test @@ -205,27 +224,27 @@ public final class AbstractDataChangedListenerTest { List<SelectorData> empty = Lists.newArrayList(); DataEventTypeEnum eventType = mock(DataEventTypeEnum.class); listener.onSelectorChanged(empty, eventType); - assertFalse(listener.getCache().containsKey(ConfigGroupEnum.SELECTOR.name())); + assertFalse(listener.getCache().containsKey(HttpLongPollingDataChangedListener.buildCacheKey(SYS_DEFAULT_NAMESPACE_ID, ConfigGroupEnum.SELECTOR.name()))); List<SelectorData> selectorDatas = Lists.newArrayList(mock(SelectorData.class)); listener.onSelectorChanged(selectorDatas, eventType); - assertTrue(listener.getCache().containsKey(ConfigGroupEnum.SELECTOR.name())); + assertTrue(listener.getCache().containsKey(HttpLongPollingDataChangedListener.buildCacheKey(SYS_DEFAULT_NAMESPACE_ID, ConfigGroupEnum.SELECTOR.name()))); } @Test public void testAfterPropertiesSet() { listener.afterPropertiesSet(); - assertTrue(listener.getCache().containsKey(ConfigGroupEnum.APP_AUTH.name())); - assertTrue(listener.getCache().containsKey(ConfigGroupEnum.PLUGIN.name())); - assertTrue(listener.getCache().containsKey(ConfigGroupEnum.RULE.name())); - assertTrue(listener.getCache().containsKey(ConfigGroupEnum.SELECTOR.name())); - assertTrue(listener.getCache().containsKey(ConfigGroupEnum.META_DATA.name())); + assertTrue(listener.getCache().containsKey(HttpLongPollingDataChangedListener.buildCacheKey(SYS_DEFAULT_NAMESPACE_ID, ConfigGroupEnum.APP_AUTH.name()))); + assertTrue(listener.getCache().containsKey(HttpLongPollingDataChangedListener.buildCacheKey(SYS_DEFAULT_NAMESPACE_ID, ConfigGroupEnum.PLUGIN.name()))); + assertTrue(listener.getCache().containsKey(HttpLongPollingDataChangedListener.buildCacheKey(SYS_DEFAULT_NAMESPACE_ID, ConfigGroupEnum.RULE.name()))); + assertTrue(listener.getCache().containsKey(HttpLongPollingDataChangedListener.buildCacheKey(SYS_DEFAULT_NAMESPACE_ID, ConfigGroupEnum.SELECTOR.name()))); + assertTrue(listener.getCache().containsKey(HttpLongPollingDataChangedListener.buildCacheKey(SYS_DEFAULT_NAMESPACE_ID, ConfigGroupEnum.META_DATA.name()))); } @Test public void testUpdateCache() { List<AppAuthData> appAuthDatas = Lists.newArrayList(mock(AppAuthData.class)); - listener.updateCache(ConfigGroupEnum.APP_AUTH, appAuthDatas); - assertTrue(listener.getCache().containsKey(ConfigGroupEnum.APP_AUTH.name())); + listener.updateCache(ConfigGroupEnum.APP_AUTH, appAuthDatas, SYS_DEFAULT_NAMESPACE_ID); + assertTrue(listener.getCache().containsKey(HttpLongPollingDataChangedListener.buildCacheKey(SYS_DEFAULT_NAMESPACE_ID, ConfigGroupEnum.APP_AUTH.name()))); } static class MockAbstractDataChangedListener extends AbstractDataChangedListener { diff --git a/shenyu-admin/src/test/java/org/apache/shenyu/admin/listener/ConfigDataCacheTest.java b/shenyu-admin/src/test/java/org/apache/shenyu/admin/listener/ConfigDataCacheTest.java index de4601058e..eb5f160f42 100644 --- a/shenyu-admin/src/test/java/org/apache/shenyu/admin/listener/ConfigDataCacheTest.java +++ b/shenyu-admin/src/test/java/org/apache/shenyu/admin/listener/ConfigDataCacheTest.java @@ -31,7 +31,8 @@ public final class ConfigDataCacheTest { String group = "default"; String json = "{\"name\":\"shenyu\"}"; String md51 = "8e8a3a2fdbd4368f169aa88c5fdce5a1"; - ConfigDataCache cache = new ConfigDataCache(group, json, md51, 0); + String namespaceId = "649330b6-c2d7-4edc-be8e-8a54df9eb385"; + ConfigDataCache cache = new ConfigDataCache(group, json, md51, 0, namespaceId); assertEquals(cache.getMd5(), md51); assertEquals(cache.getJson(), json); assertEquals(cache.getGroup(), group); 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 d39379bd82..13dc09c8c3 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 @@ -70,9 +70,9 @@ public class ShenyuConfig { private SpringCloudCacheConfig springCloudCache = new SpringCloudCacheConfig(); private AlertConfig alert = new AlertConfig(); - + private String namespace = Constants.SYS_DEFAULT_NAMESPACE_ID; - + /** * shenyu bootstrap namespace. * @@ -81,7 +81,7 @@ public class ShenyuConfig { public String getNamespace() { return namespace; } - + /** * Set shenyu bootstrap namespace, default value is {@link org.apache.shenyu.common.constant.Constants#SYS_DEFAULT_NAMESPACE_ID}. * @@ -90,7 +90,7 @@ public class ShenyuConfig { public void setNamespace(final String namespace) { this.namespace = namespace; } - + /** * Gets health. * diff --git a/shenyu-common/src/main/java/org/apache/shenyu/common/dto/ProxySelectorData.java b/shenyu-common/src/main/java/org/apache/shenyu/common/dto/ProxySelectorData.java index 0f28eedbb2..1ab2bc6759 100644 --- a/shenyu-common/src/main/java/org/apache/shenyu/common/dto/ProxySelectorData.java +++ b/shenyu-common/src/main/java/org/apache/shenyu/common/dto/ProxySelectorData.java @@ -36,6 +36,8 @@ public class ProxySelectorData { private Properties props = new Properties(); + private String namespaceId; + /** * getId. * @@ -144,4 +146,22 @@ public class ProxySelectorData { this.props = props; } + /** + * get namespaceId. + * + * @return namespaceId + */ + public String getNamespaceId() { + return namespaceId; + } + + /** + * set namespaceId. + * + * @param namespaceId namespaceId + */ + public void setNamespaceId(final String namespaceId) { + this.namespaceId = namespaceId; + } + } diff --git a/shenyu-spring-boot-starter/shenyu-spring-boot-starter-sync-data-center/shenyu-spring-boot-starter-sync-data-http/src/main/java/org/apache/shenyu/springboot/starter/sync/data/http/HttpSyncDataConfiguration.java b/shenyu-spring-boot-starter/shenyu-spring-boot-starter-sync-data-center/shenyu-spring-boot-starter-sync-data-http/src/main/java/org/apache/shenyu/springboot/starter/sync/data/http/HttpSyncDataConfiguration.java index 8bc3059848..624bb7e5b6 100644 --- a/shenyu-spring-boot-starter/shenyu-spring-boot-starter-sync-data-center/shenyu-spring-boot-starter-sync-data-http/src/main/java/org/apache/shenyu/springboot/starter/sync/data/http/HttpSyncDataConfiguration.java +++ b/shenyu-spring-boot-starter/shenyu-spring-boot-starter-sync-data-center/shenyu-spring-boot-starter-sync-data-http/src/main/java/org/apache/shenyu/springboot/starter/sync/data/http/HttpSyncDataConfiguration.java @@ -17,6 +17,7 @@ package org.apache.shenyu.springboot.starter.sync.data.http; +import org.apache.shenyu.common.config.ShenyuConfig; import org.apache.shenyu.common.constant.HttpConstants; import org.apache.shenyu.sync.data.api.AuthDataSubscriber; import org.apache.shenyu.sync.data.api.MetaDataSubscriber; @@ -103,6 +104,7 @@ public class HttpSyncDataConfiguration { * @param accessTokenManager the access token manager * @param proxySelectorDataSubscribers the proxySelectorData subscribers * @param discoveryUpstreamDataSubscribers the discoveryUpstreamData subscribers + * @param shenyuConfig the shenyuConfig * @return the sync data service */ @Bean @@ -113,7 +115,8 @@ public class HttpSyncDataConfiguration { final ObjectProvider<List<AuthDataSubscriber>> authSubscribers, final ObjectProvider<AccessTokenManager> accessTokenManager, final ObjectProvider<List<ProxySelectorDataSubscriber>> proxySelectorDataSubscribers, - final ObjectProvider<List<DiscoveryUpstreamDataSubscriber>> discoveryUpstreamDataSubscribers) { + final ObjectProvider<List<DiscoveryUpstreamDataSubscriber>> discoveryUpstreamDataSubscribers, + final ObjectProvider<ShenyuConfig> shenyuConfig) { LOGGER.info("you use http long pull sync shenyu data"); return new HttpSyncDataService( Objects.requireNonNull(httpConfig.getIfAvailable()), @@ -123,7 +126,8 @@ public class HttpSyncDataConfiguration { authSubscribers.getIfAvailable(Collections::emptyList), proxySelectorDataSubscribers.getIfAvailable(Collections::emptyList), discoveryUpstreamDataSubscribers.getIfAvailable(Collections::emptyList), - Objects.requireNonNull(accessTokenManager.getIfAvailable()) + Objects.requireNonNull(accessTokenManager.getIfAvailable()), + Objects.requireNonNull(shenyuConfig.getIfAvailable()) ); } } diff --git a/shenyu-spring-boot-starter/shenyu-spring-boot-starter-sync-data-center/shenyu-spring-boot-starter-sync-data-http/src/test/java/org/apache/shenyu/springboot/starter/sync/data/http/HttpClientPluginConfigurationTest.java b/shenyu-spring-boot-starter/shenyu-spring-boot-starter-sync-data-center/shenyu-spring-boot-starter-sync-data-http/src/test/java/org/apache/shenyu/springboot/starter/sync/data/http/HttpClientPluginConfigurationTest.java index 2a6240b7fb..d99298f6e9 100644 --- a/shenyu-spring-boot-starter/shenyu-spring-boot-starter-sync-data-center/shenyu-spring-boot-starter-sync-data-http/src/test/java/org/apache/shenyu/springboot/starter/sync/data/http/HttpClientPluginConfigurationTest.java +++ b/shenyu-spring-boot-starter/shenyu-spring-boot-starter-sync-data-center/shenyu-spring-boot-starter-sync-data-http/src/test/java/org/apache/shenyu/springboot/starter/sync/data/http/HttpClientPluginConfigurationTest.java @@ -18,6 +18,7 @@ package org.apache.shenyu.springboot.starter.sync.data.http; import com.github.tomakehurst.wiremock.WireMockServer; +import org.apache.shenyu.common.config.ShenyuConfig; import org.apache.shenyu.common.exception.CommonErrorCode; import org.apache.shenyu.common.utils.GsonUtils; import org.apache.shenyu.sync.data.api.PluginDataSubscriber; @@ -68,7 +69,7 @@ import static org.junit.jupiter.api.Assertions.assertNotNull; "spring.main.web-application-type=none" }) @EnableAutoConfiguration -@MockBean({PluginDataSubscriber.class, ServletWebServerFactory.class}) +@MockBean({PluginDataSubscriber.class, ServletWebServerFactory.class, ShenyuConfig.class}) public final class HttpClientPluginConfigurationTest { @Autowired diff --git a/shenyu-sync-data-center/shenyu-sync-data-http/src/main/java/org/apache/shenyu/sync/data/http/HttpSyncDataService.java b/shenyu-sync-data-center/shenyu-sync-data-http/src/main/java/org/apache/shenyu/sync/data/http/HttpSyncDataService.java index 509bd12b51..1c268e90c0 100644 --- a/shenyu-sync-data-center/shenyu-sync-data-http/src/main/java/org/apache/shenyu/sync/data/http/HttpSyncDataService.java +++ b/shenyu-sync-data-center/shenyu-sync-data-http/src/main/java/org/apache/shenyu/sync/data/http/HttpSyncDataService.java @@ -21,8 +21,15 @@ import com.google.common.base.Splitter; import com.google.common.collect.Lists; import com.google.gson.JsonArray; import com.google.gson.JsonObject; +import okhttp3.Headers; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.RequestBody; +import okhttp3.Response; +import okhttp3.ResponseBody; import org.apache.commons.lang3.StringUtils; import org.apache.shenyu.common.concurrent.ShenyuThreadFactory; +import org.apache.shenyu.common.config.ShenyuConfig; import org.apache.shenyu.common.constant.Constants; import org.apache.shenyu.common.dto.ConfigData; import org.apache.shenyu.common.enums.ConfigGroupEnum; @@ -30,11 +37,11 @@ import org.apache.shenyu.common.exception.ShenyuException; import org.apache.shenyu.common.utils.GsonUtils; import org.apache.shenyu.common.utils.ThreadUtils; import org.apache.shenyu.sync.data.api.AuthDataSubscriber; +import org.apache.shenyu.sync.data.api.DiscoveryUpstreamDataSubscriber; import org.apache.shenyu.sync.data.api.MetaDataSubscriber; import org.apache.shenyu.sync.data.api.PluginDataSubscriber; -import org.apache.shenyu.sync.data.api.SyncDataService; import org.apache.shenyu.sync.data.api.ProxySelectorDataSubscriber; -import org.apache.shenyu.sync.data.api.DiscoveryUpstreamDataSubscriber; +import org.apache.shenyu.sync.data.api.SyncDataService; import org.apache.shenyu.sync.data.http.config.HttpConfig; import org.apache.shenyu.sync.data.http.refresh.DataRefreshFactory; import org.slf4j.Logger; @@ -53,12 +60,6 @@ import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; -import okhttp3.Headers; -import okhttp3.OkHttpClient; -import okhttp3.Request; -import okhttp3.RequestBody; -import okhttp3.Response; -import okhttp3.ResponseBody; /** * HTTP long polling implementation. @@ -79,9 +80,11 @@ public class HttpSyncDataService implements SyncDataService { private final DataRefreshFactory factory; private final AccessTokenManager accessTokenManager; - + private final OkHttpClient okHttpClient; + private final ShenyuConfig shenyuConfig; + public HttpSyncDataService(final HttpConfig httpConfig, final PluginDataSubscriber pluginDataSubscriber, final OkHttpClient okHttpClient, @@ -89,11 +92,13 @@ public class HttpSyncDataService implements SyncDataService { final List<AuthDataSubscriber> authDataSubscribers, final List<ProxySelectorDataSubscriber> proxySelectorDataSubscribers, final List<DiscoveryUpstreamDataSubscriber> discoveryUpstreamDataSubscribers, - final AccessTokenManager accessTokenManager) { + final AccessTokenManager accessTokenManager, + final ShenyuConfig shenyuConfig) { this.accessTokenManager = accessTokenManager; this.factory = new DataRefreshFactory(pluginDataSubscriber, metaDataSubscribers, authDataSubscribers, proxySelectorDataSubscribers, discoveryUpstreamDataSubscribers); this.serverList = Lists.newArrayList(Splitter.on(",").split(httpConfig.getUrl())); this.okHttpClient = okHttpClient; + this.shenyuConfig = shenyuConfig; this.start(); } @@ -134,6 +139,7 @@ public class HttpSyncDataService implements SyncDataService { for (ConfigGroupEnum groupKey : groups) { params.append("groupKeys").append("=").append(groupKey.name()).append("&"); } + params.append("namespaceId").append("=").append(shenyuConfig.getNamespace()); String url = server + Constants.SHENYU_ADMIN_PATH_CONFIGS_FETCH + "?" + StringUtils.removeEnd(params.toString(), "&"); LOG.info("request configs: [{}]", url); String json; @@ -188,6 +194,7 @@ public class HttpSyncDataService implements SyncDataService { params.put(group.name(), Lists.newArrayList(value)); } } + params.put("namespaceId", Lists.newArrayList(shenyuConfig.getNamespace())); LOG.debug("listener params: [{}]", params); Headers headers = new Headers.Builder() .add(Constants.X_ACCESS_TOKEN, this.accessTokenManager.getAccessToken()) @@ -217,7 +224,7 @@ public class HttpSyncDataService implements SyncDataService { String message = String.format("listener configs fail, server:[%s], %s", server, e.getMessage()); throw new ShenyuException(message, e); } - + if (Objects.nonNull(groupJson) && !groupJson.isEmpty()) { // fetch group configuration async. ConfigGroupEnum[] changedGroups = GsonUtils.getGson().fromJson(groupJson, ConfigGroupEnum[].class); diff --git a/shenyu-sync-data-center/shenyu-sync-data-http/src/test/java/org/apache/shenyu/sync/data/http/HttpSyncDataServiceTest.java b/shenyu-sync-data-center/shenyu-sync-data-http/src/test/java/org/apache/shenyu/sync/data/http/HttpSyncDataServiceTest.java index 6a9ae130c5..545369b6d5 100644 --- a/shenyu-sync-data-center/shenyu-sync-data-http/src/test/java/org/apache/shenyu/sync/data/http/HttpSyncDataServiceTest.java +++ b/shenyu-sync-data-center/shenyu-sync-data-http/src/test/java/org/apache/shenyu/sync/data/http/HttpSyncDataServiceTest.java @@ -19,6 +19,7 @@ package org.apache.shenyu.sync.data.http; import com.github.tomakehurst.wiremock.WireMockServer; import com.github.tomakehurst.wiremock.extension.responsetemplating.ResponseTemplateTransformer; +import org.apache.shenyu.common.config.ShenyuConfig; import org.apache.shenyu.common.constant.HttpConstants; import org.apache.shenyu.common.dto.ConfigData; import org.apache.shenyu.common.dto.PluginData; @@ -84,6 +85,8 @@ public final class HttpSyncDataServiceTest { private HttpSyncDataService httpSyncDataService; + private ShenyuConfig shenyuConfig; + @BeforeEach public void before() { this.wireMockServer = new WireMockServer( @@ -123,6 +126,7 @@ public final class HttpSyncDataServiceTest { this.authDataSubscriber = mock(AuthDataSubscriber.class); this.proxySelectorDataSubscriber = mock(ProxySelectorDataSubscriber.class); this.discoveryUpstreamDataSubscriber = mock(DiscoveryUpstreamDataSubscriber.class); + this.shenyuConfig = mock(ShenyuConfig.class); OkHttpClient okHttpClient = new OkHttpClient.Builder() .readTimeout(Duration.ofMillis(Objects.isNull(httpConfig.getReadTimeout()) ? (int) HttpConstants.CLIENT_POLLING_READ_TIMEOUT : httpConfig.getReadTimeout())) @@ -133,7 +137,7 @@ public final class HttpSyncDataServiceTest { AccessTokenManager accessTokenManager = new AccessTokenManager(okHttpClient, httpConfig); this.httpSyncDataService = new HttpSyncDataService(httpConfig, pluginDataSubscriber, new OkHttpClient(), Collections.singletonList(metaDataSubscriber), Collections.singletonList(authDataSubscriber), Collections.singletonList(proxySelectorDataSubscriber), - Collections.singletonList(discoveryUpstreamDataSubscriber), accessTokenManager); + Collections.singletonList(discoveryUpstreamDataSubscriber), accessTokenManager, shenyuConfig); } @AfterEach