Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[type:feat]The sync-data-http method adapts to the namespace transformation #5598

Open
wants to merge 14 commits into
base: master
Choose a base branch
from
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@
package org.apache.shenyu.admin.config;

import org.apache.shenyu.admin.config.properties.HttpSyncProperties;
import org.apache.shenyu.admin.controller.ConfigController;
import org.apache.shenyu.admin.listener.http.HttpLongPollingDataChangedListener;
import org.apache.shenyu.admin.service.NamespaceService;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
Expand All @@ -43,4 +45,16 @@ public HttpLongPollingDataChangedListener httpLongPollingDataChangedListener(fin
return new HttpLongPollingDataChangedListener(httpSyncProperties);
}

/**
* configController.
*
* @param httpLongPollingDataChangedListener httpLongPollingDataChangedListener
* @param namespaceService namespaceService
* @return {@link ConfigController}
*/
@Bean
@ConditionalOnMissingBean(ConfigController.class)
public ConfigController configController(final HttpLongPollingDataChangedListener httpLongPollingDataChangedListener, final NamespaceService namespaceService) {
return new ConfigController(httpLongPollingDataChangedListener, namespaceService);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,12 @@
package org.apache.shenyu.admin.controller;

import com.google.common.collect.Maps;
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.service.NamespaceService;
import org.apache.shenyu.admin.utils.ShenyuResultMessage;
import org.apache.shenyu.common.dto.ConfigData;
import org.apache.shenyu.common.enums.ConfigGroupEnum;
Expand All @@ -35,36 +39,49 @@

import java.util.Map;

import static org.apache.shenyu.common.constant.Constants.SYS_DEFAULT_NAMESPACE_ID;

/**
* This Controller only when HttpLongPollingDataChangedListener exist, will take effect.
*/
@ResponseBody
@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 namespaceIdParams namespaceIdParams
* @return the shenyu result
*/
@GetMapping("/fetch")
public ShenyuAdminResult fetchConfigs(@NotNull final String[] groupKeys) {
public ShenyuAdminResult fetchConfigs(@NotNull final String[] groupKeys, final String namespaceIdParams) {
String namespaceId = namespaceIdParams;
if (StringUtils.isNotEmpty(namespaceId) && ObjectUtils.isEmpty(namespaceService.findById(namespaceId))) {
throw new ShenyuAdminException("namespaceId is not exist");
}
if (StringUtils.isEmpty(namespaceId)) {
namespaceId = SYS_DEFAULT_NAMESPACE_ID;
}
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.
*
Expand All @@ -75,5 +92,5 @@ public ShenyuAdminResult fetchConfigs(@NotNull final String[] groupKeys) {
public void listener(final HttpServletRequest request, final HttpServletResponse response) {
longPollingListener.doLongPolling(request, response);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -17,23 +17,26 @@

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.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;
Expand All @@ -42,11 +45,12 @@
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.
Expand Down Expand Up @@ -98,14 +102,22 @@ 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) {
public ConfigData<?> fetchConfig(final ConfigGroupEnum groupKey, final String namespaceId) {
//todo:[Namespace] Currently, only plugin data is compatible with namespace, while other data is waiting for modification
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why not remove this?

ConfigDataCache config = CACHE.get(groupKey.name());
if (groupKey.equals(ConfigGroupEnum.PLUGIN)) {
config = CACHE.get(namespaceId + groupKey.name());
}
switch (groupKey) {
case APP_AUTH:
return buildConfigData(config, AppAuthData.class);
Expand Down Expand Up @@ -167,19 +179,20 @@ public void onPluginChanged(final List<PluginData> changed, final DataEventTypeE
if (CollectionUtils.isEmpty(changed)) {
return;
}
this.updatePluginCache();
this.afterPluginChanged(changed, eventType);
String namespaceId = changed.stream().map(PluginData::getNamespaceId).findFirst().orElse(SYS_DEFAULT_NAMESPACE_ID);
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)) {
Expand All @@ -189,7 +202,7 @@ public void onRuleChanged(final List<RuleData> changed, final DataEventTypeEnum
this.updateRuleCache();
this.afterRuleChanged(changed, eventType);
}

/**
* After rule changed.
*
Expand All @@ -198,7 +211,7 @@ public void onRuleChanged(final List<RuleData> changed, final DataEventTypeEnum
*/
protected void afterRuleChanged(final List<RuleData> changed, final DataEventTypeEnum eventType) {
}

@Override
public void onSelectorChanged(final List<SelectorData> changed, final DataEventTypeEnum eventType) {
if (CollectionUtils.isEmpty(changed)) {
Expand Down Expand Up @@ -278,20 +291,29 @@ public final void afterPropertiesSet() {
* @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());
//todo:[Namespace] Currently, only plugin data is compatible with namespace, while other data is waiting for modification
String configDataCacheKey = group.name();
if (group.equals(ConfigGroupEnum.PLUGIN)) {
configDataCacheKey = 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() {
List<NamespaceVO> namespaceList = namespaceService.list();
for (NamespaceVO namespace : namespaceList) {
String namespaceId = namespace.getNamespaceId();
this.updatePluginCache(namespaceId);
}
this.updateAppAuthCache();
this.updatePluginCache();
this.updateRuleCache();
this.updateSelectorCache();
this.updateMetaDataCache();
Expand All @@ -303,43 +325,43 @@ protected void refreshLocalCache() {
* Update selector cache.
*/
protected void updateSelectorCache() {
this.updateCache(ConfigGroupEnum.SELECTOR, selectorService.listAll());
this.updateCache(ConfigGroupEnum.SELECTOR, selectorService.listAll(), "");
}

/**
* Update rule cache.
*/
protected void updateRuleCache() {
this.updateCache(ConfigGroupEnum.RULE, ruleService.listAll());
this.updateCache(ConfigGroupEnum.RULE, ruleService.listAll(), "");
}

/**
* 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());
this.updateCache(ConfigGroupEnum.APP_AUTH, appAuthService.listAll(), "");
}

/**
* Update meta data cache.
*/
protected void updateMetaDataCache() {
this.updateCache(ConfigGroupEnum.META_DATA, metaDataService.listAll());
this.updateCache(ConfigGroupEnum.META_DATA, metaDataService.listAll(), "");
}

protected void updateProxySelectorDataCache() {
this.updateCache(ConfigGroupEnum.PROXY_SELECTOR, proxySelectorService.listAll());
this.updateCache(ConfigGroupEnum.PROXY_SELECTOR, proxySelectorService.listAll(), "");
}

protected void updateDiscoveryUpstreamDataCache() {
this.updateCache(ConfigGroupEnum.DISCOVER_UPSTREAM, discoveryUpstreamService.listAll());
this.updateCache(ConfigGroupEnum.DISCOVER_UPSTREAM, discoveryUpstreamService.listAll(), "");
}

private <T> ConfigData<T> buildConfigData(final ConfigDataCache config, final Class<T> dataType) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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;
}

/**
Expand Down Expand Up @@ -94,6 +97,15 @@ public String getJson() {
return json;
}

/**
* Gets namespaceId.
*
* @return the namespaceId
*/
public String getNamespaceId() {
return namespaceId;
}

@Override
public String toString() {
return "{"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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()));
Expand Down
Loading
Loading