change: 缓存清理逻辑调整, 进一步减少内存的占用

This commit is contained in:
2024-05-22 22:11:08 +08:00
parent 74939203ce
commit 2211a6edc0
12 changed files with 81 additions and 42 deletions

1
.gitignore vendored
View File

@@ -12,6 +12,7 @@ target/
### 测试数据 ### ### 测试数据 ###
instances/ instances/
settings.properties settings.properties
logback.xml
### Eclipse ### ### Eclipse ###
.apt_generated .apt_generated

View File

@@ -1,6 +1,6 @@
package com.serliunx.ddns.config; package com.serliunx.ddns.config;
import com.serliunx.ddns.support.Refreshable; import com.serliunx.ddns.core.Refreshable;
/** /**
* 配置信息逻辑定义 * 配置信息逻辑定义

View File

@@ -0,0 +1,23 @@
package com.serliunx.ddns.core;
/**
* 定义一个实体的清理逻辑
* <li> 一般用来清理中间加载过程中所产生的无用对象
*/
@FunctionalInterface
public interface Clearable {
/**
* 执行清理
*/
void clear();
/**
* 实体是否需要执行清理逻辑
* <li> 默认为真
* @return 是否需要执行清理逻辑
*/
default boolean isClearable() {
return true;
}
}

View File

@@ -1,4 +1,4 @@
package com.serliunx.ddns.support; package com.serliunx.ddns.core;
/** /**
* 刷新逻辑 * 刷新逻辑
@@ -12,9 +12,4 @@ public interface Refreshable {
* 刷新(初始化) * 刷新(初始化)
*/ */
void refresh(); void refresh();
/**
* 刷新后逻辑定义, 一般用于资源清理
*/
default void afterRefresh(){}
} }

View File

@@ -1,10 +1,11 @@
package com.serliunx.ddns.core.context; package com.serliunx.ddns.core.context;
import com.serliunx.ddns.constant.InstanceType; import com.serliunx.ddns.constant.InstanceType;
import com.serliunx.ddns.core.Clearable;
import com.serliunx.ddns.core.factory.ListableInstanceFactory; import com.serliunx.ddns.core.factory.ListableInstanceFactory;
import com.serliunx.ddns.core.instance.Instance; import com.serliunx.ddns.core.instance.Instance;
import com.serliunx.ddns.support.Assert; import com.serliunx.ddns.support.Assert;
import com.serliunx.ddns.support.Refreshable; import com.serliunx.ddns.core.Refreshable;
import com.serliunx.ddns.util.ReflectionUtils; import com.serliunx.ddns.util.ReflectionUtils;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@@ -59,9 +60,6 @@ public abstract class AbstractInstanceContext implements InstanceContext, Multip
Set<Instance> builtInstances = buildInstances(instances); Set<Instance> builtInstances = buildInstances(instances);
instanceMap = builtInstances.stream().collect(Collectors.toMap(Instance::getName, i -> i)); instanceMap = builtInstances.stream().collect(Collectors.toMap(Instance::getName, i -> i));
// 调用善后处理钩子函数
afterRefresh();
} }
@Override @Override
@@ -112,10 +110,16 @@ public abstract class AbstractInstanceContext implements InstanceContext, Multip
return listableInstanceFactories; return listableInstanceFactories;
} }
@Override
public void clear() {
if(isClearable())
clear0();
}
/** /**
* 善后工作 * 子类清理逻辑
*/ */
public abstract void afterRefresh(); protected abstract void clear0();
/** /**
* 缓存清理 * 缓存清理
@@ -125,10 +129,11 @@ public abstract class AbstractInstanceContext implements InstanceContext, Multip
&& !cacheInstanceMap.isEmpty()){ && !cacheInstanceMap.isEmpty()){
int size = cacheInstanceMap.size(); int size = cacheInstanceMap.size();
cacheInstanceMap.clear(); cacheInstanceMap.clear();
log.debug("缓存信息清理 => {} 条", size); // 清理实例工厂的缓存信息
listableInstanceFactories.forEach(Clearable::clear);
listableInstanceFactories.clear();
log.info("共清理缓存信息 => {} 条", size);
} }
// 清理实例工厂的缓存信息
listableInstanceFactories.forEach(Refreshable::afterRefresh);
} }
/** /**

View File

@@ -21,7 +21,7 @@ public class FileInstanceContext extends AbstractInstanceContext {
} }
@Override @Override
public void afterRefresh() { protected void clear0() {
clearCache(); clearCache();
} }
} }

View File

@@ -7,8 +7,13 @@ package com.serliunx.ddns.core.context;
*/ */
public class GenericInstanceContext extends AbstractInstanceContext { public class GenericInstanceContext extends AbstractInstanceContext {
@Override @Override
public void afterRefresh() { protected void clear0() {
clearCache(); clearCache();
} }
@Override
public boolean isClearable() {
return false;
}
} }

View File

@@ -1,13 +1,12 @@
package com.serliunx.ddns.core.context; package com.serliunx.ddns.core.context;
import com.serliunx.ddns.core.factory.InstanceFactory; import com.serliunx.ddns.core.factory.InstanceFactory;
import com.serliunx.ddns.support.Refreshable;
/** /**
* @author SerLiunx * @author SerLiunx
* @since 1.0 * @since 1.0
*/ */
public interface InstanceContext extends InstanceFactory, Refreshable { public interface InstanceContext extends InstanceFactory {
@Override @Override
default int getPriority() { default int getPriority() {

View File

@@ -17,12 +17,12 @@ import static com.serliunx.ddns.util.InstanceUtils.validateInstance;
*/ */
public abstract class AbstractInstanceFactory implements InstanceFactory, ListableInstanceFactory { public abstract class AbstractInstanceFactory implements InstanceFactory, ListableInstanceFactory {
private static final Logger log = LoggerFactory.getLogger(AbstractInstanceFactory.class); private final Logger log = LoggerFactory.getLogger(this.getClass());
/** /**
* 实例信息 * 实例信息
*/ */
private Map<String, Instance> instanceMap; protected Map<String, Instance> instanceMap;
@Override @Override
public Instance getInstance(String instanceName) { public Instance getInstance(String instanceName) {
@@ -76,13 +76,9 @@ public abstract class AbstractInstanceFactory implements InstanceFactory, Listab
} }
@Override @Override
public void afterRefresh() { public final void clear() {
if (instanceMap != null if(isClearable() && instanceMap != null)
&& !instanceMap.isEmpty()){ clear0();
int size = instanceMap.size();
instanceMap.clear();
log.debug("缓存信息清理 => {} 条", size);
}
} }
/** /**
@@ -90,4 +86,13 @@ public abstract class AbstractInstanceFactory implements InstanceFactory, Listab
* @return 实例信息 * @return 实例信息
*/ */
protected abstract Set<Instance> load(); protected abstract Set<Instance> load();
/**
* 清理逻辑
*/
protected void clear0(){
final int size = instanceMap.size();
instanceMap.clear();
log.info("缓存信息清理 => {} 条", size);
}
} }

View File

@@ -1,14 +1,15 @@
package com.serliunx.ddns.core.factory; package com.serliunx.ddns.core.factory;
import com.serliunx.ddns.core.Clearable;
import com.serliunx.ddns.core.Priority; import com.serliunx.ddns.core.Priority;
import com.serliunx.ddns.core.instance.Instance; import com.serliunx.ddns.core.instance.Instance;
import com.serliunx.ddns.support.Refreshable; import com.serliunx.ddns.core.Refreshable;
/** /**
* @author SerLiunx * @author SerLiunx
* @since 1.0 * @since 1.0
*/ */
public interface InstanceFactory extends Priority, Comparable<InstanceFactory>, Refreshable { public interface InstanceFactory extends Priority, Comparable<InstanceFactory>, Refreshable, Clearable {
/** /**
* 添加实例 * 添加实例

View File

@@ -2,7 +2,7 @@ package com.serliunx.ddns.core.instance;
import com.serliunx.ddns.constant.InstanceSource; import com.serliunx.ddns.constant.InstanceSource;
import com.serliunx.ddns.constant.InstanceType; import com.serliunx.ddns.constant.InstanceType;
import com.serliunx.ddns.support.Refreshable; import com.serliunx.ddns.core.Refreshable;
/** /**
* @author SerLiunx * @author SerLiunx

View File

@@ -2,6 +2,8 @@ package com.serliunx.ddns.support;
import com.serliunx.ddns.config.Configuration; import com.serliunx.ddns.config.Configuration;
import com.serliunx.ddns.constant.SystemConstants; import com.serliunx.ddns.constant.SystemConstants;
import com.serliunx.ddns.core.Clearable;
import com.serliunx.ddns.core.Refreshable;
import com.serliunx.ddns.core.context.MultipleSourceInstanceContext; import com.serliunx.ddns.core.context.MultipleSourceInstanceContext;
import com.serliunx.ddns.core.instance.Instance; import com.serliunx.ddns.core.instance.Instance;
import com.serliunx.ddns.support.feign.client.IPAddressClient; import com.serliunx.ddns.support.feign.client.IPAddressClient;
@@ -33,7 +35,7 @@ import static com.serliunx.ddns.config.ConfigurationKeys.KEY_THREAD_POOL_CORE_SI
* @author SerLiunx * @author SerLiunx
* @since 1.0 * @since 1.0
*/ */
public final class SystemInitializer implements Refreshable { public final class SystemInitializer implements Refreshable, Clearable {
private static final Logger log = LoggerFactory.getLogger(SystemInitializer.class); private static final Logger log = LoggerFactory.getLogger(SystemInitializer.class);
@@ -79,9 +81,18 @@ public final class SystemInitializer implements Refreshable {
// 运行实例 // 运行实例
runInstances(); runInstances();
// 实例提交后, 清理实例、配置缓存, 因为读取一次就不需要了
clear();
log.info("初始化完成!"); log.info("初始化完成!");
} }
@Override
public void clear() {
instanceContext.clear();
instances.clear();
}
public MultipleSourceInstanceContext getInstanceContext() { public MultipleSourceInstanceContext getInstanceContext() {
return instanceContext; return instanceContext;
} }
@@ -90,11 +101,6 @@ public final class SystemInitializer implements Refreshable {
return instances; return instances;
} }
@Override
public void afterRefresh() {
// TODO
}
private void loadInstances() { private void loadInstances() {
instances = instanceContext.getInstances(); instances = instanceContext.getInstances();
log.info("载入 {} 个实例.", instances.size()); log.info("载入 {} 个实例.", instances.size());
@@ -166,7 +172,6 @@ public final class SystemInitializer implements Refreshable {
Runtime.getRuntime().addShutdownHook(new Thread(() -> { Runtime.getRuntime().addShutdownHook(new Thread(() -> {
MDC.put("pid", SystemSupport.getPid()); MDC.put("pid", SystemSupport.getPid());
log.info("程序正在关闭中, 可能需要一定时间."); log.info("程序正在关闭中, 可能需要一定时间.");
afterRefresh();
scheduledThreadPoolExecutor.shutdown(); scheduledThreadPoolExecutor.shutdown();
log.info("已关闭."); log.info("已关闭.");
}, "DDNS-ShutDownHook")); }, "DDNS-ShutDownHook"));