change: 日常小调整.

This commit is contained in:
2024-06-30 09:46:34 +08:00
parent 850b5b80ad
commit e76fd2915a
16 changed files with 103 additions and 49 deletions

View File

@@ -18,13 +18,13 @@ public final class ManagerLite {
init(); init();
} }
private static SystemInitializer init() { private static void init() {
SystemInitializer systemInitializer = SystemInitializer SystemInitializer systemInitializer = SystemInitializer
.configurer() .configurer()
.clearCache(false)
.configuration(new PropertiesConfiguration(SystemConstants.USER_SETTINGS_PROPERTIES_PATH)) .configuration(new PropertiesConfiguration(SystemConstants.USER_SETTINGS_PROPERTIES_PATH))
.instanceContext(new FileInstanceContext()) .instanceContext(new FileInstanceContext())
.done(); .done();
systemInitializer.refresh(); systemInitializer.refresh();
return systemInitializer;
} }
} }

View File

@@ -1,8 +1,8 @@
package com.serliunx.ddns.support.feign.client; package com.serliunx.ddns.client;
import com.serliunx.ddns.client.entity.IPAddressResponse;
import com.serliunx.ddns.support.feign.JacksonDecoder; import com.serliunx.ddns.support.feign.JacksonDecoder;
import com.serliunx.ddns.support.feign.JacksonEncoder; import com.serliunx.ddns.support.feign.JacksonEncoder;
import com.serliunx.ddns.support.feign.client.entity.IPAddressResponse;
import feign.Feign; import feign.Feign;
import feign.Logger; import feign.Logger;
import feign.RequestLine; import feign.RequestLine;

View File

@@ -1,4 +1,4 @@
package com.serliunx.ddns.support.feign.client.entity; package com.serliunx.ddns.client.entity;
/** /**
* IP地址查询响应 * IP地址查询响应

View File

@@ -14,15 +14,15 @@ import java.util.Map;
* @since 2024/5/15 * @since 2024/5/15
*/ */
public final class InstanceClasses { public final class InstanceClasses {
private InstanceClasses(){throw new UnsupportedOperationException();} private InstanceClasses(){throw new UnsupportedOperationException();}
private static final Map<InstanceType, Class<? extends Instance>> instanceTypeMap = private static final Map<InstanceType, Class<? extends Instance>> instanceTypeMap = new HashMap<>();
new HashMap<InstanceType, Class<? extends Instance>>() {
{ static {
put(InstanceType.ALI_YUN, AliyunInstance.class); instanceTypeMap.put(InstanceType.ALI_YUN, AliyunInstance.class);
put(InstanceType.TENCENT_CLOUD, TencentInstance.class); instanceTypeMap.put(InstanceType.TENCENT_CLOUD, TencentInstance.class);
} }
};
public static Class<? extends Instance> match(InstanceType type) { public static Class<? extends Instance> match(InstanceType type) {
return instanceTypeMap.get(type); return instanceTypeMap.get(type);

View File

@@ -25,7 +25,7 @@ import static com.serliunx.ddns.util.InstanceUtils.validateInstance;
*/ */
public abstract class AbstractInstanceContext implements InstanceContext, MultipleSourceInstanceContext { public abstract class AbstractInstanceContext implements InstanceContext, MultipleSourceInstanceContext {
private static final Logger log = LoggerFactory.getLogger(AbstractInstanceContext.class); private final Logger log = LoggerFactory.getLogger(this.getClass());
private final Set<ListableInstanceFactory> listableInstanceFactories = new HashSet<>(); private final Set<ListableInstanceFactory> listableInstanceFactories = new HashSet<>();
@@ -63,9 +63,7 @@ public abstract class AbstractInstanceContext implements InstanceContext, Multip
Set<Instance> instances = new HashSet<>(); Set<Instance> instances = new HashSet<>();
// 高优先级的实例工厂会覆盖低优先级实例工厂所加载的实例 // 高优先级的实例工厂会覆盖低优先级实例工厂所加载的实例
listableInstanceFactories.stream() getSortedListableInstanceFactories().forEach(f -> instances.addAll(f.getInstances()));
.sorted()
.forEach(f -> instances.addAll(f.getInstances()));
// 初次载入 // 初次载入
cacheInstanceMap = new HashMap<>(instances.stream().collect(Collectors.toMap(Instance::getName, i -> i))); cacheInstanceMap = new HashMap<>(instances.stream().collect(Collectors.toMap(Instance::getName, i -> i)));
@@ -86,10 +84,11 @@ public abstract class AbstractInstanceContext implements InstanceContext, Multip
instanceLock.lock(); instanceLock.lock();
String name = instance.getName(); String name = instance.getName();
Instance instanceExists = instanceMap.get(name); Instance instanceExists = instanceMap.get(name);
if (instanceExists != null) if (instanceExists != null) {
throw new InstanceExistsException("该实例已存在!", name, instanceExists); throw new InstanceExistsException("该实例已存在!", name, instanceExists);
else } else {
instanceMap.put(name, instance); instanceMap.put(name, instance);
}
}catch (Exception e){ }catch (Exception e){
throw new RuntimeException(e); throw new RuntimeException(e);
}finally { }finally {
@@ -146,7 +145,7 @@ public abstract class AbstractInstanceContext implements InstanceContext, Multip
protected void clearCache() { protected void clearCache() {
if (cacheInstanceMap != null if (cacheInstanceMap != null
&& !cacheInstanceMap.isEmpty()){ && !cacheInstanceMap.isEmpty()){
int size = cacheInstanceMap.size(); final int size = cacheInstanceMap.size();
cacheInstanceMap.clear(); cacheInstanceMap.clear();
// 清理实例工厂的缓存信息 // 清理实例工厂的缓存信息
listableInstanceFactories.forEach(Clearable::clear); listableInstanceFactories.forEach(Clearable::clear);

View File

@@ -3,7 +3,10 @@ package com.serliunx.ddns.core.context;
import com.serliunx.ddns.core.factory.InstanceFactory; import com.serliunx.ddns.core.factory.InstanceFactory;
import com.serliunx.ddns.core.factory.ListableInstanceFactory; import com.serliunx.ddns.core.factory.ListableInstanceFactory;
import java.util.Collections;
import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.stream.Collectors;
/** /**
* 多数据源的实例容器, 将多种实例来源汇聚到一起 * 多数据源的实例容器, 将多种实例来源汇聚到一起
@@ -26,4 +29,18 @@ public interface MultipleSourceInstanceContext extends InstanceContext, Listable
* @return 实例工厂列表 * @return 实例工厂列表
*/ */
Set<ListableInstanceFactory> getListableInstanceFactories(); Set<ListableInstanceFactory> getListableInstanceFactories();
/**
* 获取当前实例容器下所有实例工厂(已排序)
* @return 已排序的实例工厂
*/
default List<ListableInstanceFactory> getSortedListableInstanceFactories() {
Set<ListableInstanceFactory> listableInstanceFactories = getListableInstanceFactories();
if (listableInstanceFactories == null || listableInstanceFactories.isEmpty())
return Collections.emptyList();
return listableInstanceFactories.stream()
.sorted()
.collect(Collectors.toList());
}
} }

View File

@@ -74,6 +74,11 @@ public abstract class AbstractInstanceFactory implements InstanceFactory, Listab
clear0(); clear0();
} }
@Override
public String toString() {
return getClass().getSimpleName() + "(priority: " + getPriority() + ")";
}
/** /**
* 交由子类去加载实例信息 * 交由子类去加载实例信息
* @return 实例信息 * @return 实例信息

View File

@@ -26,6 +26,16 @@ public abstract class FileInstanceFactory extends AbstractInstanceFactory {
this.instanceDir = instanceDir; this.instanceDir = instanceDir;
} }
@Override
public int getPriority() {
return 256;
}
@Override
public String toString() {
return getClass().getSimpleName() + "(instanceDir: " + instanceDir + ", priority: " + getPriority() + ")";
}
@Override @Override
protected Set<Instance> load() { protected Set<Instance> load() {
Set<File> files = loadFiles(); Set<File> files = loadFiles();
@@ -38,11 +48,6 @@ public abstract class FileInstanceFactory extends AbstractInstanceFactory {
return Collections.emptySet(); return Collections.emptySet();
} }
@Override
public int getPriority() {
return 256;
}
/** /**
* 交由具体的子类去加载实例, 比如: json格式的实例信息、xml格式的实例信息 * 交由具体的子类去加载实例, 比如: json格式的实例信息、xml格式的实例信息
* @param file 文件信息 * @param file 文件信息

View File

@@ -96,13 +96,15 @@ public class YamlFileInstanceFactory extends FileInstanceFactory {
f.set(instance, Enum.valueOf((Class<? extends Enum>) clazz, (String) value)); f.set(instance, Enum.valueOf((Class<? extends Enum>) clazz, (String) value));
continue; continue;
} }
if (value != null) if (value != null) {
f.set(instance, value); f.set(instance, value);
}
} catch (IllegalAccessException e) { } catch (IllegalAccessException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} } finally {
f.setAccessible(false); f.setAccessible(false);
} }
}
return instance; return instance;
} }
} }

View File

@@ -23,7 +23,7 @@ import static com.serliunx.ddns.constant.SystemConstants.XML_ROOT_INSTANCE_NAME;
@JacksonXmlRootElement(localName = XML_ROOT_INSTANCE_NAME) @JacksonXmlRootElement(localName = XML_ROOT_INSTANCE_NAME)
public abstract class AbstractInstance implements Instance { public abstract class AbstractInstance implements Instance {
private static final Logger log = LoggerFactory.getLogger(AbstractInstance.class); private final Logger log = LoggerFactory.getLogger(this.getClass());
/** /**
* 实例名称 * 实例名称

View File

@@ -14,6 +14,7 @@ public final class Configurer {
private Configuration configuration; private Configuration configuration;
private MultipleSourceInstanceContext instanceContext; private MultipleSourceInstanceContext instanceContext;
private boolean clearCache;
Configurer(){} Configurer(){}
@@ -29,8 +30,13 @@ public final class Configurer {
return this; return this;
} }
public Configurer clearCache(boolean clearCache) {
this.clearCache = clearCache;
return this;
}
public SystemInitializer done() { public SystemInitializer done() {
Assert.notNull(configuration, instanceContext); Assert.notNull(configuration, instanceContext);
return new SystemInitializer(configuration, instanceContext); return new SystemInitializer(configuration, instanceContext, clearCache);
} }
} }

View File

@@ -39,8 +39,9 @@ public final class NetworkContextHolder {
} }
public static String getIpAddress() { public static String getIpAddress() {
if(IP_ADDRESS != null) if(IP_ADDRESS != null) {
return IP_ADDRESS; return IP_ADDRESS;
}
try { try {
if(!IP_CONTEXT_WAIT_LATCH.await(IP_CONTEXT_TIME_OUT, TimeUnit.SECONDS)) { if(!IP_CONTEXT_WAIT_LATCH.await(IP_CONTEXT_TIME_OUT, TimeUnit.SECONDS)) {
log.error("IP地址获取超时."); log.error("IP地址获取超时.");

View File

@@ -6,8 +6,8 @@ import com.serliunx.ddns.core.Clearable;
import com.serliunx.ddns.core.Refreshable; 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.client.IPAddressClient;
import com.serliunx.ddns.support.feign.client.entity.IPAddressResponse; import com.serliunx.ddns.client.entity.IPAddressResponse;
import com.serliunx.ddns.thread.TaskThreadFactory; import com.serliunx.ddns.thread.TaskThreadFactory;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@@ -40,14 +40,20 @@ public final class SystemInitializer implements Refreshable, Clearable {
private final Configuration configuration; private final Configuration configuration;
private final MultipleSourceInstanceContext instanceContext; private final MultipleSourceInstanceContext instanceContext;
private final boolean clearCache;
private ScheduledThreadPoolExecutor scheduledThreadPoolExecutor; private ScheduledThreadPoolExecutor scheduledThreadPoolExecutor;
private Set<Instance> instances; private Set<Instance> instances;
private final Map<String, ScheduledFuture<?>> runningInstances = new HashMap<>(64); private final Map<String, ScheduledFuture<?>> runningInstances = new HashMap<>(64);
SystemInitializer(Configuration configuration, MultipleSourceInstanceContext instanceContext) { SystemInitializer(Configuration configuration, MultipleSourceInstanceContext instanceContext, boolean clearCache) {
this.configuration = configuration; this.configuration = configuration;
this.instanceContext = instanceContext; this.instanceContext = instanceContext;
this.clearCache = clearCache;
}
SystemInitializer(Configuration configuration, MultipleSourceInstanceContext instanceContext) {
this(configuration, instanceContext, true);
} }
public static Configurer configurer() { public static Configurer configurer() {
@@ -80,8 +86,10 @@ public final class SystemInitializer implements Refreshable, Clearable {
// 运行实例 // 运行实例
runInstances(); runInstances();
// 实例提交后, 清理实例、配置缓存, 因为读取一次就不需要了 // 清理实例、配置缓存, 正常情况下读取一次就不需要了
if (clearCache) {
clear(); clear();
}
log.info("初始化完成!"); log.info("初始化完成!");
InstanceContextHolder.clearAdditional(); InstanceContextHolder.clearAdditional();
} }
@@ -120,9 +128,10 @@ public final class SystemInitializer implements Refreshable, Clearable {
byte[] buffer = new byte[1024]; byte[] buffer = new byte[1024];
int bytesRead; int bytesRead;
if (inputStream != null) { if (inputStream != null) {
while ((bytesRead = inputStream.read(buffer)) != -1) while ((bytesRead = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, bytesRead); outputStream.write(buffer, 0, bytesRead);
} }
}
outputStream.close(); outputStream.close();
} catch (Exception e) { } catch (Exception e) {
log.error("文件 {} 解压失败!, 原因: {}", resourceName, e.getMessage()); log.error("文件 {} 解压失败!, 原因: {}", resourceName, e.getMessage());
@@ -140,7 +149,7 @@ public final class SystemInitializer implements Refreshable, Clearable {
} }
// 初始化实例 // 初始化实例
i.refresh(); i.refresh();
ScheduledFuture<?> future = scheduledThreadPoolExecutor.scheduleWithFixedDelay(i, 0, ScheduledFuture<?> future = scheduledThreadPoolExecutor.scheduleWithFixedDelay(i, 5,
i.getInterval(), TimeUnit.SECONDS); i.getInterval(), TimeUnit.SECONDS);
runningInstances.put(i.getName(), future); runningInstances.put(i.getName(), future);
log.info("{}({})已启动, 运行周期 {} 秒.", i.getName(), i.getType(), i.getInterval()); log.info("{}({})已启动, 运行周期 {} 秒.", i.getName(), i.getType(), i.getInterval());
@@ -187,15 +196,15 @@ public final class SystemInitializer implements Refreshable, Clearable {
boolean result = scheduledThreadPoolExecutor.awaitTermination(5, TimeUnit.SECONDS); boolean result = scheduledThreadPoolExecutor.awaitTermination(5, TimeUnit.SECONDS);
if (result) { if (result) {
log.error("线程池无法在正常的时间范围内关闭, 将强制关闭线程池!"); log.error("线程池无法在正常的时间范围内关闭, 将强制关闭线程池!");
if (!scheduledThreadPoolExecutor.isShutdown()) if (!scheduledThreadPoolExecutor.isShutdown()) {
scheduledThreadPoolExecutor.shutdownNow(); scheduledThreadPoolExecutor.shutdownNow();
} }
}
} catch (InterruptedException e) { } catch (InterruptedException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} } finally {
instances.clear(); instances.clear();
runningInstances.clear(); runningInstances.clear();
} }
}
} }

View File

@@ -34,9 +34,8 @@ public class ContextTest {
@Test @Test
public void testFileContext(){ public void testFileContext(){
MultipleSourceInstanceContext context = new FileInstanceContext(); FileInstanceContext context = new FileInstanceContext();
context.getSortedListableInstanceFactories().forEach(System.out::println);
context.getInstances().forEach(System.out::println);
} }
@Test @Test

View File

@@ -1,9 +1,15 @@
package com.serliunx.ddns.test; package com.serliunx.ddns.test;
import com.serliunx.ddns.constant.InstanceType;
import com.serliunx.ddns.constant.SystemConstants; import com.serliunx.ddns.constant.SystemConstants;
import com.serliunx.ddns.core.factory.InstanceFactory;
import com.serliunx.ddns.core.factory.ListableInstanceFactory;
import com.serliunx.ddns.core.factory.YamlFileInstanceFactory; import com.serliunx.ddns.core.factory.YamlFileInstanceFactory;
import com.serliunx.ddns.core.instance.Instance;
import org.junit.Test; import org.junit.Test;
import java.util.Map;
/** /**
* @author SerLiunx * @author SerLiunx
* @since 1.0 * @since 1.0
@@ -12,9 +18,14 @@ public class FactoryTest {
@Test @Test
public void testYamlFileFactory() { public void testYamlFileFactory() {
YamlFileInstanceFactory factory = new YamlFileInstanceFactory(SystemConstants.USER_INSTANCE_DIR); ListableInstanceFactory factory = new YamlFileInstanceFactory(SystemConstants.USER_INSTANCE_DIR);
factory.refresh(); factory.refresh();
factory.getInstances().forEach(System.out::println); factory.getInstances().forEach(System.out::println);
factory.clear();
Map<String, Instance> instances = factory.getInstanceOfType(InstanceType.TENCENT_CLOUD);
instances.forEach((k, v) -> {
System.out.println(k + ": " + v);
});
} }
} }

View File

@@ -1,6 +1,6 @@
package com.serliunx.ddns.test.support; package com.serliunx.ddns.test.support;
import com.serliunx.ddns.support.feign.client.IPAddressClient; import com.serliunx.ddns.client.IPAddressClient;
import org.junit.Test; import org.junit.Test;
/** /**