remove direct read (#11670)

* remove isDirectRead

* check style

* coverage makeup

* coverage makeup

* coverage makeup
This commit is contained in:
nov.lzf 2024-01-17 19:20:48 +08:00 committed by GitHub
parent 30a5014e5d
commit 5f9c848d7e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 378 additions and 751 deletions

View File

@ -20,7 +20,6 @@ import com.alibaba.nacos.api.model.v2.ErrorCode;
import com.alibaba.nacos.api.model.v2.Result;
import com.alibaba.nacos.common.constant.HttpHeaderConsts;
import com.alibaba.nacos.common.http.param.MediaType;
import com.alibaba.nacos.common.utils.InternetAddressUtil;
import com.alibaba.nacos.common.utils.JacksonUtils;
import com.alibaba.nacos.common.utils.Pair;
import com.alibaba.nacos.common.utils.StringUtils;
@ -28,18 +27,13 @@ import com.alibaba.nacos.config.server.constant.Constants;
import com.alibaba.nacos.config.server.enums.FileTypeEnum;
import com.alibaba.nacos.config.server.model.CacheItem;
import com.alibaba.nacos.config.server.model.ConfigCache;
import com.alibaba.nacos.config.server.model.ConfigInfoBase;
import com.alibaba.nacos.config.server.service.ConfigCacheService;
import com.alibaba.nacos.config.server.service.LongPollingService;
import com.alibaba.nacos.config.server.service.dump.disk.ConfigDiskServiceFactory;
import com.alibaba.nacos.config.server.service.repository.ConfigInfoBetaPersistService;
import com.alibaba.nacos.config.server.service.repository.ConfigInfoPersistService;
import com.alibaba.nacos.config.server.service.repository.ConfigInfoTagPersistService;
import com.alibaba.nacos.config.server.service.trace.ConfigTraceService;
import com.alibaba.nacos.config.server.utils.GroupKey2;
import com.alibaba.nacos.config.server.utils.LogUtil;
import com.alibaba.nacos.config.server.utils.MD5Util;
import com.alibaba.nacos.config.server.utils.PropertyUtil;
import com.alibaba.nacos.config.server.utils.Protocol;
import com.alibaba.nacos.config.server.utils.RequestUtil;
import com.alibaba.nacos.config.server.utils.TimeUtils;
@ -77,19 +71,8 @@ public class ConfigServletInner {
private final LongPollingService longPollingService;
private final ConfigInfoPersistService configInfoPersistService;
private final ConfigInfoBetaPersistService configInfoBetaPersistService;
private final ConfigInfoTagPersistService configInfoTagPersistService;
public ConfigServletInner(LongPollingService longPollingService, ConfigInfoPersistService configInfoPersistService,
ConfigInfoBetaPersistService configInfoBetaPersistService,
ConfigInfoTagPersistService configInfoTagPersistService) {
public ConfigServletInner(LongPollingService longPollingService) {
this.longPollingService = longPollingService;
this.configInfoPersistService = configInfoPersistService;
this.configInfoBetaPersistService = configInfoBetaPersistService;
this.configInfoTagPersistService = configInfoTagPersistService;
}
/**
@ -145,8 +128,7 @@ public class ConfigServletInner {
* Execute to get config [API V1] or [API V2].
*/
public String doGetConfig(HttpServletRequest request, HttpServletResponse response, String dataId, String group,
String tenant, String tag, String isNotify, String clientIp, boolean isV2)
throws IOException, ServletException {
String tenant, String tag, String isNotify, String clientIp, boolean isV2) throws IOException {
boolean notify = StringUtils.isNotBlank(isNotify) && Boolean.parseBoolean(isNotify);
@ -160,65 +142,46 @@ public class ConfigServletInner {
String autoTag = request.getHeader(com.alibaba.nacos.api.common.Constants.VIPSERVER_TAG);
String requestIpApp = RequestUtil.getAppName(request);
int lockResult = tryConfigReadLock(groupKey);
int lockResult = ConfigCacheService.tryConfigReadLock(groupKey);
CacheItem cacheItem = ConfigCacheService.getContentCache(groupKey);
final String requestIp = RequestUtil.getRemoteIp(request);
boolean isBeta = false;
if (lockResult > 0) {
// LockResult > 0 means cacheItem is not null and other thread can`t delete this cacheItem
if (lockResult > 0 && cacheItem != null) {
try {
String md5 = Constants.NULL;
long lastModified = 0L;
CacheItem cacheItem = ConfigCacheService.getContentCache(groupKey);
if (cacheItem.isBeta() && cacheItem.getConfigCacheBeta() != null && cacheItem.getIps4Beta() != null
&& cacheItem.getIps4Beta().contains(clientIp)) {
isBeta = true;
}
long lastModified;
boolean isBeta =
cacheItem.isBeta() && cacheItem.getConfigCacheBeta() != null && cacheItem.getIps4Beta() != null
&& cacheItem.getIps4Beta().contains(clientIp);
final String configType =
(null != cacheItem.getType()) ? cacheItem.getType() : FileTypeEnum.TEXT.getFileType();
response.setHeader(com.alibaba.nacos.api.common.Constants.CONFIG_TYPE, configType);
FileTypeEnum fileTypeEnum = FileTypeEnum.getFileTypeEnumByFileExtensionOrFileType(configType);
String contentTypeHeader = fileTypeEnum.getContentType();
response.setHeader(HttpHeaderConsts.CONTENT_TYPE, contentTypeHeader);
if (isV2) {
response.setHeader(HttpHeaderConsts.CONTENT_TYPE, MediaType.APPLICATION_JSON);
}
response.setHeader(HttpHeaderConsts.CONTENT_TYPE,
isV2 ? MediaType.APPLICATION_JSON : contentTypeHeader);
String pullEvent;
String content = null;
ConfigInfoBase configInfoBase = null;
String content;
String md5;
String encryptedDataKey;
if (isBeta) {
ConfigCache configCacheBeta = cacheItem.getConfigCacheBeta();
pullEvent = ConfigTraceService.PULL_EVENT_BETA;
md5 = configCacheBeta.getMd5(acceptCharset);
lastModified = configCacheBeta.getLastModifiedTs();
if (PropertyUtil.isDirectRead()) {
configInfoBase = configInfoBetaPersistService.findConfigInfo4Beta(dataId, group, tenant);
} else {
content = ConfigDiskServiceFactory.getInstance().getBetaContent(dataId, group, tenant);
}
encryptedDataKey = configCacheBeta.getEncryptedDataKey();
content = ConfigDiskServiceFactory.getInstance().getBetaContent(dataId, group, tenant);
response.setHeader("isBeta", "true");
} else {
if (StringUtils.isBlank(tag)) {
if (isUseTag(cacheItem, autoTag)) {
if (cacheItem.getConfigCacheTags() != null) {
ConfigCache configCacheTag = cacheItem.getConfigCacheTags().get(autoTag);
if (configCacheTag != null) {
md5 = configCacheTag.getMd5(acceptCharset);
lastModified = configCacheTag.getLastModifiedTs();
}
}
if (PropertyUtil.isDirectRead()) {
configInfoBase = configInfoTagPersistService.findConfigInfo4Tag(dataId, group, tenant,
autoTag);
} else {
content = ConfigDiskServiceFactory.getInstance()
.getTagContent(dataId, group, tenant, autoTag);
}
ConfigCache configCacheTag = cacheItem.getConfigCacheTags().get(autoTag);
md5 = configCacheTag.getMd5(acceptCharset);
lastModified = configCacheTag.getLastModifiedTs();
encryptedDataKey = configCacheTag.getEncryptedDataKey();
content = ConfigDiskServiceFactory.getInstance()
.getTagContent(dataId, group, tenant, autoTag);
pullEvent = ConfigTraceService.PULL_EVENT_TAG + "-" + autoTag;
response.setHeader(com.alibaba.nacos.api.common.Constants.VIPSERVER_TAG,
URLEncoder.encode(autoTag, StandardCharsets.UTF_8.displayName()));
@ -226,49 +189,25 @@ public class ConfigServletInner {
pullEvent = ConfigTraceService.PULL_EVENT;
md5 = cacheItem.getConfigCache().getMd5(acceptCharset);
lastModified = cacheItem.getConfigCache().getLastModifiedTs();
if (PropertyUtil.isDirectRead()) {
configInfoBase = configInfoPersistService.findConfigInfo(dataId, group, tenant);
} else {
content = ConfigDiskServiceFactory.getInstance().getContent(dataId, group, tenant);
}
if (configInfoBase == null && content == null) {
// FIXME CacheItem
// No longer exists. It is impossible to simply calculate the push delayed. Here, simply record it as - 1.
ConfigTraceService.logPullEvent(dataId, group, tenant, requestIpApp, -1, pullEvent,
ConfigTraceService.PULL_TYPE_NOTFOUND, -1, requestIp, notify, "http");
// pullLog.info("[client-get] clientIp={}, {},
// no data",
// new Object[]{clientIp, groupKey});
return get404Result(response, isV2);
}
encryptedDataKey = cacheItem.getConfigCache().getEncryptedDataKey();
content = ConfigDiskServiceFactory.getInstance().getContent(dataId, group, tenant);
}
} else {
md5 = cacheItem.getTagMd5(tag, acceptCharset);
lastModified = cacheItem.getTagLastModified(tag);
if (PropertyUtil.isDirectRead()) {
configInfoBase = configInfoTagPersistService.findConfigInfo4Tag(dataId, group, tenant, tag);
} else {
content = ConfigDiskServiceFactory.getInstance().getTagContent(dataId, group, tenant, tag);
}
pullEvent = ConfigTraceService.PULL_EVENT_TAG + "-" + tag;
encryptedDataKey = cacheItem.getTagEncryptedDataKey(tag);
if (configInfoBase == null && content == null) {
// FIXME CacheItem
// No longer exists. It is impossible to simply calculate the push delayed. Here, simply record it as - 1.
ConfigTraceService.logPullEvent(dataId, group, tenant, requestIpApp, -1, pullEvent,
ConfigTraceService.PULL_TYPE_NOTFOUND, -1, requestIp, notify, "http");
// pullLog.info("[client-get] clientIp={}, {},
// no data",
// new Object[]{clientIp, groupKey});
return get404Result(response, isV2);
}
content = ConfigDiskServiceFactory.getInstance().getTagContent(dataId, group, tenant, tag);
pullEvent = ConfigTraceService.PULL_EVENT_TAG + "-" + tag;
}
}
if (content == null) {
ConfigTraceService.logPullEvent(dataId, group, tenant, requestIpApp, -1, pullEvent,
ConfigTraceService.PULL_TYPE_NOTFOUND, -1, requestIp, notify, "http");
return get404Result(response, isV2);
}
response.setHeader(Constants.CONTENT_MD5, md5);
// Disable cache.
@ -276,28 +215,19 @@ public class ConfigServletInner {
response.setDateHeader("Expires", 0);
response.setHeader("Cache-Control", "no-cache,no-store");
response.setDateHeader("Last-Modified", lastModified);
putEncryptedDataKeyHeader(response, tag, clientIp, acceptCharset, cacheItem, isBeta, autoTag);
PrintWriter out;
if (PropertyUtil.isDirectRead()) {
Pair<String, String> pair = EncryptionHandler.decryptHandler(dataId,
configInfoBase.getEncryptedDataKey(), configInfoBase.getContent());
out = response.getWriter();
if (isV2) {
out.print(JacksonUtils.toJson(Result.success(pair.getSecond())));
} else {
out.print(pair.getSecond());
}
} else {
String encryptedDataKey = response.getHeader("Encrypted-Data-Key");
Pair<String, String> pair = EncryptionHandler.decryptHandler(dataId, encryptedDataKey, content);
String decryptContent = pair.getSecond();
out = response.getWriter();
if (isV2) {
out.print(JacksonUtils.toJson(Result.success(decryptContent)));
} else {
out.print(decryptContent);
}
if (encryptedDataKey != null) {
response.setHeader("Encrypted-Data-Key", encryptedDataKey);
}
PrintWriter out;
Pair<String, String> pair = EncryptionHandler.decryptHandler(dataId, encryptedDataKey, content);
String decryptContent = pair.getSecond();
out = response.getWriter();
if (isV2) {
out.print(JacksonUtils.toJson(Result.success(decryptContent)));
} else {
out.print(decryptContent);
}
out.flush();
out.close();
@ -307,30 +237,23 @@ public class ConfigServletInner {
ConfigTraceService.logPullEvent(dataId, group, tenant, requestIpApp, lastModified, pullEvent,
ConfigTraceService.PULL_TYPE_OK, delayed, clientIp, notify, "http");
} finally {
releaseConfigReadLock(groupKey);
ConfigCacheService.releaseReadLock(groupKey);
}
} else if (lockResult == 0) {
} else if (lockResult == 0 || cacheItem == null) {
// FIXME CacheItem No longer exists. It is impossible to simply calculate the push delayed. Here, simply record it as - 1.
ConfigTraceService.logPullEvent(dataId, group, tenant, requestIpApp, -1, ConfigTraceService.PULL_EVENT,
ConfigTraceService.PULL_TYPE_NOTFOUND, -1, requestIp, notify, "http");
return get404Result(response, isV2);
} else {
PULL_LOG.info("[client-get] clientIp={}, {}, get data during dump", clientIp, groupKey);
return get409Result(response, isV2);
}
return HttpServletResponse.SC_OK + "";
}
private static void releaseConfigReadLock(String groupKey) {
ConfigCacheService.releaseReadLock(groupKey);
}
private String get404Result(HttpServletResponse response, boolean isV2) throws IOException {
response.setStatus(HttpServletResponse.SC_NOT_FOUND);
PrintWriter writer = response.getWriter();
@ -354,75 +277,6 @@ public class ConfigServletInner {
return HttpServletResponse.SC_CONFLICT + "";
}
/**
* Try to add read lock.
*
* @param groupKey groupKey string value.
* @return 0 - No data and failed. Positive number - lock succeeded. Negative number - lock failed
*/
private static int tryConfigReadLock(String groupKey) {
// Lock failed by default.
int lockResult = -1;
// Try to get lock times, max value: 10;
for (int i = TRY_GET_LOCK_TIMES; i >= 0; --i) {
lockResult = ConfigCacheService.tryReadLock(groupKey);
// The data is non-existent.
if (0 == lockResult) {
break;
}
// Success
if (lockResult > 0) {
break;
}
// Retry.
if (i > 0) {
try {
Thread.sleep(1);
} catch (Exception e) {
LogUtil.PULL_CHECK_LOG.error("An Exception occurred while thread sleep", e);
}
}
}
return lockResult;
}
private void putEncryptedDataKeyHeader(HttpServletResponse response, String tag, String clientIp, String charset,
CacheItem cacheItem, boolean isBeta, String autoTag) {
if (cacheItem == null) {
return;
}
String encryptedDataKey = null;
if (isBeta && cacheItem.getConfigCacheBeta() != null) {
encryptedDataKey = cacheItem.getConfigCacheBeta().getEncryptedDataKey();
} else {
if (org.apache.commons.lang.StringUtils.isBlank(tag)) {
if (isUseTag(cacheItem, autoTag)) {
// autoTag
encryptedDataKey = cacheItem.getTagEncryptedDataKey(autoTag);
} else if (cacheItem.isBatch && cacheItem.delimiter >= InternetAddressUtil.ipToInt(clientIp)
&& cacheItem.getConfigCacheBatch() != null) {
// batch
encryptedDataKey = cacheItem.getConfigCacheBatch().getEncryptedDataKey();
} else {
encryptedDataKey = cacheItem.getConfigCache().getEncryptedDataKey();
}
} else {
encryptedDataKey = cacheItem.getTagEncryptedDataKey(tag);
}
}
if (org.apache.commons.lang.StringUtils.isNotBlank(encryptedDataKey)) {
response.setHeader("Encrypted-Data-Key", encryptedDataKey);
}
}
private static boolean isUseTag(CacheItem cacheItem, String tag) {
return cacheItem != null && cacheItem.getConfigCacheTags() != null && cacheItem.getConfigCacheTags()
.containsKey(tag);

View File

@ -22,20 +22,13 @@ import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.api.remote.request.RequestMeta;
import com.alibaba.nacos.api.remote.response.ResponseCode;
import com.alibaba.nacos.auth.annotation.Secured;
import com.alibaba.nacos.common.utils.InternetAddressUtil;
import com.alibaba.nacos.common.utils.StringUtils;
import com.alibaba.nacos.config.server.constant.Constants;
import com.alibaba.nacos.config.server.model.CacheItem;
import com.alibaba.nacos.config.server.model.ConfigInfoBase;
import com.alibaba.nacos.config.server.service.ConfigCacheService;
import com.alibaba.nacos.config.server.service.dump.disk.ConfigDiskServiceFactory;
import com.alibaba.nacos.config.server.service.repository.ConfigInfoBetaPersistService;
import com.alibaba.nacos.config.server.service.repository.ConfigInfoPersistService;
import com.alibaba.nacos.config.server.service.repository.ConfigInfoTagPersistService;
import com.alibaba.nacos.config.server.service.trace.ConfigTraceService;
import com.alibaba.nacos.config.server.utils.GroupKey2;
import com.alibaba.nacos.config.server.utils.LogUtil;
import com.alibaba.nacos.config.server.utils.PropertyUtil;
import com.alibaba.nacos.config.server.utils.TimeUtils;
import com.alibaba.nacos.core.control.TpsControl;
import com.alibaba.nacos.core.paramcheck.ExtractorManager;
@ -60,20 +53,7 @@ import static com.alibaba.nacos.config.server.utils.RequestUtil.CLIENT_APPNAME_H
@Component
public class ConfigQueryRequestHandler extends RequestHandler<ConfigQueryRequest, ConfigQueryResponse> {
private static final int TRY_GET_LOCK_TIMES = 9;
private final ConfigInfoPersistService configInfoPersistService;
private final ConfigInfoTagPersistService configInfoTagPersistService;
private final ConfigInfoBetaPersistService configInfoBetaPersistService;
public ConfigQueryRequestHandler(ConfigInfoPersistService configInfoPersistService,
ConfigInfoTagPersistService configInfoTagPersistService,
ConfigInfoBetaPersistService configInfoBetaPersistService) {
this.configInfoPersistService = configInfoPersistService;
this.configInfoTagPersistService = configInfoTagPersistService;
this.configInfoBetaPersistService = configInfoBetaPersistService;
public ConfigQueryRequestHandler() {
}
@Override
@ -97,128 +77,87 @@ public class ConfigQueryRequestHandler extends RequestHandler<ConfigQueryRequest
String tenant = configQueryRequest.getTenant();
String clientIp = meta.getClientIp();
String tag = configQueryRequest.getTag();
ConfigQueryResponse response = new ConfigQueryResponse();
final String groupKey = GroupKey2.getKey(configQueryRequest.getDataId(), configQueryRequest.getGroup(),
String groupKey = GroupKey2.getKey(configQueryRequest.getDataId(), configQueryRequest.getGroup(),
configQueryRequest.getTenant());
String autoTag = configQueryRequest.getHeader(com.alibaba.nacos.api.common.Constants.VIPSERVER_TAG);
String requestIpApp = meta.getLabels().get(CLIENT_APPNAME_HEADER);
String acceptCharset = ENCODE_UTF8;
int lockResult = tryConfigReadLock(groupKey);
int lockResult = ConfigCacheService.tryConfigReadLock(groupKey);
String pullEvent = ConfigTraceService.PULL_EVENT;
boolean isBeta = false;
if (lockResult > 0) {
String pullType = ConfigTraceService.PULL_TYPE_OK;
ConfigQueryResponse response = new ConfigQueryResponse();
CacheItem cacheItem = ConfigCacheService.getContentCache(groupKey);
if (lockResult > 0 && cacheItem != null) {
try {
String md5 = Constants.NULL;
long lastModified = 0L;
CacheItem cacheItem = ConfigCacheService.getContentCache(groupKey);
if (cacheItem != null) {
if (cacheItem.isBeta() && cacheItem.getIps4Beta() != null && cacheItem.getIps4Beta()
.contains(clientIp) && cacheItem.getConfigCacheBeta() != null) {
isBeta = true;
}
String configType = cacheItem.getType();
response.setContentType((null != configType) ? configType : "text");
}
String content = null;
ConfigInfoBase configInfoBase = null;
boolean isBeta = cacheItem.isBeta() && cacheItem.getIps4Beta() != null && cacheItem.getIps4Beta()
.contains(clientIp) && cacheItem.getConfigCacheBeta() != null;
String configType = cacheItem.getType();
response.setContentType((null != configType) ? configType : "text");
String content;
String md5;
String encryptedDataKey;
if (isBeta) {
md5 = cacheItem.getConfigCacheBeta().getMd5(acceptCharset);
lastModified = cacheItem.getConfigCacheBeta().getLastModifiedTs();
if (PropertyUtil.isDirectRead()) {
configInfoBase = configInfoBetaPersistService.findConfigInfo4Beta(dataId, group, tenant);
} else {
content = ConfigDiskServiceFactory.getInstance().getBetaContent(dataId, group, tenant);
}
content = ConfigDiskServiceFactory.getInstance().getBetaContent(dataId, group, tenant);
pullEvent = ConfigTraceService.PULL_EVENT_BETA;
encryptedDataKey = cacheItem.getConfigCacheBeta().getEncryptedDataKey();
response.setBeta(true);
} else {
if (StringUtils.isBlank(tag)) {
if (isUseTag(cacheItem, autoTag)) {
if (cacheItem != null) {
md5 = cacheItem.getTagMd5(autoTag, acceptCharset);
lastModified = cacheItem.getTagLastModified(autoTag);
}
if (PropertyUtil.isDirectRead()) {
configInfoBase = configInfoTagPersistService.findConfigInfo4Tag(dataId, group, tenant,
autoTag);
} else {
content = ConfigDiskServiceFactory.getInstance()
.getTagContent(dataId, group, tenant, autoTag);
}
md5 = cacheItem.getTagMd5(autoTag, acceptCharset);
lastModified = cacheItem.getTagLastModified(autoTag);
encryptedDataKey = cacheItem.getTagEncryptedDataKey(autoTag);
content = ConfigDiskServiceFactory.getInstance()
.getTagContent(dataId, group, tenant, autoTag);
pullEvent = ConfigTraceService.PULL_EVENT_TAG + "-" + autoTag;
response.setTag(URLEncoder.encode(autoTag, ENCODE_UTF8));
} else {
md5 = cacheItem.getConfigCache().getMd5(acceptCharset);
lastModified = cacheItem.getConfigCache().getLastModifiedTs();
if (PropertyUtil.isDirectRead()) {
configInfoBase = configInfoPersistService.findConfigInfo(dataId, group, tenant);
} else {
content = ConfigDiskServiceFactory.getInstance().getContent(dataId, group, tenant);
}
encryptedDataKey = cacheItem.getConfigCache().getEncryptedDataKey();
content = ConfigDiskServiceFactory.getInstance().getContent(dataId, group, tenant);
pullEvent = ConfigTraceService.PULL_EVENT;
if (configInfoBase == null && content == null) {
// No longer exists. It is impossible to simply calculate the push delayed. Here, simply record it as - 1.
ConfigTraceService.logPullEvent(dataId, group, tenant, requestIpApp, -1, pullEvent,
ConfigTraceService.PULL_TYPE_NOTFOUND, -1, clientIp, false, "grpc");
response.setErrorInfo(ConfigQueryResponse.CONFIG_NOT_FOUND, "config data not exist");
return response;
}
}
} else {
if (cacheItem != null) {
md5 = cacheItem.getTagMd5(tag, acceptCharset);
lastModified = cacheItem.getTagLastModified(tag);
}
if (PropertyUtil.isDirectRead()) {
configInfoBase = configInfoTagPersistService.findConfigInfo4Tag(dataId, group, tenant, tag);
} else {
content = ConfigDiskServiceFactory.getInstance().getTagContent(dataId, group, tenant, tag);
}
md5 = cacheItem.getTagMd5(tag, acceptCharset);
lastModified = cacheItem.getTagLastModified(tag);
encryptedDataKey = cacheItem.getTagEncryptedDataKey(tag);
content = ConfigDiskServiceFactory.getInstance().getTagContent(dataId, group, tenant, tag);
response.setTag(tag);
pullEvent = ConfigTraceService.PULL_EVENT_TAG + "-" + tag;
if (configInfoBase == null && content == null) {
// No longer exists. It is impossible to simply calculate the push delayed. Here, simply record it as - 1.
ConfigTraceService.logPullEvent(dataId, group, tenant, requestIpApp, -1, pullEvent,
ConfigTraceService.PULL_TYPE_NOTFOUND, -1, clientIp, false, "grpc");
response.setErrorInfo(ConfigQueryResponse.CONFIG_NOT_FOUND, "config data not exist");
return response;
}
}
}
response.setMd5(md5);
String encryptedDataKey = getEncryptedDataKey(tag, clientIp, cacheItem, isBeta, autoTag);
response.setEncryptedDataKey(encryptedDataKey);
if (PropertyUtil.isDirectRead()) {
response.setLastModified(lastModified);
response.setContent(configInfoBase.getContent());
response.setResultCode(ResponseCode.SUCCESS.getCode());
response.setContent(content);
response.setLastModified(lastModified);
if (content == null) {
pullType = ConfigTraceService.PULL_TYPE_NOTFOUND;
response.setErrorInfo(ConfigQueryResponse.CONFIG_NOT_FOUND, "config data not exist");
} else {
response.setContent(content);
response.setLastModified(lastModified);
response.setResultCode(ResponseCode.SUCCESS.getCode());
}
LogUtil.PULL_CHECK_LOG.warn("{}|{}|{}|{}", groupKey, clientIp, md5, TimeUtils.getCurrentTimeStr());
final long delayed = notify ? -1 : System.currentTimeMillis() - lastModified;
ConfigTraceService.logPullEvent(dataId, group, tenant, requestIpApp, lastModified, pullEvent,
ConfigTraceService.PULL_TYPE_OK, delayed, clientIp, notify, "grpc");
ConfigTraceService.logPullEvent(dataId, group, tenant, requestIpApp, lastModified, pullEvent, pullType,
delayed, clientIp, notify, "grpc");
} finally {
releaseConfigReadLock(groupKey);
ConfigCacheService.releaseReadLock(groupKey);
}
} else if (lockResult == 0) {
} else if (lockResult == 0 || cacheItem == null) {
// FIXME CacheItem No longer exists. It is impossible to simply calculate the push delayed. Here, simply record it as - 1.
//CacheItem No longer exists. It is impossible to simply calculate the push delayed. Here, simply record it as - 1.
ConfigTraceService.logPullEvent(dataId, group, tenant, requestIpApp, -1, pullEvent,
ConfigTraceService.PULL_TYPE_NOTFOUND, -1, clientIp, notify, "grpc");
response.setErrorInfo(ConfigQueryResponse.CONFIG_NOT_FOUND, "config data not exist");
@ -231,68 +170,6 @@ public class ConfigQueryRequestHandler extends RequestHandler<ConfigQueryRequest
return response;
}
private String getEncryptedDataKey(String tag, String clientIp, CacheItem cacheItem, boolean isBeta,
String autoTag) {
if (cacheItem == null) {
return null;
}
String encryptedDataKey;
if (isBeta && cacheItem.getConfigCacheBeta() != null) {
encryptedDataKey = cacheItem.getConfigCacheBeta().getEncryptedDataKey();
} else {
if (StringUtils.isBlank(tag)) {
if (isUseTag(cacheItem, autoTag)) {
encryptedDataKey = cacheItem.getTagEncryptedDataKey(autoTag);
} else if (cacheItem.isBatch && cacheItem.delimiter >= InternetAddressUtil.ipToInt(clientIp)
&& cacheItem.getConfigCacheBatch() != null) {
// batch
encryptedDataKey = cacheItem.getConfigCacheBatch().getEncryptedDataKey();
} else {
encryptedDataKey = cacheItem.getConfigCache().getEncryptedDataKey();
}
} else {
encryptedDataKey = cacheItem.getTagEncryptedDataKey(tag);
}
}
return encryptedDataKey;
}
private static void releaseConfigReadLock(String groupKey) {
ConfigCacheService.releaseReadLock(groupKey);
}
private static int tryConfigReadLock(String groupKey) {
// Lock failed by default.
int lockResult = -1;
// Try to get lock times, max value: 10;
for (int i = TRY_GET_LOCK_TIMES; i >= 0; --i) {
lockResult = ConfigCacheService.tryReadLock(groupKey);
// The data is non-existent.
if (0 == lockResult) {
break;
}
// Success
if (lockResult > 0) {
break;
}
// Retry.
if (i > 0) {
try {
Thread.sleep(1);
} catch (Exception e) {
LogUtil.PULL_CHECK_LOG.error("An Exception occurred while thread sleep", e);
}
}
}
return lockResult;
}
private static boolean isUseTag(CacheItem cacheItem, String tag) {
return StringUtils.isNotBlank(tag) && cacheItem.getConfigCacheTags() != null && cacheItem.getConfigCacheTags()
.containsKey(tag);

View File

@ -27,7 +27,7 @@ import com.alibaba.nacos.config.server.model.ConfigCache;
import com.alibaba.nacos.config.server.model.event.LocalDataChangeEvent;
import com.alibaba.nacos.config.server.service.dump.disk.ConfigDiskServiceFactory;
import com.alibaba.nacos.config.server.utils.GroupKey2;
import com.alibaba.nacos.config.server.utils.PropertyUtil;
import com.alibaba.nacos.config.server.utils.LogUtil;
import com.alibaba.nacos.sys.env.EnvUtil;
import com.google.common.collect.Lists;
@ -107,13 +107,9 @@ public class ConfigCacheService {
String localContentMd5 = ConfigCacheService.getContentMd5(groupKey);
boolean md5Changed = !md5.equals(localContentMd5);
if (md5Changed) {
if (!PropertyUtil.isDirectRead()) {
DUMP_LOG.info("[dump] md5 changed, save to disk cache ,groupKey={}, newMd5={},oldMd5={}", groupKey,
md5, localContentMd5);
ConfigDiskServiceFactory.getInstance().saveToDisk(dataId, group, tenant, content);
} else {
//ignore to save disk cache in direct model
}
DUMP_LOG.info("[dump] md5 changed, save to disk cache ,groupKey={}, newMd5={},oldMd5={}", groupKey, md5,
localContentMd5);
ConfigDiskServiceFactory.getInstance().saveToDisk(dataId, group, tenant, content);
} else {
DUMP_LOG.warn("[dump-ignore] ignore to save to disk cache. md5 consistent,groupKey={}, md5={}",
groupKey, md5);
@ -214,15 +210,10 @@ public class ConfigCacheService {
String localContentBetaMd5 = ConfigCacheService.getContentBetaMd5(groupKey);
boolean md5Changed = !md5.equals(localContentBetaMd5);
if (md5Changed) {
if (!PropertyUtil.isDirectRead()) {
DUMP_LOG.info(
"[dump-beta] md5 changed, update md5 in local disk cache. groupKey={}, newMd5={}, oldMd5={}",
groupKey, md5, localContentBetaMd5);
ConfigDiskServiceFactory.getInstance().saveBetaToDisk(dataId, group, tenant, content);
} else {
//
}
DUMP_LOG.info(
"[dump-beta] md5 changed, update md5 in local disk cache. groupKey={}, newMd5={}, oldMd5={}",
groupKey, md5, localContentBetaMd5);
ConfigDiskServiceFactory.getInstance().saveBetaToDisk(dataId, group, tenant, content);
}
//md5 , ip list timestamp check and update local jvm cache.
@ -298,11 +289,7 @@ public class ConfigCacheService {
boolean md5Changed = !md5.equals(localContentTagMd5);
if (md5Changed) {
if (!PropertyUtil.isDirectRead()) {
ConfigDiskServiceFactory.getInstance().saveTagToDisk(dataId, group, tenant, tag, content);
} else {
//
}
ConfigDiskServiceFactory.getInstance().saveTagToDisk(dataId, group, tenant, tag, content);
}
if (md5Changed) {
@ -354,10 +341,9 @@ public class ConfigCacheService {
}
try {
if (!PropertyUtil.isDirectRead()) {
DUMP_LOG.info("[dump] remove local disk cache,groupKey={} ", groupKey);
ConfigDiskServiceFactory.getInstance().removeConfigInfo(dataId, group, tenant);
}
DUMP_LOG.info("[dump] remove local disk cache,groupKey={} ", groupKey);
ConfigDiskServiceFactory.getInstance().removeConfigInfo(dataId, group, tenant);
CACHE.remove(groupKey);
DUMP_LOG.info("[dump] remove local jvm cache,groupKey={} ", groupKey);
@ -394,10 +380,8 @@ public class ConfigCacheService {
}
try {
if (!PropertyUtil.isDirectRead()) {
DUMP_LOG.info("[remove-beta-ok] remove beta in local disk cache,groupKey={} ", groupKey);
ConfigDiskServiceFactory.getInstance().removeConfigInfo4Beta(dataId, group, tenant);
}
DUMP_LOG.info("[remove-beta-ok] remove beta in local disk cache,groupKey={} ", groupKey);
ConfigDiskServiceFactory.getInstance().removeConfigInfo4Beta(dataId, group, tenant);
NotifyCenter.publishEvent(new LocalDataChangeEvent(groupKey, true, CACHE.get(groupKey).getIps4Beta()));
CACHE.get(groupKey).removeBeta();
DUMP_LOG.info("[remove-beta-ok] remove beta in local jvm cache,groupKey={} ", groupKey);
@ -434,10 +418,8 @@ public class ConfigCacheService {
}
try {
if (!PropertyUtil.isDirectRead()) {
DUMP_LOG.info("[remove-tag-ok] remove tag in local disk cache,tag={},groupKey={} ", tag, groupKey);
ConfigDiskServiceFactory.getInstance().removeConfigInfo4Tag(dataId, group, tenant, tag);
}
DUMP_LOG.info("[remove-tag-ok] remove tag in local disk cache,tag={},groupKey={} ", tag, groupKey);
ConfigDiskServiceFactory.getInstance().removeConfigInfo4Tag(dataId, group, tenant, tag);
CacheItem ci = CACHE.get(groupKey);
if (ci.getConfigCacheTags() != null) {
@ -737,5 +719,45 @@ public class ConfigCacheService {
cache.getConfigCacheBeta().setLastModifiedTs(lastModifiedTs);
}
private static final int TRY_GET_LOCK_TIMES = 9;
/**
* try config read lock with spin of try get lock times.
*
* @param groupKey group key of config.
* @return
*/
public static int tryConfigReadLock(String groupKey) {
// Lock failed by default.
int lockResult = -1;
// Try to get lock times, max value: 10;
for (int i = TRY_GET_LOCK_TIMES; i >= 0; --i) {
lockResult = ConfigCacheService.tryReadLock(groupKey);
// The data is non-existent.
if (0 == lockResult) {
break;
}
// Success
if (lockResult > 0) {
break;
}
// Retry.
if (i > 0) {
try {
Thread.sleep(1);
} catch (Exception e) {
LogUtil.PULL_CHECK_LOG.error("An Exception occurred while thread sleep", e);
}
}
}
return lockResult;
}
}

View File

@ -17,7 +17,6 @@
package com.alibaba.nacos.config.server.utils;
import com.alibaba.nacos.config.server.constant.PropertiesConstant;
import com.alibaba.nacos.persistence.configuration.DatasourceConfiguration;
import com.alibaba.nacos.sys.env.EnvUtil;
import org.slf4j.Logger;
import org.springframework.context.ApplicationContextInitializer;
@ -240,14 +239,6 @@ public class PropertyUtil implements ApplicationContextInitializer<ConfigurableA
return EnvUtil.getStandaloneMode();
}
// Determines whether to read the data directly
// if use mysql, Reduce database read pressure
// if use raft+derby, Reduce leader read pressure
public static boolean isDirectRead() {
return EnvUtil.getStandaloneMode() && DatasourceConfiguration.isEmbeddedStorage();
}
private void loadSetting() {
try {
setNotifyConnectTimeout(Integer.parseInt(EnvUtil.getProperty(PropertiesConstant.NOTIFY_CONNECT_TIMEOUT,

View File

@ -16,27 +16,25 @@
package com.alibaba.nacos.config.server.controller;
import com.alibaba.nacos.api.model.v2.Result;
import com.alibaba.nacos.common.constant.HttpHeaderConsts;
import com.alibaba.nacos.common.http.param.MediaType;
import com.alibaba.nacos.common.utils.JacksonUtils;
import com.alibaba.nacos.config.server.constant.Constants;
import com.alibaba.nacos.config.server.model.CacheItem;
import com.alibaba.nacos.config.server.model.ConfigInfoBetaWrapper;
import com.alibaba.nacos.config.server.model.ConfigInfoTagWrapper;
import com.alibaba.nacos.config.server.model.ConfigInfoWrapper;
import com.alibaba.nacos.config.server.service.ConfigCacheService;
import com.alibaba.nacos.config.server.service.LongPollingService;
import com.alibaba.nacos.config.server.service.dump.disk.ConfigDiskServiceFactory;
import com.alibaba.nacos.config.server.service.dump.disk.ConfigRocksDbDiskService;
import com.alibaba.nacos.config.server.service.repository.ConfigInfoBetaPersistService;
import com.alibaba.nacos.config.server.service.repository.ConfigInfoPersistService;
import com.alibaba.nacos.config.server.service.repository.ConfigInfoTagPersistService;
import com.alibaba.nacos.config.server.utils.GroupKey;
import com.alibaba.nacos.config.server.utils.GroupKey2;
import com.alibaba.nacos.config.server.utils.MD5Util;
import com.alibaba.nacos.config.server.utils.PropertyUtil;
import com.alibaba.nacos.sys.env.EnvUtil;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
@ -50,15 +48,15 @@ import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.util.ReflectionTestUtils;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static com.alibaba.nacos.api.common.Constants.VIPSERVER_TAG;
import static com.alibaba.nacos.config.server.constant.Constants.CONTENT_MD5;
import static com.alibaba.nacos.config.server.utils.RequestUtil.CLIENT_APPNAME_HEADER;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.when;
@RunWith(SpringJUnit4ClassRunner.class)
@ -71,23 +69,11 @@ public class ConfigServletInnerTest {
@Mock
private LongPollingService longPollingService;
@Mock
private ConfigInfoPersistService configInfoPersistService;
@Mock
private ConfigInfoBetaPersistService configInfoBetaPersistService;
@Mock
private ConfigInfoTagPersistService configInfoTagPersistService;
@Mock
private ConfigRocksDbDiskService configRocksDbDiskService;
static MockedStatic<ConfigDiskServiceFactory> configDiskServiceFactoryMockedStatic;
@Rule
public TemporaryFolder tempFolder = new TemporaryFolder();
MockedStatic<ConfigCacheService> configCacheServiceMockedStatic;
MockedStatic<PropertyUtil> propertyUtilMockedStatic;
@ -109,7 +95,7 @@ public class ConfigServletInnerTest {
@After
public void after() {
if (configCacheServiceMockedStatic != null) {
configCacheServiceMockedStatic.close();
}
@ -150,158 +136,196 @@ public class ConfigServletInnerTest {
}
@Test
public void testDoGetConfigV1() throws Exception {
public void testDoGetConfigV1Beta() throws Exception {
configCacheServiceMockedStatic.when(() -> ConfigCacheService.tryReadLock(anyString())).thenReturn(1);
configCacheServiceMockedStatic.when(() -> ConfigCacheService.tryConfigReadLock(anyString())).thenReturn(1);
// isBeta: true
//mock cache item isBeta
CacheItem cacheItem = new CacheItem("test");
cacheItem.setBeta(true);
List<String> ips4Beta = new ArrayList<>();
ips4Beta.add("localhost");
cacheItem.setIps4Beta(ips4Beta);
cacheItem.initBetaCacheIfEmpty();
configCacheServiceMockedStatic.when(() -> ConfigCacheService.getContentCache(anyString()))
cacheItem.getConfigCacheBeta().setEncryptedDataKey("betaKey1234567");
cacheItem.getConfigCacheBeta().setMd5Utf8("md52345Beta");
String dataId = "testDataId135";
String group = "group23";
String tenant = "tenant234";
configCacheServiceMockedStatic.when(
() -> ConfigCacheService.getContentCache(GroupKey.getKeyTenant(dataId, group, tenant)))
.thenReturn(cacheItem);
// if direct read is true
propertyUtilMockedStatic.when(PropertyUtil::isDirectRead).thenReturn(true);
ConfigInfoBetaWrapper configInfoBetaWrapper = new ConfigInfoBetaWrapper();
configInfoBetaWrapper.setDataId("test");
configInfoBetaWrapper.setGroup("test");
configInfoBetaWrapper.setContent("isBeta:true, direct read: true");
when(configInfoBetaPersistService.findConfigInfo4Beta(anyString(), anyString(), anyString())).thenReturn(
configInfoBetaWrapper);
MockHttpServletRequest request = new MockHttpServletRequest();
request.setRemoteAddr("localhost:8080");
request.addHeader(CLIENT_APPNAME_HEADER, "test");
MockHttpServletResponse response = new MockHttpServletResponse();
String actualValue = configServletInner.doGetConfig(request, response, "test", "test", "test", "", "true",
String mockBetaContent = "content3456543";
when(configRocksDbDiskService.getBetaContent(dataId, group, tenant)).thenReturn(mockBetaContent);
String actualValue = configServletInner.doGetConfig(request, response, dataId, group, tenant, "", "true",
"localhost");
Assert.assertEquals(HttpServletResponse.SC_OK + "", actualValue);
Assert.assertEquals("true", response.getHeader("isBeta"));
Assert.assertEquals("isBeta:true, direct read: true", response.getContentAsString());
// if direct read is false
propertyUtilMockedStatic.when(PropertyUtil::isDirectRead).thenReturn(false);
File file = tempFolder.newFile("test.txt");
when(configRocksDbDiskService.getBetaContent("test", "test", "test")).thenReturn(
"isBeta:true, direct read: false");
response = new MockHttpServletResponse();
actualValue = configServletInner.doGetConfig(request, response, "test", "test", "test", "", "true",
"localhost");
Assert.assertEquals(HttpServletResponse.SC_OK + "", actualValue);
Assert.assertEquals("true", response.getHeader("isBeta"));
Assert.assertEquals("isBeta:true, direct read: false", response.getContentAsString());
Assert.assertEquals("md52345Beta", response.getHeader(CONTENT_MD5));
Assert.assertEquals("betaKey1234567", response.getHeader("Encrypted-Data-Key"));
Assert.assertEquals(mockBetaContent, response.getContentAsString());
}
/**
* test get config of tag.
*
* @throws Exception exception.
*/
@Test
public void testDoGetConfigV2() throws Exception {
public void testDoGetConfigV1Tag() throws Exception {
configCacheServiceMockedStatic.when(() -> ConfigCacheService.tryReadLock(anyString())).thenReturn(1);
String dataId = "dataId123455";
String group = "group";
String tenant = "tenant";
configCacheServiceMockedStatic.when(
() -> ConfigCacheService.tryConfigReadLock(GroupKey2.getKey(dataId, group, tenant))).thenReturn(1);
// isBeta: false
//mock cache item with tag.
CacheItem cacheItem = new CacheItem("test");
cacheItem.setBeta(false);
List<String> ips4Beta = new ArrayList<>();
ips4Beta.add("localhost");
cacheItem.setIps4Beta(ips4Beta);
cacheItem.initConfigTagsIfEmpty("auto-tag-test");
String autoTag = "auto-tag-test";
cacheItem.initConfigTagsIfEmpty(autoTag);
cacheItem.getConfigCacheTags().get(autoTag).setEncryptedDataKey("autoTagkey");
cacheItem.getConfigCacheTags().get(autoTag).setMd5Utf8("md5autotag11");
long autoTagTs = System.currentTimeMillis();
cacheItem.getConfigCacheTags().get(autoTag).setLastModifiedTs(autoTagTs);
String specificTag = "specificTag";
cacheItem.initConfigTagsIfEmpty(specificTag);
cacheItem.getConfigCacheTags().get(specificTag).setEncryptedDataKey("specificTagkey");
cacheItem.getConfigCacheTags().get(specificTag).setMd5Utf8("md5specificTag11");
long specificTs = System.currentTimeMillis();
cacheItem.getConfigCacheTags().get(specificTag).setLastModifiedTs(specificTs);
configCacheServiceMockedStatic.when(() -> ConfigCacheService.getContentCache(anyString()))
configCacheServiceMockedStatic.when(
() -> ConfigCacheService.getContentCache(GroupKey2.getKey(dataId, group, tenant)))
.thenReturn(cacheItem);
// if tag is blank and direct read is true
propertyUtilMockedStatic.when(PropertyUtil::isDirectRead).thenReturn(true);
ConfigInfoWrapper configInfoWrapper = new ConfigInfoWrapper();
configInfoWrapper.setDataId("test");
configInfoWrapper.setGroup("test");
configInfoWrapper.setContent("tag is blank and direct read is true");
when(configInfoPersistService.findConfigInfo(anyString(), anyString(), anyString())).thenReturn(
configInfoWrapper);
//test auto tag.
MockHttpServletRequest request = new MockHttpServletRequest();
request.setRemoteAddr("localhost:8080");
request.addHeader(CLIENT_APPNAME_HEADER, "test");
request.addHeader(VIPSERVER_TAG, autoTag);
MockHttpServletResponse response = new MockHttpServletResponse();
String actualValue = configServletInner.doGetConfig(request, response, "test", "test", "test", "", "true",
String autoTagContent = "1234566autotag";
Mockito.when(configRocksDbDiskService.getTagContent(dataId, group, tenant, autoTag)).thenReturn(autoTagContent);
String actualValue = configServletInner.doGetConfig(request, response, dataId, group, tenant, null, "true",
"localhost");
Assert.assertEquals(HttpServletResponse.SC_OK + "", actualValue);
Assert.assertEquals("tag is blank and direct read is true", response.getContentAsString());
Assert.assertEquals(autoTagContent, response.getContentAsString());
Assert.assertEquals("md5autotag11", response.getHeader(CONTENT_MD5));
Assert.assertEquals("autoTagkey", response.getHeader("Encrypted-Data-Key"));
// if tag is blank and direct read is false
propertyUtilMockedStatic.when(PropertyUtil::isDirectRead).thenReturn(false);
//test for specific tag. has higher propority than auto tag.
response = new MockHttpServletResponse();
when(configRocksDbDiskService.getContent("test", "test", "test")).thenReturn(
"tag is blank and direct read is false");
actualValue = configServletInner.doGetConfig(request, response, "test", "test", "test", "", "true",
String specificTagContent = "1234566autotag";
when(configRocksDbDiskService.getTagContent(dataId, group, tenant, specificTag)).thenReturn(specificTagContent);
actualValue = configServletInner.doGetConfig(request, response, dataId, group, tenant, specificTag, "true",
"localhost");
Assert.assertEquals(HttpServletResponse.SC_OK + "", actualValue);
Assert.assertEquals("tag is blank and direct read is false", response.getContentAsString());
Assert.assertEquals(specificTagContent, response.getContentAsString());
Assert.assertEquals("md5specificTag11", response.getHeader(CONTENT_MD5));
Assert.assertEquals("specificTagkey", response.getHeader("Encrypted-Data-Key"));
// if tag is not blank and direct read is true
propertyUtilMockedStatic.when(PropertyUtil::isDirectRead).thenReturn(true);
ConfigInfoTagWrapper configInfoTagWrapper = new ConfigInfoTagWrapper();
configInfoTagWrapper.setDataId("test");
configInfoTagWrapper.setGroup("test");
configInfoTagWrapper.setContent("tag is not blank and direct read is true");
when(configInfoTagPersistService.findConfigInfo4Tag(anyString(), anyString(), anyString(),
anyString())).thenReturn(configInfoTagWrapper);
// test for specific tag ,not exist
when(configRocksDbDiskService.getTagContent(dataId, group, tenant, "auto-tag-test-not-exist")).thenReturn(null);
response = new MockHttpServletResponse();
actualValue = configServletInner.doGetConfig(request, response, "test", "test", "test", "test", "true",
"localhost");
Assert.assertEquals(HttpServletResponse.SC_OK + "", actualValue);
Assert.assertEquals("tag is not blank and direct read is true", response.getContentAsString());
// if tag is not blank and direct read is false
propertyUtilMockedStatic.when(PropertyUtil::isDirectRead).thenReturn(false);
response = new MockHttpServletResponse();
when(configRocksDbDiskService.getTagContent("test", "test", "test", "testTag")).thenReturn(
"tag is not blank and direct read is true");
actualValue = configServletInner.doGetConfig(request, response, "test", "test", "test", "testTag", "true",
"localhost");
Assert.assertEquals(HttpServletResponse.SC_OK + "", actualValue);
Assert.assertEquals("tag is not blank and direct read is true", response.getContentAsString());
// if use auto tag and direct read is true
propertyUtilMockedStatic.when(PropertyUtil::isDirectRead).thenReturn(true);
request.addHeader("Vipserver-Tag", "auto-tag-test");
configInfoTagWrapper.setContent("auto tag mode and direct read is true");
when(configInfoTagPersistService.findConfigInfo4Tag(anyString(), anyString(), anyString(),
eq("auto-tag-test"))).thenReturn(configInfoTagWrapper);
response = new MockHttpServletResponse();
actualValue = configServletInner.doGetConfig(request, response, "test", "test", "test", "", "true",
"localhost");
Assert.assertEquals(HttpServletResponse.SC_OK + "", actualValue);
Assert.assertEquals("auto tag mode and direct read is true", response.getContentAsString());
// if use auto tag and direct read is false
propertyUtilMockedStatic.when(PropertyUtil::isDirectRead).thenReturn(false);
when(configRocksDbDiskService.getTagContent("test", "test", "test", "auto-tag-test")).thenReturn(
"use auto tag and direct read is false");
response = new MockHttpServletResponse();
actualValue = configServletInner.doGetConfig(request, response, "test", "test", "test", "", "true",
"localhost");
Assert.assertEquals(HttpServletResponse.SC_OK + "", actualValue);
Assert.assertEquals("use auto tag and direct read is false", response.getContentAsString());
actualValue = configServletInner.doGetConfig(request, response, dataId, group, tenant,
"auto-tag-test-not-exist", "true", "localhost");
Assert.assertEquals(HttpServletResponse.SC_NOT_FOUND + "", actualValue);
Assert.assertEquals("config data not exist\n", response.getContentAsString());
}
@Test
public void testDoGetConfigV3() throws Exception {
public void testDoGetConfigFormal() throws Exception {
String dataId = "dataId1234552333";
String group = "group";
String tenant = "tenant";
configCacheServiceMockedStatic.when(
() -> ConfigCacheService.tryConfigReadLock(GroupKey2.getKey(dataId, group, tenant))).thenReturn(1);
// if lockResult equals 0
configCacheServiceMockedStatic.when(() -> ConfigCacheService.tryReadLock(anyString())).thenReturn(0);
//mock cache item .
CacheItem cacheItem = new CacheItem("test");
cacheItem.setBeta(false);
String md5 = "md5wertyui";
String content = "content345678";
cacheItem.getConfigCache().setMd5Utf8(md5);
long ts = System.currentTimeMillis();
cacheItem.getConfigCache().setLastModifiedTs(ts);
cacheItem.getConfigCache().setEncryptedDataKey("key2345678");
configCacheServiceMockedStatic.when(
() -> ConfigCacheService.getContentCache(GroupKey.getKeyTenant(dataId, group, tenant)))
.thenReturn(cacheItem);
MockHttpServletRequest request = new MockHttpServletRequest();
MockHttpServletResponse response = new MockHttpServletResponse();
when(configRocksDbDiskService.getContent(dataId, group, tenant)).thenReturn(content);
String actualValue = configServletInner.doGetConfig(request, response, dataId, group, tenant, null, "true",
"localhost");
Assert.assertEquals(content, response.getContentAsString());
Assert.assertEquals(HttpServletResponse.SC_OK + "", actualValue);
Assert.assertEquals(md5, response.getHeader(CONTENT_MD5));
Assert.assertEquals("key2345678", response.getHeader("Encrypted-Data-Key"));
}
@Test
public void testDoGetConfigFormalV2() throws Exception {
String dataId = "dataId1234552333V2";
String group = "group";
String tenant = "tenant";
configCacheServiceMockedStatic.when(
() -> ConfigCacheService.tryConfigReadLock(GroupKey2.getKey(dataId, group, tenant))).thenReturn(1);
//mock cache item .
CacheItem cacheItem = new CacheItem("test");
cacheItem.setBeta(false);
String md5 = "md5wertyui";
String content = "content345678";
cacheItem.getConfigCache().setMd5Utf8(md5);
long ts = System.currentTimeMillis();
cacheItem.getConfigCache().setLastModifiedTs(ts);
cacheItem.getConfigCache().setEncryptedDataKey("key2345678");
configCacheServiceMockedStatic.when(
() -> ConfigCacheService.getContentCache(GroupKey.getKeyTenant(dataId, group, tenant)))
.thenReturn(cacheItem);
MockHttpServletRequest request = new MockHttpServletRequest();
MockHttpServletResponse response = new MockHttpServletResponse();
when(configRocksDbDiskService.getContent(dataId, group, tenant)).thenReturn(content);
String actualValue = configServletInner.doGetConfig(request, response, dataId, group, tenant, null, "true",
"localhost", true);
Assert.assertEquals(JacksonUtils.toJson(Result.success(content)), response.getContentAsString());
Assert.assertEquals(HttpServletResponse.SC_OK + "", actualValue);
Assert.assertEquals(md5, response.getHeader(CONTENT_MD5));
Assert.assertEquals("key2345678", response.getHeader("Encrypted-Data-Key"));
Assert.assertEquals(MediaType.APPLICATION_JSON, response.getHeader(HttpHeaderConsts.CONTENT_TYPE));
}
@Test
public void testDoGetConfigNotExist() throws Exception {
// if lockResult equals 0,cache item not exist.
configCacheServiceMockedStatic.when(() -> ConfigCacheService.tryConfigReadLock(anyString())).thenReturn(0);
MockHttpServletRequest request = new MockHttpServletRequest();
MockHttpServletResponse response = new MockHttpServletResponse();
String actualValue = configServletInner.doGetConfig(request, response, "test", "test", "test", "test", "true",
"localhost");
Assert.assertEquals(HttpServletResponse.SC_NOT_FOUND + "", actualValue);
configCacheServiceMockedStatic.when(
() -> ConfigCacheService.getContentCache(GroupKey2.getKey("test", "test", "test")))
.thenReturn(new CacheItem(GroupKey2.getKey("test", "test", "test")));
// if lockResult less than 0
configCacheServiceMockedStatic.when(() -> ConfigCacheService.tryReadLock(anyString())).thenReturn(-1);
configCacheServiceMockedStatic.when(() -> ConfigCacheService.tryConfigReadLock(anyString())).thenReturn(-1);
actualValue = configServletInner.doGetConfig(request, response, "test", "test", "test", "test", "true",
"localhost");
Assert.assertEquals(HttpServletResponse.SC_CONFLICT + "", actualValue);

View File

@ -22,15 +22,9 @@ import com.alibaba.nacos.api.remote.request.RequestMeta;
import com.alibaba.nacos.common.utils.MD5Utils;
import com.alibaba.nacos.config.server.model.CacheItem;
import com.alibaba.nacos.config.server.model.ConfigCache;
import com.alibaba.nacos.config.server.model.ConfigInfoBetaWrapper;
import com.alibaba.nacos.config.server.model.ConfigInfoTagWrapper;
import com.alibaba.nacos.config.server.model.ConfigInfoWrapper;
import com.alibaba.nacos.config.server.service.ConfigCacheService;
import com.alibaba.nacos.config.server.service.dump.disk.ConfigDiskServiceFactory;
import com.alibaba.nacos.config.server.service.dump.disk.ConfigRocksDbDiskService;
import com.alibaba.nacos.config.server.service.repository.ConfigInfoBetaPersistService;
import com.alibaba.nacos.config.server.service.repository.ConfigInfoPersistService;
import com.alibaba.nacos.config.server.service.repository.ConfigInfoTagPersistService;
import com.alibaba.nacos.config.server.utils.GroupKey2;
import com.alibaba.nacos.config.server.utils.PropertyUtil;
import com.alibaba.nacos.sys.env.EnvUtil;
@ -39,7 +33,6 @@ import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockedStatic;
import org.mockito.Mockito;
import org.mockito.junit.MockitoJUnitRunner;
@ -49,6 +42,7 @@ import java.io.IOException;
import java.util.Arrays;
import static com.alibaba.nacos.api.common.Constants.VIPSERVER_TAG;
import static com.alibaba.nacos.api.config.remote.response.ConfigQueryResponse.CONFIG_NOT_FOUND;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.when;
@ -57,15 +51,6 @@ public class ConfigQueryRequestHandlerTest {
private ConfigQueryRequestHandler configQueryRequestHandler;
@Mock
private ConfigInfoPersistService configInfoPersistService;
@Mock
private ConfigInfoTagPersistService configInfoTagPersistService;
@Mock
private ConfigInfoBetaPersistService configInfoBetaPersistService;
static MockedStatic<ConfigCacheService> configCacheServiceMockedStatic;
static MockedStatic<PropertyUtil> propertyUtilMockedStatic;
@ -76,6 +61,8 @@ public class ConfigQueryRequestHandlerTest {
String group = "group" + System.currentTimeMillis();
String tenant = "tenant" + System.currentTimeMillis();
String content = "content" + System.currentTimeMillis();
@After
@ -92,64 +79,25 @@ public class ConfigQueryRequestHandlerTest {
configCacheServiceMockedStatic = Mockito.mockStatic(ConfigCacheService.class);
propertyUtilMockedStatic = Mockito.mockStatic(PropertyUtil.class);
configDiskServiceFactoryMockedStatic = Mockito.mockStatic(ConfigDiskServiceFactory.class);
configQueryRequestHandler = new ConfigQueryRequestHandler(configInfoPersistService, configInfoTagPersistService,
configInfoBetaPersistService);
configQueryRequestHandler = new ConfigQueryRequestHandler();
final String groupKey = GroupKey2.getKey(dataId, group, "");
when(ConfigCacheService.tryReadLock(groupKey)).thenReturn(1);
when(ConfigCacheService.tryConfigReadLock(groupKey)).thenReturn(1);
propertyUtilMockedStatic.when(PropertyUtil::getMaxContent).thenReturn(1024 * 1000);
}
/**
* get normal config from direct read.
*
* @throws Exception Exception.
*/
@Test
public void testGetNormalDirectRead() throws Exception {
final String groupKey = GroupKey2.getKey(dataId, group, "");
String content = "content_from_directreadÄãºÃ" + System.currentTimeMillis();
ConfigRocksDbDiskService configRocksDbDiskService = Mockito.mock(ConfigRocksDbDiskService.class);
when(ConfigDiskServiceFactory.getInstance()).thenReturn(configRocksDbDiskService);
when(PropertyUtil.isDirectRead()).thenReturn(true);
CacheItem cacheItem = new CacheItem(groupKey);
cacheItem.getConfigCache().setMd5Gbk(MD5Utils.md5Hex(content, "GBK"));
cacheItem.getConfigCache().setMd5Utf8(MD5Utils.md5Hex(content, "UTF-8"));
when(ConfigCacheService.getContentCache(eq(groupKey))).thenReturn(cacheItem);
ConfigQueryRequest configQueryRequest = new ConfigQueryRequest();
configQueryRequest.setDataId(dataId);
configQueryRequest.setGroup(group);
RequestMeta requestMeta = new RequestMeta();
requestMeta.setClientIp("127.0.0.1");
ConfigInfoWrapper configInfoBase = new ConfigInfoWrapper();
configInfoBase.setDataId(dataId);
configInfoBase.setGroup(group);
configInfoBase.setContent(content);
when(configInfoPersistService.findConfigInfo(eq(dataId), eq(group), eq(null))).thenReturn(configInfoBase);
ConfigQueryResponse response = configQueryRequestHandler.handle(configQueryRequest, requestMeta);
Assert.assertEquals(content, response.getContent());
Assert.assertEquals(MD5Utils.md5Hex(content, "UTF-8"), response.getMd5());
Assert.assertFalse(response.isBeta());
Assert.assertNull(response.getTag());
}
/**
* get normal config from local disk.
*
* @throws Exception Exception.
*/
@Test
public void testGetNormalNotDirectRead() throws Exception {
public void testGetNormal() throws Exception {
final String groupKey = GroupKey2.getKey(dataId, group, "");
String content = "content_from_notdirectreadÄãºÃ" + System.currentTimeMillis();
ConfigRocksDbDiskService configRocksDbDiskService = Mockito.mock(ConfigRocksDbDiskService.class);
when(ConfigDiskServiceFactory.getInstance()).thenReturn(configRocksDbDiskService);
when(PropertyUtil.isDirectRead()).thenReturn(false);
CacheItem cacheItem = new CacheItem(groupKey);
cacheItem.getConfigCache().setMd5Gbk(MD5Utils.md5Hex(content, "GBK"));
@ -182,12 +130,11 @@ public class ConfigQueryRequestHandlerTest {
* @throws Exception Exception.
*/
@Test
public void testGetBetaNotDirectRead() throws Exception {
public void testGetBeta() throws Exception {
final String groupKey = GroupKey2.getKey(dataId, group, "");
ConfigRocksDbDiskService configRocksDbDiskService = Mockito.mock(ConfigRocksDbDiskService.class);
when(ConfigDiskServiceFactory.getInstance()).thenReturn(configRocksDbDiskService);
when(PropertyUtil.isDirectRead()).thenReturn(false);
CacheItem cacheItem = new CacheItem(groupKey);
cacheItem.initBetaCacheIfEmpty();
@ -217,57 +164,6 @@ public class ConfigQueryRequestHandlerTest {
}
/**
* get beta config from direct read.
*
* @throws Exception Exception.
*/
@Test
public void testGetBetaDirectRead() throws Exception {
final String groupKey = GroupKey2.getKey(dataId, group, "");
ConfigRocksDbDiskService configRocksDbDiskService = Mockito.mock(ConfigRocksDbDiskService.class);
when(ConfigDiskServiceFactory.getInstance()).thenReturn(configRocksDbDiskService);
when(PropertyUtil.isDirectRead()).thenReturn(true);
CacheItem cacheItem = new CacheItem(groupKey);
cacheItem.initBetaCacheIfEmpty();
String content = "content_from_beta_directreadÄãºÃ" + System.currentTimeMillis();
cacheItem.getConfigCacheBeta().setMd5Gbk(MD5Utils.md5Hex(content, "GBK"));
cacheItem.getConfigCacheBeta().setMd5Utf8(MD5Utils.md5Hex(content, "UTF-8"));
cacheItem.getConfigCacheBeta().setEncryptedDataKey("key_testGetBeta_DirectRead");
cacheItem.setBeta(true);
cacheItem.setIps4Beta(Arrays.asList("127.0.0.1"));
when(ConfigCacheService.getContentCache(eq(groupKey))).thenReturn(cacheItem);
ConfigQueryRequest configQueryRequest = new ConfigQueryRequest();
configQueryRequest.setDataId(dataId);
configQueryRequest.setGroup(group);
RequestMeta requestMeta = new RequestMeta();
requestMeta.setClientIp("127.0.0.1");
//mock direct read.
ConfigInfoBetaWrapper configInfoBase = new ConfigInfoBetaWrapper();
configInfoBase.setDataId(dataId);
configInfoBase.setGroup(group);
configInfoBase.setContent(content);
when(configInfoBetaPersistService.findConfigInfo4Beta(eq(dataId), eq(group), eq(null))).thenReturn(
configInfoBase);
ConfigQueryResponse response = configQueryRequestHandler.handle(configQueryRequest, requestMeta);
//check content&md5
Assert.assertEquals(content, response.getContent());
Assert.assertEquals(MD5Utils.md5Hex(content, "UTF-8"), response.getMd5());
Assert.assertEquals("key_testGetBeta_DirectRead", response.getEncryptedDataKey());
//check flags.
Assert.assertTrue(response.isBeta());
Assert.assertNull(response.getTag());
}
/**
* get tag config ,but not found.
*
@ -277,11 +173,10 @@ public class ConfigQueryRequestHandlerTest {
public void testGetTagNotFound() throws Exception {
final String groupKey = GroupKey2.getKey(dataId, group, "");
String content = "content_from_tag_directreadÄãºÃ" + System.currentTimeMillis();
String content = "content_from_tag_withtagÄãºÃ" + System.currentTimeMillis();
ConfigRocksDbDiskService configRocksDbDiskService = Mockito.mock(ConfigRocksDbDiskService.class);
when(ConfigDiskServiceFactory.getInstance()).thenReturn(configRocksDbDiskService);
when(PropertyUtil.isDirectRead()).thenReturn(true);
CacheItem cacheItem = new CacheItem(groupKey);
cacheItem.getConfigCache().setMd5Gbk(MD5Utils.md5Hex(content, "GBK"));
cacheItem.getConfigCache().setMd5Utf8(MD5Utils.md5Hex(content, "UTF-8"));
@ -294,21 +189,17 @@ public class ConfigQueryRequestHandlerTest {
configQueryRequest.setGroup(group);
String specificTag = "specific_tag";
configQueryRequest.setTag(specificTag);
String autoTag = "specific_tag";
String autoTag = "auto_tag111";
configQueryRequest.putHeader(VIPSERVER_TAG, autoTag);
RequestMeta requestMeta = new RequestMeta();
requestMeta.setClientIp("127.0.0.1");
//mock direct read.
when(configInfoTagPersistService.findConfigInfo4Tag(eq(dataId), eq(group), eq(null),
eq(specificTag))).thenReturn(null);
ConfigQueryResponse response = configQueryRequestHandler.handle(configQueryRequest, requestMeta);
//check content&md5
Assert.assertNull(response.getContent());
Assert.assertNull(response.getMd5());
System.out.println(response.getMessage());
Assert.assertEquals(response.getErrorCode(), ConfigQueryResponse.CONFIG_NOT_FOUND);
Assert.assertEquals(response.getErrorCode(), CONFIG_NOT_FOUND);
Assert.assertNull(response.getEncryptedDataKey());
//check flags.
@ -317,79 +208,18 @@ public class ConfigQueryRequestHandlerTest {
}
/**
* get tag config from direct read.
*
* @throws Exception Exception.
*/
@Test
public void testGetTagDirectRead() throws Exception {
final String groupKey = GroupKey2.getKey(dataId, group, "");
ConfigRocksDbDiskService configRocksDbDiskService = Mockito.mock(ConfigRocksDbDiskService.class);
when(ConfigDiskServiceFactory.getInstance()).thenReturn(configRocksDbDiskService);
when(PropertyUtil.isDirectRead()).thenReturn(true);
CacheItem cacheItem = new CacheItem(groupKey);
String content = "content_from_tag_directreadÄãºÃ" + System.currentTimeMillis();
cacheItem.getConfigCache().setMd5Gbk(MD5Utils.md5Hex(content, "GBK"));
cacheItem.getConfigCache().setEncryptedDataKey("key_testGetTag_DirectRead");
cacheItem.initConfigTagsIfEmpty();
ConfigCache configCacheTag = new ConfigCache();
String tagContent = "content_from_specific_tag_directreadÄãºÃ" + System.currentTimeMillis();
configCacheTag.setMd5Gbk(MD5Utils.md5Hex(tagContent, "GBK"));
configCacheTag.setMd5Utf8(MD5Utils.md5Hex(tagContent, "UTF-8"));
configCacheTag.setEncryptedDataKey("key_testGetTag_DirectRead");
cacheItem.initConfigTagsIfEmpty();
//specific tag to get
String specificTag = "specific_tag";
cacheItem.getConfigCacheTags().put(specificTag, configCacheTag);
when(ConfigCacheService.getContentCache(eq(groupKey))).thenReturn(cacheItem);
ConfigQueryRequest configQueryRequest = new ConfigQueryRequest();
configQueryRequest.setDataId(dataId);
configQueryRequest.setGroup(group);
configQueryRequest.setTag(specificTag);
//just for compare.
String autoTag = "specific_tag";
configQueryRequest.putHeader(VIPSERVER_TAG, autoTag);
RequestMeta requestMeta = new RequestMeta();
requestMeta.setClientIp("127.0.0.1");
//mock direct read.
ConfigInfoTagWrapper configInfoBase = new ConfigInfoTagWrapper();
configInfoBase.setDataId(dataId);
configInfoBase.setGroup(group);
configInfoBase.setContent(tagContent);
configInfoBase.setMd5(MD5Utils.md5Hex(tagContent, "UTF-8"));
when(configInfoTagPersistService.findConfigInfo4Tag(eq(dataId), eq(group), eq(null),
eq(specificTag))).thenReturn(configInfoBase);
ConfigQueryResponse response = configQueryRequestHandler.handle(configQueryRequest, requestMeta);
//check content&md5
Assert.assertEquals(tagContent, response.getContent());
Assert.assertEquals("key_testGetTag_DirectRead", response.getEncryptedDataKey());
Assert.assertEquals(MD5Utils.md5Hex(tagContent, "UTF-8"), response.getMd5());
//check flags.
Assert.assertFalse(response.isBeta());
Assert.assertEquals(response.getTag(), specificTag);
}
/**
* get tag config from local disk.
*
* @throws Exception Exception.
*/
@Test
public void testGetTagNotDirectRead() throws Exception {
public void testGetTagWithTag() throws Exception {
final String groupKey = GroupKey2.getKey(dataId, group, "");
String content = "content_from_tag_notdirectreadÄãºÃ" + System.currentTimeMillis();
ConfigRocksDbDiskService configRocksDbDiskService = Mockito.mock(ConfigRocksDbDiskService.class);
when(ConfigDiskServiceFactory.getInstance()).thenReturn(configRocksDbDiskService);
when(PropertyUtil.isDirectRead()).thenReturn(false);
CacheItem cacheItem = new CacheItem(groupKey);
cacheItem.getConfigCache().setMd5Gbk(MD5Utils.md5Hex(content, "GBK"));
@ -438,15 +268,12 @@ public class ConfigQueryRequestHandlerTest {
* @throws Exception Exception.
*/
@Test
public void testGetTagAutoTagNotDirectRead() throws Exception {
public void testGetTagAutoTag() throws Exception {
final String groupKey = GroupKey2.getKey(dataId, group, "");
String content = "content_from_tag_notdirectreadÄãºÃ" + System.currentTimeMillis();
ConfigRocksDbDiskService configRocksDbDiskService = Mockito.mock(ConfigRocksDbDiskService.class);
when(ConfigDiskServiceFactory.getInstance()).thenReturn(configRocksDbDiskService);
when(PropertyUtil.isDirectRead()).thenReturn(false);
//just for compare.
CacheItem cacheItem = new CacheItem(groupKey);
cacheItem.getConfigCache().setMd5Gbk(MD5Utils.md5Hex(content, "GBK"));
@ -484,59 +311,47 @@ public class ConfigQueryRequestHandlerTest {
}
/**
* get tag config of auto tag from direct read.
* get normal config from local disk.
*
* @throws Exception Exception.
*/
@Test
public void testGetTagAutoTagDirectRead() throws Exception {
public void testGetConfigNotExistAndConflict() throws Exception {
final String groupKey = GroupKey2.getKey(dataId, group, "");
String content = "content_from_tag_directreadÄãºÃ" + System.currentTimeMillis();
ConfigRocksDbDiskService configRocksDbDiskService = Mockito.mock(ConfigRocksDbDiskService.class);
when(ConfigDiskServiceFactory.getInstance()).thenReturn(configRocksDbDiskService);
when(PropertyUtil.isDirectRead()).thenReturn(true);
CacheItem cacheItem = new CacheItem(groupKey);
cacheItem.getConfigCache().setMd5Gbk(MD5Utils.md5Hex(content, "GBK"));
cacheItem.getConfigCache().setMd5Utf8(MD5Utils.md5Hex(content, "UTF-8"));
ConfigCache configCacheTag = new ConfigCache();
String tagContent = "content_from_specific_tag_directreadÄãºÃ" + System.currentTimeMillis();
configCacheTag.setMd5Gbk(MD5Utils.md5Hex(tagContent, "GBK"));
configCacheTag.setMd5Utf8(MD5Utils.md5Hex(tagContent, "UTF-8"));
configCacheTag.setEncryptedDataKey("key_testGetTag_AutoTag_DirectRead");
cacheItem.initConfigTagsIfEmpty();
//just for compare.
String autoTag = "auto_tag";
cacheItem.getConfigCacheTags().put(autoTag, configCacheTag);
when(ConfigCacheService.getContentCache(eq(groupKey))).thenReturn(cacheItem);
String dataId = "dataId" + System.currentTimeMillis();
String group = "group" + System.currentTimeMillis();
String tenant = "tenant" + System.currentTimeMillis();
//test config not exist
configCacheServiceMockedStatic.when(
() -> ConfigCacheService.tryConfigReadLock(GroupKey2.getKey(dataId, group, tenant))).thenReturn(0);
final String groupKey = GroupKey2.getKey(dataId, group, tenant);
when(ConfigCacheService.getContentCache(eq(groupKey))).thenReturn(null);
ConfigQueryRequest configQueryRequest = new ConfigQueryRequest();
configQueryRequest.setDataId(dataId);
configQueryRequest.setGroup(group);
configQueryRequest.setTag(autoTag);
configQueryRequest.putHeader(VIPSERVER_TAG, autoTag);
configQueryRequest.setTenant(tenant);
RequestMeta requestMeta = new RequestMeta();
requestMeta.setClientIp("127.0.0.1");
//mock direct read.
ConfigInfoTagWrapper configInfoBase = new ConfigInfoTagWrapper();
configInfoBase.setDataId(dataId);
configInfoBase.setGroup(group);
configInfoBase.setContent(tagContent);
when(configInfoTagPersistService.findConfigInfo4Tag(eq(dataId), eq(group), eq(null), eq(autoTag))).thenReturn(
configInfoBase);
ConfigQueryResponse response = configQueryRequestHandler.handle(configQueryRequest, requestMeta);
//check content&md5
Assert.assertEquals(tagContent, response.getContent());
Assert.assertEquals(MD5Utils.md5Hex(tagContent, "UTF-8"), response.getMd5());
Assert.assertEquals("key_testGetTag_AutoTag_DirectRead", response.getEncryptedDataKey());
//check flags.
Assert.assertEquals(CONFIG_NOT_FOUND, response.getErrorCode());
Assert.assertEquals(null, response.getContent());
Assert.assertEquals(null, response.getMd5());
Assert.assertFalse(response.isBeta());
Assert.assertEquals(response.getTag(), autoTag);
Assert.assertNull(response.getTag());
//test config conflict
when(ConfigCacheService.getContentCache(eq(groupKey))).thenReturn(new CacheItem(groupKey));
configCacheServiceMockedStatic.when(
() -> ConfigCacheService.tryConfigReadLock(GroupKey2.getKey(dataId, group, tenant))).thenReturn(-1);
ConfigQueryResponse responseConflict = configQueryRequestHandler.handle(configQueryRequest, requestMeta);
Assert.assertEquals(ConfigQueryResponse.CONFIG_QUERY_CONFLICT, responseConflict.getErrorCode());
Assert.assertEquals(null, responseConflict.getContent());
Assert.assertEquals(null, responseConflict.getMd5());
Assert.assertFalse(responseConflict.isBeta());
Assert.assertNull(responseConflict.getTag());
}

View File

@ -23,6 +23,7 @@ import com.alibaba.nacos.config.server.service.dump.disk.ConfigDiskService;
import com.alibaba.nacos.config.server.service.dump.disk.ConfigDiskServiceFactory;
import com.alibaba.nacos.config.server.utils.GroupKey2;
import com.alibaba.nacos.config.server.utils.PropertyUtil;
import com.alibaba.nacos.config.server.utils.SimpleReadWriteLock;
import com.alibaba.nacos.sys.env.EnvUtil;
import org.junit.After;
import org.junit.Assert;
@ -32,12 +33,15 @@ import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockedStatic;
import org.mockito.Mockito;
import org.mockito.stubbing.OngoingStubbing;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import java.io.IOException;
import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
@ -312,4 +316,44 @@ public class ConfigCacheServiceTest {
Assert.assertNull(configCacheTags);
}
@Test
public void testTryConfigReadLock() throws Exception {
String dataId = "123testTryConfigReadLock";
String group = "1234";
String tenant = "1234";
CacheItem cacheItem = Mockito.mock(CacheItem.class);
SimpleReadWriteLock lock = Mockito.mock(SimpleReadWriteLock.class);
Mockito.when(cacheItem.getRwLock()).thenReturn(lock);
String groupKey = GroupKey2.getKey(dataId, group, tenant);
Field cache1 = ConfigCacheService.class.getDeclaredField("CACHE");
cache1.setAccessible(true);
ConcurrentHashMap<String, CacheItem> cache = (ConcurrentHashMap<String, CacheItem>) cache1.get(null);
cache.put(groupKey, cacheItem);
// lock ==0,not exist
int readLock = ConfigCacheService.tryConfigReadLock(groupKey + "3245");
Assert.assertEquals(0, readLock);
//lock == 1 , success get lock
Mockito.when(lock.tryReadLock()).thenReturn(true);
int readLockSuccess = ConfigCacheService.tryConfigReadLock(groupKey);
Assert.assertEquals(1, readLockSuccess);
//lock ==-1 fail after spin all times;
OngoingStubbing<Boolean> when = Mockito.when(lock.tryReadLock());
for (int i = 0; i < 10; i++) {
when = when.thenReturn(false);
}
int readLockFail = ConfigCacheService.tryConfigReadLock(groupKey);
Assert.assertEquals(-1, readLockFail);
//lock ==1 success after serval spin times;
OngoingStubbing<Boolean> when2 = Mockito.when(lock.tryReadLock());
for (int i = 0; i < 5; i++) {
when2 = when2.thenReturn(false);
}
when2.thenReturn(true);
int readLockSuccessAfterRetry = ConfigCacheService.tryConfigReadLock(groupKey);
Assert.assertEquals(1, readLockSuccessAfterRetry);
}
}

View File

@ -51,8 +51,8 @@ public class EncryptionHandler {
return Pair.with("", content);
}
Optional<String> algorithmName = parseAlgorithmName(dataId);
Optional<EncryptionPluginService> optional = algorithmName
.flatMap(EncryptionPluginManager.instance()::findEncryptionService);
Optional<EncryptionPluginService> optional = algorithmName.flatMap(
EncryptionPluginManager.instance()::findEncryptionService);
if (!optional.isPresent()) {
LOGGER.warn("[EncryptionHandler] [encryptHandler] No encryption program with the corresponding name found");
return Pair.with("", content);
@ -73,14 +73,14 @@ public class EncryptionHandler {
*/
public static Pair<String, String> decryptHandler(String dataId, String secretKey, String content) {
if (!checkCipher(dataId)) {
return Pair.with("", content);
return Pair.with(secretKey, content);
}
Optional<String> algorithmName = parseAlgorithmName(dataId);
Optional<EncryptionPluginService> optional = algorithmName
.flatMap(EncryptionPluginManager.instance()::findEncryptionService);
Optional<EncryptionPluginService> optional = algorithmName.flatMap(
EncryptionPluginManager.instance()::findEncryptionService);
if (!optional.isPresent()) {
LOGGER.warn("[EncryptionHandler] [decryptHandler] No encryption program with the corresponding name found");
return Pair.with("", content);
return Pair.with(secretKey, content);
}
EncryptionPluginService encryptionPluginService = optional.get();
String decryptSecretKey = encryptionPluginService.decryptSecretKey(secretKey);