use of com.alibaba.nacos.config.server.model.CacheItem in project nacos by alibaba.
the class ConfigServletInner method doGetConfig.
/**
* Execute to get config API.
*/
public String doGetConfig(HttpServletRequest request, HttpServletResponse response, String dataId, String group, String tenant, String tag, String isNotify, String clientIp) throws IOException, ServletException {
boolean notify = false;
if (StringUtils.isNotBlank(isNotify)) {
notify = Boolean.parseBoolean(isNotify);
}
final String groupKey = GroupKey2.getKey(dataId, group, tenant);
String autoTag = request.getHeader("Vipserver-Tag");
String requestIpApp = RequestUtil.getAppName(request);
int lockResult = tryConfigReadLock(groupKey);
final String requestIp = RequestUtil.getRemoteIp(request);
boolean isBeta = false;
boolean isSli = false;
if (lockResult > 0) {
// LockResult > 0 means cacheItem is not null and other thread can`t delete this cacheItem
FileInputStream fis = null;
try {
String md5 = Constants.NULL;
long lastModified = 0L;
CacheItem cacheItem = ConfigCacheService.getContentCache(groupKey);
if (cacheItem.isBeta() && cacheItem.getIps4Beta().contains(clientIp)) {
isBeta = true;
}
final String configType = (null != cacheItem.getType()) ? cacheItem.getType() : FileTypeEnum.TEXT.getFileType();
response.setHeader("Config-Type", configType);
FileTypeEnum fileTypeEnum = FileTypeEnum.getFileTypeEnumByFileExtensionOrFileType(configType);
String contentTypeHeader = fileTypeEnum.getContentType();
response.setHeader(HttpHeaderConsts.CONTENT_TYPE, contentTypeHeader);
File file = null;
ConfigInfoBase configInfoBase = null;
PrintWriter out;
if (isBeta) {
md5 = cacheItem.getMd54Beta();
lastModified = cacheItem.getLastModifiedTs4Beta();
if (PropertyUtil.isDirectRead()) {
configInfoBase = persistService.findConfigInfo4Beta(dataId, group, tenant);
} else {
file = DiskUtil.targetBetaFile(dataId, group, tenant);
}
response.setHeader("isBeta", "true");
} else {
if (StringUtils.isBlank(tag)) {
if (isUseTag(cacheItem, autoTag)) {
if (cacheItem.tagMd5 != null) {
md5 = cacheItem.tagMd5.get(autoTag);
}
if (cacheItem.tagLastModifiedTs != null) {
lastModified = cacheItem.tagLastModifiedTs.get(autoTag);
}
if (PropertyUtil.isDirectRead()) {
configInfoBase = persistService.findConfigInfo4Tag(dataId, group, tenant, autoTag);
} else {
file = DiskUtil.targetTagFile(dataId, group, tenant, autoTag);
}
response.setHeader(com.alibaba.nacos.api.common.Constants.VIPSERVER_TAG, URLEncoder.encode(autoTag, StandardCharsets.UTF_8.displayName()));
} else {
md5 = cacheItem.getMd5();
lastModified = cacheItem.getLastModifiedTs();
if (PropertyUtil.isDirectRead()) {
configInfoBase = persistService.findConfigInfo(dataId, group, tenant);
} else {
file = DiskUtil.targetFile(dataId, group, tenant);
}
if (configInfoBase == null && fileNotExist(file)) {
// 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_NOTFOUND, -1, requestIp, notify);
return get404Result(response);
}
isSli = true;
}
} else {
if (cacheItem.tagMd5 != null) {
md5 = cacheItem.tagMd5.get(tag);
}
if (cacheItem.tagLastModifiedTs != null) {
Long lm = cacheItem.tagLastModifiedTs.get(tag);
if (lm != null) {
lastModified = lm;
}
}
if (PropertyUtil.isDirectRead()) {
configInfoBase = persistService.findConfigInfo4Tag(dataId, group, tenant, tag);
} else {
file = DiskUtil.targetTagFile(dataId, group, tenant, tag);
}
if (configInfoBase == null && fileNotExist(file)) {
// 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_NOTFOUND, -1, requestIp, notify && isSli);
// pullLog.info("[client-get] clientIp={}, {},
// no data",
// new Object[]{clientIp, groupKey});
response.setStatus(HttpServletResponse.SC_NOT_FOUND);
response.getWriter().println("config data not exist");
return HttpServletResponse.SC_NOT_FOUND + "";
}
}
}
response.setHeader(Constants.CONTENT_MD5, md5);
// Disable cache.
response.setHeader("Pragma", "no-cache");
response.setDateHeader("Expires", 0);
response.setHeader("Cache-Control", "no-cache,no-store");
if (PropertyUtil.isDirectRead()) {
response.setDateHeader("Last-Modified", lastModified);
} else {
fis = new FileInputStream(file);
response.setDateHeader("Last-Modified", file.lastModified());
}
if (PropertyUtil.isDirectRead()) {
Pair<String, String> pair = EncryptionHandler.decryptHandler(dataId, configInfoBase.getEncryptedDataKey(), configInfoBase.getContent());
out = response.getWriter();
out.print(pair.getSecond());
out.flush();
out.close();
} else {
String fileContent = IoUtils.toString(fis, Charsets.UTF_8.name());
String encryptedDataKey = cacheItem.getEncryptedDataKey();
Pair<String, String> pair = EncryptionHandler.decryptHandler(dataId, encryptedDataKey, fileContent);
String decryptContent = pair.getSecond();
out = response.getWriter();
out.print(decryptContent);
out.flush();
out.close();
}
LogUtil.PULL_CHECK_LOG.warn("{}|{}|{}|{}", groupKey, requestIp, md5, TimeUtils.getCurrentTimeStr());
final long delayed = System.currentTimeMillis() - lastModified;
// TODO distinguish pull-get && push-get
/*
Otherwise, delayed cannot be used as the basis of push delay directly,
because the delayed value of active get requests is very large.
*/
ConfigTraceService.logPullEvent(dataId, group, tenant, requestIpApp, lastModified, ConfigTraceService.PULL_EVENT_OK, delayed, requestIp, notify && isSli);
} finally {
releaseConfigReadLock(groupKey);
IoUtils.closeQuietly(fis);
}
} else if (lockResult == 0) {
// 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_NOTFOUND, -1, requestIp, notify && isSli);
return get404Result(response);
} else {
PULL_LOG.info("[client-get] clientIp={}, {}, get data during dump", clientIp, groupKey);
response.setStatus(HttpServletResponse.SC_CONFLICT);
response.getWriter().println("requested file is being modified, please try later.");
return HttpServletResponse.SC_CONFLICT + "";
}
return HttpServletResponse.SC_OK + "";
}
use of com.alibaba.nacos.config.server.model.CacheItem in project nacos by alibaba.
the class ConfigQueryRequestHandler method getContext.
private ConfigQueryResponse getContext(ConfigQueryRequest configQueryRequest, RequestMeta meta, boolean notify) throws UnsupportedEncodingException {
String dataId = configQueryRequest.getDataId();
String group = configQueryRequest.getGroup();
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(), configQueryRequest.getTenant());
String autoTag = configQueryRequest.getHeader(com.alibaba.nacos.api.common.Constants.VIPSERVER_TAG);
String requestIpApp = meta.getLabels().get(CLIENT_APPNAME_HEADER);
int lockResult = tryConfigReadLock(groupKey);
boolean isBeta = false;
boolean isSli = false;
if (lockResult > 0) {
// FileInputStream fis = null;
try {
String md5 = Constants.NULL;
long lastModified = 0L;
CacheItem cacheItem = ConfigCacheService.getContentCache(groupKey);
if (cacheItem != null) {
if (cacheItem.isBeta()) {
if (cacheItem.getIps4Beta().contains(clientIp)) {
isBeta = true;
}
}
String configType = cacheItem.getType();
response.setContentType((null != configType) ? configType : "text");
}
File file = null;
ConfigInfoBase configInfoBase = null;
PrintWriter out = null;
if (isBeta) {
md5 = cacheItem.getMd54Beta();
lastModified = cacheItem.getLastModifiedTs4Beta();
if (PropertyUtil.isDirectRead()) {
configInfoBase = persistService.findConfigInfo4Beta(dataId, group, tenant);
} else {
file = DiskUtil.targetBetaFile(dataId, group, tenant);
}
response.setBeta(true);
} else {
if (StringUtils.isBlank(tag)) {
if (isUseTag(cacheItem, autoTag)) {
if (cacheItem != null) {
if (cacheItem.tagMd5 != null) {
md5 = cacheItem.tagMd5.get(autoTag);
}
if (cacheItem.tagLastModifiedTs != null) {
lastModified = cacheItem.tagLastModifiedTs.get(autoTag);
}
}
if (PropertyUtil.isDirectRead()) {
configInfoBase = persistService.findConfigInfo4Tag(dataId, group, tenant, autoTag);
} else {
file = DiskUtil.targetTagFile(dataId, group, tenant, autoTag);
}
response.setTag(URLEncoder.encode(autoTag, Constants.ENCODE));
} else {
md5 = cacheItem.getMd5();
lastModified = cacheItem.getLastModifiedTs();
if (PropertyUtil.isDirectRead()) {
configInfoBase = persistService.findConfigInfo(dataId, group, tenant);
} else {
file = DiskUtil.targetFile(dataId, group, tenant);
}
if (configInfoBase == null && fileNotExist(file)) {
// 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_NOTFOUND, -1, clientIp, false);
// pullLog.info("[client-get] clientIp={}, {},
// no data",
// new Object[]{clientIp, groupKey});
response.setErrorInfo(ConfigQueryResponse.CONFIG_NOT_FOUND, "config data not exist");
return response;
}
}
} else {
if (cacheItem != null) {
if (cacheItem.tagMd5 != null) {
md5 = cacheItem.tagMd5.get(tag);
}
if (cacheItem.tagLastModifiedTs != null) {
Long lm = cacheItem.tagLastModifiedTs.get(tag);
if (lm != null) {
lastModified = lm;
}
}
}
if (PropertyUtil.isDirectRead()) {
configInfoBase = persistService.findConfigInfo4Tag(dataId, group, tenant, tag);
} else {
file = DiskUtil.targetTagFile(dataId, group, tenant, tag);
}
if (configInfoBase == null && fileNotExist(file)) {
// 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_NOTFOUND, -1, clientIp, false);
// pullLog.info("[client-get] clientIp={}, {},
// no data",
// new Object[]{clientIp, groupKey});
response.setErrorInfo(ConfigQueryResponse.CONFIG_NOT_FOUND, "config data not exist");
return response;
}
}
}
response.setMd5(md5);
if (PropertyUtil.isDirectRead()) {
response.setLastModified(lastModified);
response.setContent(configInfoBase.getContent());
response.setEncryptedDataKey(configInfoBase.getEncryptedDataKey());
response.setResultCode(ResponseCode.SUCCESS.getCode());
} else {
// read from file
String content = null;
try {
content = readFileContent(file);
response.setContent(content);
response.setLastModified(lastModified);
response.setResultCode(ResponseCode.SUCCESS.getCode());
if (isBeta) {
response.setEncryptedDataKey(cacheItem.getEncryptedDataKeyBeta());
} else {
response.setEncryptedDataKey(cacheItem.getEncryptedDataKey());
}
} catch (IOException e) {
response.setErrorInfo(ResponseCode.FAIL.getCode(), e.getMessage());
return response;
}
}
LogUtil.PULL_CHECK_LOG.warn("{}|{}|{}|{}", groupKey, clientIp, md5, TimeUtils.getCurrentTimeStr());
final long delayed = System.currentTimeMillis() - lastModified;
// TODO distinguish pull-get && push-get
/*
Otherwise, delayed cannot be used as the basis of push delay directly,
because the delayed value of active get requests is very large.
*/
ConfigTraceService.logPullEvent(dataId, group, tenant, requestIpApp, lastModified, ConfigTraceService.PULL_EVENT_OK, notify ? delayed : -1, clientIp, notify);
} finally {
releaseConfigReadLock(groupKey);
}
} else if (lockResult == 0) {
// 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_NOTFOUND, -1, clientIp, notify);
response.setErrorInfo(ConfigQueryResponse.CONFIG_NOT_FOUND, "config data not exist");
} else {
PULL_LOG.info("[client-get] clientIp={}, {}, get data during dump", clientIp, groupKey);
response.setErrorInfo(ConfigQueryResponse.CONFIG_QUERY_CONFLICT, "requested file is being modified, please try later.");
}
return response;
}
use of com.alibaba.nacos.config.server.model.CacheItem in project nacos by alibaba.
the class ConfigServletInnerTest method testDoGetConfigV2.
@Test
public void testDoGetConfigV2() throws Exception {
final MockedStatic<DiskUtil> diskUtil = Mockito.mockStatic(DiskUtil.class);
final MockedStatic<ConfigCacheService> configCacheService = Mockito.mockStatic(ConfigCacheService.class);
final MockedStatic<PropertyUtil> propertyUtil = Mockito.mockStatic(PropertyUtil.class);
when(ConfigCacheService.tryReadLock(anyString())).thenReturn(1);
// isBeta: false
CacheItem cacheItem = new CacheItem("test");
cacheItem.setBeta(false);
List<String> ips4Beta = new ArrayList<>();
ips4Beta.add("localhost");
cacheItem.setIps4Beta(ips4Beta);
when(ConfigCacheService.getContentCache(anyString())).thenReturn(cacheItem);
// if tag is blank and direct read is true
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(persistService.findConfigInfo(anyString(), anyString(), anyString())).thenReturn(configInfoWrapper);
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", "localhost");
Assert.assertEquals(HttpServletResponse.SC_OK + "", actualValue);
Assert.assertEquals("tag is blank and direct read is true", response.getContentAsString());
// if tag is blank and direct read is false
when(PropertyUtil.isDirectRead()).thenReturn(false);
response = new MockHttpServletResponse();
File file = tempFolder.newFile("test.txt");
when(DiskUtil.targetFile(anyString(), anyString(), anyString())).thenReturn(file);
actualValue = configServletInner.doGetConfig(request, response, "test", "test", "test", "", "true", "localhost");
Assert.assertEquals(HttpServletResponse.SC_OK + "", actualValue);
Assert.assertEquals("", response.getContentAsString());
// if tag is not blank and direct read is true
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(persistService.findConfigInfo4Tag(anyString(), anyString(), anyString(), anyString())).thenReturn(configInfoTagWrapper);
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
when(PropertyUtil.isDirectRead()).thenReturn(false);
response = new MockHttpServletResponse();
when(DiskUtil.targetTagFile(anyString(), anyString(), anyString(), anyString())).thenReturn(file);
actualValue = configServletInner.doGetConfig(request, response, "test", "test", "test", "test", "true", "localhost");
Assert.assertEquals(HttpServletResponse.SC_OK + "", actualValue);
Assert.assertEquals("", response.getContentAsString());
// if use auto tag and direct read is true
when(PropertyUtil.isDirectRead()).thenReturn(true);
Map<String, String> tagMd5 = new HashMap<>();
tagMd5.put("auto-tag-test", "auto-tag-test");
cacheItem.setTagMd5(tagMd5);
request.addHeader("Vipserver-Tag", "auto-tag-test");
configInfoTagWrapper.setContent("auto tag mode and direct read is true");
when(persistService.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
when(PropertyUtil.isDirectRead()).thenReturn(false);
response = new MockHttpServletResponse();
actualValue = configServletInner.doGetConfig(request, response, "test", "test", "test", "", "true", "localhost");
Assert.assertEquals(HttpServletResponse.SC_OK + "", actualValue);
Assert.assertEquals("", response.getContentAsString());
diskUtil.close();
configCacheService.close();
propertyUtil.close();
}
use of com.alibaba.nacos.config.server.model.CacheItem in project nacos by alibaba.
the class ConfigServletInnerTest method testDoGetConfigV1.
@Test
public void testDoGetConfigV1() throws Exception {
final MockedStatic<DiskUtil> diskUtil = Mockito.mockStatic(DiskUtil.class);
final MockedStatic<ConfigCacheService> configCacheService = Mockito.mockStatic(ConfigCacheService.class);
final MockedStatic<PropertyUtil> propertyUtil = Mockito.mockStatic(PropertyUtil.class);
when(ConfigCacheService.tryReadLock(anyString())).thenReturn(1);
// isBeta: true
CacheItem cacheItem = new CacheItem("test");
cacheItem.setBeta(true);
List<String> ips4Beta = new ArrayList<>();
ips4Beta.add("localhost");
cacheItem.setIps4Beta(ips4Beta);
when(ConfigCacheService.getContentCache(anyString())).thenReturn(cacheItem);
// if direct read is true
when(PropertyUtil.isDirectRead()).thenReturn(true);
ConfigInfoBetaWrapper configInfoBetaWrapper = new ConfigInfoBetaWrapper();
configInfoBetaWrapper.setDataId("test");
configInfoBetaWrapper.setGroup("test");
configInfoBetaWrapper.setContent("isBeta:true, direct read: true");
when(persistService.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", "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
when(PropertyUtil.isDirectRead()).thenReturn(false);
File file = tempFolder.newFile("test.txt");
when(DiskUtil.targetBetaFile(anyString(), anyString(), anyString())).thenReturn(file);
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("", response.getContentAsString());
diskUtil.close();
configCacheService.close();
propertyUtil.close();
}
use of com.alibaba.nacos.config.server.model.CacheItem in project nacos by alibaba.
the class ConfigQueryRequestHandlerTest method setUp.
@Before
public void setUp() throws IOException {
EnvUtil.setEnvironment(new StandardEnvironment());
Mockito.mockStatic(ConfigCacheService.class);
Mockito.mockStatic(PropertyUtil.class);
Mockito.mockStatic(FileUtils.class);
Mockito.mockStatic(DiskUtil.class);
ReflectionTestUtils.setField(configQueryRequestHandler, "persistService", persistService);
final String groupKey = GroupKey2.getKey("dataId", "group", "");
when(ConfigCacheService.tryReadLock(groupKey)).thenReturn(1);
when(DiskUtil.targetFile(Mockito.any(), Mockito.any(), Mockito.any())).thenReturn(file);
when(FileUtils.readFileToString(file, ENCODE)).thenReturn("content");
when(file.exists()).thenReturn(true);
CacheItem cacheItem = new CacheItem(groupKey);
cacheItem.setMd5("1");
cacheItem.setLastModifiedTs(1L);
when(ConfigCacheService.getContentCache(Mockito.any())).thenReturn(cacheItem);
}
Aggregations