[ISSUE #11253]To fix the triggering of the listener upon failover con… (#11254)

* [ISSUE #11253]To fix the triggering of the listener upon failover content changes.

* [ISSUE #11255]Update style.

* [ISSUE #11255]Fix UdpConnectorTest#testContainAck.
This commit is contained in:
阿魁 2023-10-23 13:48:54 +08:00 committed by GitHub
parent 0e6b5faf4f
commit 086be0386b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 110 additions and 66 deletions

View File

@ -93,7 +93,7 @@ public class CacheData {
LOGGER.info("nacos.cache.data.init.snapshot = {} ", initSnapshot); LOGGER.info("nacos.cache.data.init.snapshot = {} ", initSnapshot);
} }
private final String envName; public final String envName;
private final ConfigFilterChainManager configFilterChainManager; private final ConfigFilterChainManager configFilterChainManager;
@ -124,13 +124,13 @@ public class CacheData {
/** /**
* local cache change timestamp. * local cache change timestamp.
*/ */
private volatile AtomicLong lastModifiedTs = new AtomicLong(0); private final AtomicLong lastModifiedTs = new AtomicLong(0);
/** /**
* notify change flag,for notify&sync concurrent control. 1.reset to false if starting to sync with server. 2.update * notify change flag,for notify&sync concurrent control. 1.reset to false if starting to sync with server. 2.update
* to true if receive config change notification. * to true if receive config change notification.
*/ */
private volatile AtomicBoolean receiveNotifyChanged = new AtomicBoolean(false); private final AtomicBoolean receiveNotifyChanged = new AtomicBoolean(false);
private int taskId; private int taskId;
@ -139,7 +139,7 @@ public class CacheData {
/** /**
* if is cache data md5 sync with the server. * if is cache data md5 sync with the server.
*/ */
private volatile AtomicBoolean isConsistentWithServer = new AtomicBoolean(); private final AtomicBoolean isConsistentWithServer = new AtomicBoolean();
/** /**
* if is cache data is discard,need to remove. * if is cache data is discard,need to remove.

View File

@ -36,8 +36,6 @@ import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.api.remote.RemoteConstants; import com.alibaba.nacos.api.remote.RemoteConstants;
import com.alibaba.nacos.api.remote.request.Request; import com.alibaba.nacos.api.remote.request.Request;
import com.alibaba.nacos.api.remote.response.Response; import com.alibaba.nacos.api.remote.response.Response;
import com.alibaba.nacos.common.remote.client.Connection;
import com.alibaba.nacos.plugin.auth.api.RequestResource;
import com.alibaba.nacos.client.config.common.GroupKey; import com.alibaba.nacos.client.config.common.GroupKey;
import com.alibaba.nacos.client.config.filter.impl.ConfigFilterChainManager; import com.alibaba.nacos.client.config.filter.impl.ConfigFilterChainManager;
import com.alibaba.nacos.client.config.filter.impl.ConfigResponse; import com.alibaba.nacos.client.config.filter.impl.ConfigResponse;
@ -55,6 +53,7 @@ import com.alibaba.nacos.common.notify.Event;
import com.alibaba.nacos.common.notify.NotifyCenter; import com.alibaba.nacos.common.notify.NotifyCenter;
import com.alibaba.nacos.common.notify.listener.Subscriber; import com.alibaba.nacos.common.notify.listener.Subscriber;
import com.alibaba.nacos.common.remote.ConnectionType; import com.alibaba.nacos.common.remote.ConnectionType;
import com.alibaba.nacos.common.remote.client.Connection;
import com.alibaba.nacos.common.remote.client.ConnectionEventListener; import com.alibaba.nacos.common.remote.client.ConnectionEventListener;
import com.alibaba.nacos.common.remote.client.RpcClient; import com.alibaba.nacos.common.remote.client.RpcClient;
import com.alibaba.nacos.common.remote.client.RpcClientFactory; import com.alibaba.nacos.common.remote.client.RpcClientFactory;
@ -66,10 +65,12 @@ import com.alibaba.nacos.common.utils.MD5Utils;
import com.alibaba.nacos.common.utils.StringUtils; import com.alibaba.nacos.common.utils.StringUtils;
import com.alibaba.nacos.common.utils.ThreadUtils; import com.alibaba.nacos.common.utils.ThreadUtils;
import com.alibaba.nacos.common.utils.VersionUtils; import com.alibaba.nacos.common.utils.VersionUtils;
import com.alibaba.nacos.plugin.auth.api.RequestResource;
import com.google.gson.Gson; import com.google.gson.Gson;
import com.google.gson.JsonObject; import com.google.gson.JsonObject;
import org.slf4j.Logger; import org.slf4j.Logger;
import java.io.File;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
@ -123,11 +124,11 @@ public class ClientWorker implements Closeable {
private final ConfigFilterChainManager configFilterChainManager; private final ConfigFilterChainManager configFilterChainManager;
private String uuid = UUID.randomUUID().toString(); private final String uuid = UUID.randomUUID().toString();
private long timeout; private long timeout;
private ConfigRpcTransportClient agent; private final ConfigRpcTransportClient agent;
private int taskPenaltyTime; private int taskPenaltyTime;
@ -570,7 +571,7 @@ public class ClientWorker implements Closeable {
private final BlockingQueue<Object> listenExecutebell = new ArrayBlockingQueue<>(1); private final BlockingQueue<Object> listenExecutebell = new ArrayBlockingQueue<>(1);
private Object bellItem = new Object(); private final Object bellItem = new Object();
private long lastAllSyncTime = System.currentTimeMillis(); private long lastAllSyncTime = System.currentTimeMillis();
@ -780,6 +781,8 @@ public class ClientWorker implements Closeable {
synchronized (cache) { synchronized (cache) {
checkLocalConfig(cache);
// check local listeners consistent. // check local listeners consistent.
if (cache.isConsistentWithServer()) { if (cache.isConsistentWithServer()) {
cache.checkListenerMd5(); cache.checkListenerMd5();
@ -788,28 +791,19 @@ public class ClientWorker implements Closeable {
} }
} }
// If local configuration information is used, then skip the processing directly.
if (cache.isUseLocalConfigInfo()) {
continue;
}
if (!cache.isDiscard()) { if (!cache.isDiscard()) {
//get listen config List<CacheData> cacheDatas = listenCachesMap.computeIfAbsent(String.valueOf(cache.getTaskId()),
if (!cache.isUseLocalConfigInfo()) { k -> new LinkedList<>());
List<CacheData> cacheDatas = listenCachesMap.get(String.valueOf(cache.getTaskId()));
if (cacheDatas == null) {
cacheDatas = new LinkedList<>();
listenCachesMap.put(String.valueOf(cache.getTaskId()), cacheDatas);
}
cacheDatas.add(cache); cacheDatas.add(cache);
} else {
} List<CacheData> cacheDatas = removeListenCachesMap.computeIfAbsent(
} else if (cache.isDiscard() && CollectionUtils.isEmpty(cache.getListeners())) { String.valueOf(cache.getTaskId()), k -> new LinkedList<>());
if (!cache.isUseLocalConfigInfo()) {
List<CacheData> cacheDatas = removeListenCachesMap.get(String.valueOf(cache.getTaskId()));
if (cacheDatas == null) {
cacheDatas = new LinkedList<>();
removeListenCachesMap.put(String.valueOf(cache.getTaskId()), cacheDatas);
}
cacheDatas.add(cache); cacheDatas.add(cache);
}
} }
} }
@ -831,6 +825,56 @@ public class ClientWorker implements Closeable {
} }
/**
* Checks and handles local configuration for a given CacheData object. This method evaluates the use of
* failover files for local configuration storage and updates the CacheData accordingly.
*
* @param cacheData The CacheData object to be processed.
*/
public void checkLocalConfig(CacheData cacheData) {
final String dataId = cacheData.dataId;
final String group = cacheData.group;
final String tenant = cacheData.tenant;
final String envName = cacheData.envName;
// Check if a failover file exists for the specified dataId, group, and tenant.
File file = LocalConfigInfoProcessor.getFailoverFile(envName, dataId, group, tenant);
// If not using local config info and a failover file exists, load and use it.
if (!cacheData.isUseLocalConfigInfo() && file.exists()) {
String content = LocalConfigInfoProcessor.getFailover(envName, dataId, group, tenant);
final String md5 = MD5Utils.md5Hex(content, Constants.ENCODE);
cacheData.setUseLocalConfigInfo(true);
cacheData.setLocalConfigInfoVersion(file.lastModified());
cacheData.setContent(content);
LOGGER.warn(
"[{}] [failover-change] failover file created. dataId={}, group={}, tenant={}, md5={}, content={}",
envName, dataId, group, tenant, md5, ContentUtils.truncateContent(content));
return;
}
// If use local config info, but the failover file is deleted, switch back to server config.
if (cacheData.isUseLocalConfigInfo() && !file.exists()) {
cacheData.setUseLocalConfigInfo(false);
LOGGER.warn("[{}] [failover-change] failover file deleted. dataId={}, group={}, tenant={}", envName,
dataId, group, tenant);
return;
}
// When the failover file content changes, indicating a change in local configuration.
if (cacheData.isUseLocalConfigInfo() && file.exists()
&& cacheData.getLocalConfigInfoVersion() != file.lastModified()) {
String content = LocalConfigInfoProcessor.getFailover(envName, dataId, group, tenant);
final String md5 = MD5Utils.md5Hex(content, Constants.ENCODE);
cacheData.setUseLocalConfigInfo(true);
cacheData.setLocalConfigInfoVersion(file.lastModified());
cacheData.setContent(content);
LOGGER.warn(
"[{}] [failover-change] failover file changed. dataId={}, group={}, tenant={}, md5={}, content={}",
envName, dataId, group, tenant, md5, ContentUtils.truncateContent(content));
}
}
private ExecutorService ensureSyncExecutor(String taskId) { private ExecutorService ensureSyncExecutor(String taskId) {
if (!multiTaskExecutor.containsKey(taskId)) { if (!multiTaskExecutor.containsKey(taskId)) {
multiTaskExecutor.put(taskId, multiTaskExecutor.put(taskId,
@ -1180,7 +1224,7 @@ public class ClientWorker implements Closeable {
try { try {
return getOneRunningClient().isRunning(); return getOneRunningClient().isRunning();
} catch (NacosException e) { } catch (NacosException e) {
LOGGER.warn("check server status failed. error={}", e); LOGGER.warn("check server status failed.", e);
return false; return false;
} }
} }

View File

@ -91,7 +91,7 @@ public class UdpConnectorTest {
@Test @Test
public void testContainAck() { public void testContainAck() {
when(ackMap.containsKey(Mockito.anyString())).thenReturn(true); when(ackMap.containsKey("1111")).thenReturn(true);
Assert.assertTrue(udpConnector.containAck("1111")); Assert.assertTrue(udpConnector.containAck("1111"));
} }