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

Merged
merged 36 commits into from
Oct 16, 2024
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
e15cc58
sync frontend
Jul 17, 2024
1701c6a
commit
xcsnx Jul 18, 2024
2f46079
commit
Jul 18, 2024
0e9f036
Merge remote-tracking branch 'origin/syncFront' into feat_sync_namesp…
xcsnx Jul 19, 2024
89a56e3
fix e2e
xcsnx Jul 19, 2024
08d7e31
fix test
xcsnx Jul 19, 2024
7b01924
Merge branch 'master' into feat_sync_namespace_change
xcsnx Jul 19, 2024
3d993e8
Merge branch 'master' into feat_sync_namespace_change
xcsnx Jul 20, 2024
bd16403
Merge branch 'master' into feat_sync_namespace_change
Sep 14, 2024
523236f
fix
Sep 14, 2024
8088148
fix cr
Sep 15, 2024
e4d3e4b
Merge branch 'master' into feat_sync_namespace_change
xcsnx Sep 15, 2024
016db76
fix cr
Sep 15, 2024
c0ba599
Merge branch 'master' into feat_sync_namespace_change
Aias00 Sep 19, 2024
1cea6c3
Merge branch 'master' into feat_sync_namespace_change
Aias00 Sep 23, 2024
6a2f11a
Merge branch 'master' into feat_sync_namespace_change
Oct 10, 2024
f021ab9
fix cr
Oct 10, 2024
077ac60
Merge branch 'master' into feat_sync_namespace_change
Oct 13, 2024
e0656ff
final
Oct 13, 2024
d426de2
Merge branch 'master' into feat_sync_namespace_change
xcsnx Oct 13, 2024
9028d21
fix
Oct 13, 2024
b661354
fix
Oct 13, 2024
4be804f
fix
Oct 13, 2024
161c1a7
fix
Oct 13, 2024
33e0f87
fix uni test
Oct 13, 2024
86ed6ac
fix
Oct 13, 2024
0b1d8d2
fix
Oct 13, 2024
38a9976
fix
Oct 13, 2024
5c37591
Merge branch 'master' into feat_sync_namespace_change
Aias00 Oct 15, 2024
adb48be
Merge branch 'master' into feat_sync_namespace_change
xcsnx Oct 16, 2024
9a67d6d
fix
Oct 16, 2024
21770f4
fix
Oct 16, 2024
b052506
fix
Oct 16, 2024
b9e9686
fix
Oct 16, 2024
a6b25ba
fix
Oct 16, 2024
5572730
Merge branch 'master' into feat_sync_namespace_change
xcsnx Oct 16, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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);
xcsnx marked this conversation as resolved.
Show resolved Hide resolved
}
}
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)) {
moremind marked this conversation as resolved.
Show resolved Hide resolved
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
moremind marked this conversation as resolved.
Show resolved Hide resolved
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