Skip to content

Commit

Permalink
[ISSUE#12359]Refactoring the historical configuration cleanup strateg…
Browse files Browse the repository at this point in the history
…y with SPI (#12367)

* 历史配置清理逻辑SPI改造

* 添加单元测试

* 单元测试fix

* 单元测试fix

* 优化spi实现

* 优化日志打印
  • Loading branch information
Sunrisea authored Jul 23, 2024
1 parent 197795a commit 7e57781
Show file tree
Hide file tree
Showing 9 changed files with 485 additions and 54 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
/*
* Copyright 1999-2024 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.alibaba.nacos.config.server.service.dump;

import com.alibaba.nacos.config.server.service.repository.HistoryConfigInfoPersistService;
import com.alibaba.nacos.config.server.utils.TimeUtils;
import com.alibaba.nacos.sys.env.EnvUtil;
import com.alibaba.nacos.sys.utils.ApplicationUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.Calendar;

import static com.alibaba.nacos.config.server.utils.LogUtil.FATAL_LOG;

/**
* The type Default history config cleaner.
*
* @author Sunrisea
*/
public class DefaultHistoryConfigCleaner implements HistoryConfigCleaner {

private static final Logger LOGGER = LoggerFactory.getLogger(DefaultHistoryConfigCleaner.class);

private HistoryConfigInfoPersistService historyConfigInfoPersistService;

private int retentionDays = 30;

@Override
public void cleanHistoryConfig() {
Timestamp startTime = getBeforeStamp(TimeUtils.getCurrentTime(), 24 * getRetentionDays());
int pageSize = 1000;
LOGGER.warn("clearConfigHistory, getBeforeStamp:{}, pageSize:{}", startTime, pageSize);
getHistoryConfigInfoPersistService().removeConfigHistory(startTime, pageSize);
}

private HistoryConfigInfoPersistService getHistoryConfigInfoPersistService() {
if (historyConfigInfoPersistService == null) {
historyConfigInfoPersistService = ApplicationUtils.getBean(HistoryConfigInfoPersistService.class);
}
return historyConfigInfoPersistService;
}

private Timestamp getBeforeStamp(Timestamp date, int step) {
Calendar cal = Calendar.getInstance();
cal.setTime(date);
cal.add(Calendar.HOUR_OF_DAY, -step);
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
return Timestamp.valueOf(format.format(cal.getTime()));
}

private int getRetentionDays() {
String val = EnvUtil.getProperty("nacos.config.retention.days");
if (null == val) {
return retentionDays;
}

int tmp = 0;
try {
tmp = Integer.parseInt(val);
if (tmp > 0) {
retentionDays = tmp;
}
} catch (NumberFormatException nfe) {
FATAL_LOG.error("read nacos.config.retention.days wrong", nfe);
}

return retentionDays;
}

@Override
public String getName() {
return "nacos";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@
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.cluster.ServerMemberManager;
import com.alibaba.nacos.core.namespace.repository.NamespacePersistService;
import com.alibaba.nacos.persistence.datasource.DynamicDataSource;
Expand All @@ -54,14 +53,11 @@
import org.slf4j.LoggerFactory;

import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.List;
import java.util.Random;
import java.util.concurrent.TimeUnit;

import static com.alibaba.nacos.config.server.utils.LogUtil.DUMP_LOG;
import static com.alibaba.nacos.config.server.utils.LogUtil.FATAL_LOG;

/**
* Dump data service.
Expand Down Expand Up @@ -194,29 +190,31 @@ void handleConfigDataChange(Event event) {
*/
protected abstract void init() throws Throwable;

void clearConfigHistory() {
LOGGER.warn("clearConfigHistory start");
if (canExecute()) {
try {
Timestamp startTime = getBeforeStamp(TimeUtils.getCurrentTime(), 24 * getRetentionDays());
int pageSize = 1000;
LOGGER.warn("clearConfigHistory, getBeforeStamp:{}, pageSize:{}", startTime, pageSize);
historyConfigInfoPersistService.removeConfigHistory(startTime, pageSize);
} catch (Throwable e) {
LOGGER.error("clearConfigHistory error : {}", e.toString());
}
}

}

/**
* config history clear.
*/
class ConfigHistoryClear implements Runnable {

private HistoryConfigCleaner historyConfigCleaner;

public ConfigHistoryClear(HistoryConfigCleaner historyConfigCleaner) {
this.historyConfigCleaner = historyConfigCleaner;
}

@Override
public void run() {
clearConfigHistory();
LOGGER.warn("clearHistoryConfig get scheduled");
if (canExecute()) {
try {
LOGGER.warn("clearHistoryConfig is enable in current context, try to run cleaner");
historyConfigCleaner.cleanHistoryConfig();
LOGGER.warn("history config cleaner successfully");
} catch (Throwable e) {
LOGGER.error("clearConfigHistory error : {}", e.toString());
}
} else {
LOGGER.warn("clearHistoryConfig is disable in current context");
}
}
}

Expand Down Expand Up @@ -316,7 +314,10 @@ protected void dumpOperate() throws NacosException {

}

ConfigExecutor.scheduleConfigTask(new ConfigHistoryClear(), 10, 10, TimeUnit.MINUTES);
HistoryConfigCleaner cleaner = HistoryConfigCleanerManager.getHistoryConfigCleaner(
HistoryConfigCleanerConfig.getInstance().getActiveHistoryConfigCleaner());
ConfigExecutor.scheduleConfigTask(new ConfigHistoryClear(cleaner), 10, 10, TimeUnit.MINUTES);

} finally {
TimerContext.end(dumpFileContext, LogUtil.DUMP_LOG);
}
Expand All @@ -335,34 +336,6 @@ private void dumpAllConfigInfoOnStartup(DumpAllProcessor dumpAllProcessor) {
}
}

private Timestamp getBeforeStamp(Timestamp date, int step) {
Calendar cal = Calendar.getInstance();
cal.setTime(date);
// before 6 hour
cal.add(Calendar.HOUR_OF_DAY, -step);
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
return Timestamp.valueOf(format.format(cal.getTime()));
}

private int getRetentionDays() {
String val = EnvUtil.getProperty("nacos.config.retention.days");
if (null == val) {
return retentionDays;
}

int tmp = 0;
try {
tmp = Integer.parseInt(val);
if (tmp > 0) {
retentionDays = tmp;
}
} catch (NumberFormatException nfe) {
FATAL_LOG.error("read nacos.config.retention.days wrong", nfe);
}

return retentionDays;
}

/**
* dump operation.
*
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* Copyright 1999-2024 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.alibaba.nacos.config.server.service.dump;

/**
* The interface History config cleaner.
* @author Sunrisea
*/
public interface HistoryConfigCleaner {

/**
* Clean history config.
*/
public void cleanHistoryConfig();

/**
* Gets name.
*
* @return the name
*/
public String getName();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
/*
* Copyright 1999-2024 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.alibaba.nacos.config.server.service.dump;

import com.alibaba.nacos.api.utils.StringUtils;
import com.alibaba.nacos.core.config.AbstractDynamicConfig;
import com.alibaba.nacos.sys.env.EnvUtil;

/**
* The type History config cleaner config.
* @author Sunrisea
*/
public class HistoryConfigCleanerConfig extends AbstractDynamicConfig {

private static final String HISTORY_CONFIG_CLEANER = "historyConfigCleaner";

private static final HistoryConfigCleanerConfig INSTANCE = new HistoryConfigCleanerConfig();

private String activeHistoryConfigCleaner = "nacos";

private HistoryConfigCleanerConfig() {
super(HISTORY_CONFIG_CLEANER);
resetConfig();
}

/**
* Gets instance.
*
* @return the instance
*/
public static HistoryConfigCleanerConfig getInstance() {
return INSTANCE;
}

@Override
protected void getConfigFromEnv() {
activeHistoryConfigCleaner = EnvUtil.getProperty("nacos.config.history.clear.name", String.class, "nacos");
if (StringUtils.isBlank(activeHistoryConfigCleaner)) {
activeHistoryConfigCleaner = "nacos";
}
}

/**
* Gets active history config cleaner.
*
* @return the active history config cleaner
*/
public String getActiveHistoryConfigCleaner() {
return activeHistoryConfigCleaner;
}

/**
* Sets active history config cleaner.
*
* @param activeHistoryConfigCleaner the active history config cleaner
*/
public void setActiveHistoryConfigCleaner(String activeHistoryConfigCleaner) {
this.activeHistoryConfigCleaner = activeHistoryConfigCleaner;
}

@Override
protected String printConfig() {
return "activeHistoryConfigCleaner{ " + "activeHistoryConfigCleaner=" + activeHistoryConfigCleaner + "}";
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/*
* Copyright 1999-2024 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.alibaba.nacos.config.server.service.dump;

import com.alibaba.nacos.common.spi.NacosServiceLoader;

import java.util.HashMap;

/**
* The type History config cleaner manager.
*
* @author Sunrisea
*/
public class HistoryConfigCleanerManager {

private static HashMap<String, HistoryConfigCleaner> historyConfigCleanerMap = new HashMap<String, HistoryConfigCleaner>();

static {
NacosServiceLoader.load(HistoryConfigCleaner.class).forEach(historyConfigCleaner -> {
historyConfigCleanerMap.put(historyConfigCleaner.getName(), historyConfigCleaner);
});
historyConfigCleanerMap.put("nacos", new DefaultHistoryConfigCleaner());
}

/**
* Gets history config cleaner.
*
* @param name the name
* @return the history config cleaner
*/
public static HistoryConfigCleaner getHistoryConfigCleaner(String name) {
return historyConfigCleanerMap.getOrDefault(name, historyConfigCleanerMap.get("nacos"));
}
}
Loading

0 comments on commit 7e57781

Please sign in to comment.